From 12ddaa3806d8f95705cd385eaf40bbf8993529bb Mon Sep 17 00:00:00 2001 From: Oli Evans Date: Mon, 28 Jan 2019 14:09:55 +0000 Subject: [PATCH 001/233] feat: return protocol from getEndpointConfig (#935) The protocol is used to construct the request, and it's useful to be able to check it has been set correctly, so we add it here to he the util.getEndpointConfig() return value. License: MIT Signed-off-by: Oli Evans --- README.md | 2 +- src/util/get-endpoint-config.js | 4 +++- test/util.spec.js | 7 +++++-- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 9c62638e0..4bcc34255 100644 --- a/README.md +++ b/README.md @@ -370,7 +370,7 @@ Complete documentation for these methods is coming with: https://github.com/ipfs > `ipfs.util.getEndpointConfig()` -This returns an object containing the `host` and the `port` +This returns an object containing the `host`, `port` and `protocol` ##### Get libp2p crypto primitives diff --git a/src/util/get-endpoint-config.js b/src/util/get-endpoint-config.js index 7598239ee..a4f0c80e1 100644 --- a/src/util/get-endpoint-config.js +++ b/src/util/get-endpoint-config.js @@ -3,6 +3,8 @@ module.exports = (config) => { return () => ({ host: config.host, - port: config.port + port: config.port, + protocol: config.protocol, + 'api-path': config['api-path'] }) } diff --git a/test/util.spec.js b/test/util.spec.js index ff0b83c81..002a7777f 100644 --- a/test/util.spec.js +++ b/test/util.spec.js @@ -35,10 +35,13 @@ describe('.util', () => { }) describe('.getEndpointConfig', () => { - it('should return the endpoint configured host and port', function () { + it('should return the endpoint configuration', function () { const endpoint = ipfs.util.getEndpointConfig() - expect(endpoint).to.have.property('host') + expect(endpoint.host).to.equal('127.0.0.1') + expect(endpoint.protocol).to.equal('http') + expect(endpoint['api-path']).to.equal('/api/v0/') + // changes per test run so we just assert it exists. expect(endpoint).to.have.property('port') }) }) From bcbf0d20e818e8e80aec9d740cf87221f581437e Mon Sep 17 00:00:00 2001 From: Oli Evans Date: Tue, 29 Jan 2019 11:59:49 +0000 Subject: [PATCH 002/233] fix: throw on invalid multiaddr to constructor (#934) - dont assume that invalid multiaddrs are valid hosts - if multiaddrOrHost starts with a /, assume its a multiaddr - throw if that multiaddr is invalid. Previously, we'd try and use invalid multiaddrs as the host, which would lead to requests like http:///dnsaddr/foobar.com:5001/api License: MIT Signed-off-by: Oli Evans --- src/index.js | 57 ++++++++++-------- test/constructor.spec.js | 126 ++++++++++++++++++++++++++------------- 2 files changed, 118 insertions(+), 65 deletions(-) diff --git a/src/index.js b/src/index.js index 5643084d0..5be787427 100644 --- a/src/index.js +++ b/src/index.js @@ -7,35 +7,35 @@ const getConfig = require('./utils/default-config') const sendRequest = require('./utils/send-request') function ipfsClient (hostOrMultiaddr, port, opts) { - const config = getConfig() - - try { - const maddr = multiaddr(hostOrMultiaddr).nodeAddress() - config.host = maddr.address - config.port = maddr.port - } catch (e) { - if (typeof hostOrMultiaddr === 'string') { - config.host = hostOrMultiaddr - config.port = port && typeof port !== 'object' ? port : config.port + // convert all three params to objects that we can merge. + let hostAndPort = {} + + if (!hostOrMultiaddr) { + // autoconfigure host and port in browser + if (typeof self !== 'undefined') { + const split = self.location.host.split(':') + hostAndPort.host = split[0] + hostAndPort.port = split[1] + } + } else if (multiaddr.isMultiaddr(hostOrMultiaddr)) { + hostAndPort = toHostAndPort(hostOrMultiaddr) + } else if (typeof hostOrMultiaddr === 'object') { + hostAndPort = hostOrMultiaddr + } else if (typeof hostOrMultiaddr === 'string') { + if (hostOrMultiaddr[0] === '/') { + // throws if multiaddr is malformed or can't be converted to a nodeAddress + hostAndPort = toHostAndPort(multiaddr(hostOrMultiaddr)) + } else { + // hostOrMultiaddr is domain or ip address as a string + hostAndPort.host = hostOrMultiaddr } } - let lastIndex = arguments.length - while (!opts && lastIndex-- > 0) { - opts = arguments[lastIndex] - if (opts) break - } - - Object.assign(config, opts) - - // autoconfigure in browser - if (!config.host && - typeof self !== 'undefined') { - const split = self.location.host.split(':') - config.host = split[0] - config.port = split[1] + if (port && typeof port !== 'object') { + port = { port: port } } + const config = Object.assign(getConfig(), hostAndPort, port, opts) const requestAPI = sendRequest(config) const cmds = loadCommands(requestAPI, config) cmds.send = requestAPI @@ -44,4 +44,13 @@ function ipfsClient (hostOrMultiaddr, port, opts) { return cmds } +// throws if multiaddr can't be converted to a nodeAddress +function toHostAndPort (multiaddr) { + const nodeAddr = multiaddr.nodeAddress() + return { + host: nodeAddr.address, + port: nodeAddr.port + } +} + module.exports = ipfsClient diff --git a/test/constructor.spec.js b/test/constructor.spec.js index e2ec239f0..f14d9635c 100644 --- a/test/constructor.spec.js +++ b/test/constructor.spec.js @@ -1,6 +1,7 @@ /* eslint-env mocha */ 'use strict' +const multiaddr = require('multiaddr') const chai = require('chai') const dirtyChai = require('dirty-chai') const expect = chai.expect @@ -9,18 +10,74 @@ chai.use(dirtyChai) const f = require('./utils/factory') const ipfsClient = require('../src/index.js') -function clientWorks (client, done) { - client.id((err, id) => { - expect(err).to.not.exist() +describe('ipfs-http-client constructor tests', () => { + describe('parameter permuations', () => { + it('none', () => { + const ipfs = ipfsClient() + if (typeof self !== 'undefined') { + const { hostname, port } = self.location + expectConfig(ipfs, { host: hostname, port }) + } else { + expectConfig(ipfs, {}) + } + }) - expect(id).to.have.a.property('id') - expect(id).to.have.a.property('publicKey') - done() + it('opts', () => { + const host = 'wizard.world' + const port = '999' + const protocol = 'https' + const ipfs = ipfsClient({ host, port, protocol }) + expectConfig(ipfs, { host, port, protocol }) + }) + + it('mutliaddr dns4 string, opts', () => { + const host = 'foo.com' + const port = '1001' + const protocol = 'https' + const addr = `/dns4/${host}/tcp/${port}` + const ipfs = ipfsClient(addr, { protocol }) + expectConfig(ipfs, { host, port, protocol }) + }) + + it('mutliaddr ipv4 string', () => { + const host = '101.101.101.101' + const port = '1001' + const addr = `/ip4/${host}/tcp/${port}` + const ipfs = ipfsClient(addr) + expectConfig(ipfs, { host, port }) + }) + + it('mutliaddr instance', () => { + const host = 'ace.place' + const port = '1001' + const addr = multiaddr(`/dns4/${host}/tcp/${port}`) + const ipfs = ipfsClient(addr) + expectConfig(ipfs, { host, port }) + }) + + it('host and port strings', () => { + const host = '1.1.1.1' + const port = '9999' + const ipfs = ipfsClient(host, port) + expectConfig(ipfs, { host, port }) + }) + + it('host, port and api path', () => { + const host = '10.100.100.255' + const port = '9999' + const apiPath = '/future/api/v1/' + const ipfs = ipfsClient(host, port, { 'api-path': apiPath }) + expectConfig(ipfs, { host, port, apiPath }) + }) + + it('throws on invalid mutliaddr', () => { + expect(() => ipfsClient('/dns4')).to.throw('invalid address') + expect(() => ipfsClient('/hello')).to.throw('no protocol with name') + expect(() => ipfsClient('/dns4/ipfs.io')).to.throw('multiaddr must have a valid format') + }) }) -} -describe('ipfs-http-client constructor tests', () => { - describe('parameter permuations', () => { + describe('integration', () => { let apiAddr let ipfsd @@ -40,39 +97,26 @@ describe('ipfs-http-client constructor tests', () => { ipfsd.stop(done) }) - it('opts', (done) => { - const splitted = apiAddr.split('/') - clientWorks(ipfsClient({ - host: splitted[2], - port: splitted[4], - protocol: 'http' - }), done) - }) - - it('mutliaddr, opts', (done) => { - clientWorks(ipfsClient(apiAddr, { protocol: 'http' }), done) - }) - - it('host, port', (done) => { - const splitted = apiAddr.split('/') - - clientWorks(ipfsClient(splitted[2], splitted[4]), done) - }) - - it('specify host, port and api path', (done) => { - const splitted = apiAddr.split('/') - - clientWorks(ipfsClient({ - host: splitted[2], - port: splitted[4], - 'api-path': '/api/v0/' - }), done) + it('can connect to an ipfs http api', (done) => { + clientWorks(ipfsClient(apiAddr), done) }) + }) +}) - it('host, port, opts', (done) => { - const splitted = apiAddr.split('/') +function clientWorks (client, done) { + client.id((err, id) => { + expect(err).to.not.exist() - clientWorks(ipfsClient(splitted[2], splitted[4], { protocol: 'http' }), done) - }) + expect(id).to.have.a.property('id') + expect(id).to.have.a.property('publicKey') + done() }) -}) +} + +function expectConfig (ipfs, { host, port, protocol, apiPath }) { + const conf = ipfs.util.getEndpointConfig() + expect(conf.host).to.equal(host || 'localhost') + expect(conf.port).to.equal(port || '5001') + expect(conf.protocol).to.equal(protocol || 'http') + expect(conf['api-path']).to.equal(apiPath || '/api/v0/') +} From 301c9f49f7126cb41cc0d8916b93366949de3b9f Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Tue, 29 Jan 2019 13:58:12 +0000 Subject: [PATCH 003/233] chore: update contributors --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e4692b74b..58475b6fb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ipfs-http-client", - "version": "29.0.1", + "version": "29.1.0", "description": "A client library for the IPFS HTTP API", "leadMaintainer": "Alan Shaw ", "main": "src/index.js", From 6012e673ff1e954d244693781ed13daad9f340b1 Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Tue, 29 Jan 2019 13:58:12 +0000 Subject: [PATCH 004/233] chore: release version v29.1.0 --- CHANGELOG.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8e6a331d2..e7068feea 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,18 @@ + +# [29.1.0](https://github.com/ipfs/js-ipfs-http-client/compare/v29.0.1...v29.1.0) (2019-01-29) + + +### Bug Fixes + +* throw on invalid multiaddr to constructor ([#934](https://github.com/ipfs/js-ipfs-http-client/issues/934)) ([bcbf0d2](https://github.com/ipfs/js-ipfs-http-client/commit/bcbf0d2)) + + +### Features + +* return protocol from getEndpointConfig ([#935](https://github.com/ipfs/js-ipfs-http-client/issues/935)) ([12ddaa3](https://github.com/ipfs/js-ipfs-http-client/commit/12ddaa3)) + + + ## [29.0.1](https://github.com/ipfs/js-ipfs-http-client/compare/v29.0.0...v29.0.1) (2019-01-24) From bfd71c2bd9a467b166c85eaa7dd5d7fb94e4dfa4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20=C5=A0?= Date: Mon, 4 Feb 2019 16:08:31 +0100 Subject: [PATCH 005/233] chore: update required Node.js version (#937) --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 58475b6fb..24e10c409 100644 --- a/package.json +++ b/package.json @@ -68,7 +68,7 @@ "through2": "^3.0.0" }, "engines": { - "node": ">=8.0.0", + "node": ">=10.0.0", "npm": ">=3.0.0" }, "repository": { From 6552f0f8478fee0e189a8d1c248232c66e6318f7 Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Tue, 12 Feb 2019 21:50:49 +0000 Subject: [PATCH 006/233] chore: switch to travis-ci.com (#943) License: MIT Signed-off-by: Alan Shaw --- .gitattributes | 2 + .travis.yml | 72 +++++++++++++++++----------- README.md | 2 +- appveyor.yml | 29 ----------- ci/Jenkinsfile | 2 - circle.yml | 19 -------- src/files-regular/get-pull-stream.js | 19 ++++---- 7 files changed, 55 insertions(+), 90 deletions(-) create mode 100644 .gitattributes delete mode 100644 appveyor.yml delete mode 100644 ci/Jenkinsfile delete mode 100644 circle.yml diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 000000000..a836e072a --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +* text=auto +test/fixtures/** text eol=lf diff --git a/.travis.yml b/.travis.yml index 5102ee5ff..fb59f0eeb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,32 +1,46 @@ -# Warning: This file is automatically synced from https://github.com/ipfs/ci-sync so if you want to change it, please change it there and ask someone to sync all repositories. -sudo: false language: node_js +cache: npm +stages: + - check + - test + - cov -matrix: +node_js: + - '10' + +os: + - linux + - osx + - windows + +script: npx nyc -s npm run test:node -- --bail +after_success: npx nyc report --reporter=text-lcov > coverage.lcov && npx codecov + +jobs: include: - - node_js: 6 - env: CXX=g++-4.8 - - node_js: 8 - env: CXX=g++-4.8 - # - node_js: stable - # env: CXX=g++-4.8 - -script: - - npm run lint - - npm run test - - npm run coverage - -before_script: - - export DISPLAY=:99.0 - - sh -e /etc/init.d/xvfb start - -after_success: - - npm run coverage-publish - -addons: - firefox: 'latest' - apt: - sources: - - ubuntu-toolchain-r-test - packages: - - g++-4.8 + - stage: check + script: + - npx aegir commitlint --travis + - npx aegir dep-check + - npm run lint + + - stage: test + name: chrome + addons: + chrome: stable + script: npx aegir test -t browser + + - stage: test + name: firefox + addons: + firefox: latest + script: npx aegir test -t browser -- --browsers FirefoxHeadless + + - stage: test + name: webworker + addons: + chrome: stable + script: npx aegir test -t webworker + +notifications: + email: false diff --git a/README.md b/README.md index 4bcc34255..f8bb44c80 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@

- +
diff --git a/appveyor.yml b/appveyor.yml deleted file mode 100644 index 046bf9108..000000000 --- a/appveyor.yml +++ /dev/null @@ -1,29 +0,0 @@ -# Warning: This file is automatically synced from https://github.com/ipfs/ci-sync so if you want to change it, please change it there and ask someone to sync all repositories. -version: "{build}" - -environment: - matrix: - - nodejs_version: "6" - - nodejs_version: "8" - -matrix: - fast_finish: true - -install: - # Install Node.js - - ps: Install-Product node $env:nodejs_version - - # Upgrade npm - - npm install -g npm - - # Output our current versions for debugging - - node --version - - npm --version - - # Install our package dependencies - - npm install - -test_script: - - npm run test:node - -build: off diff --git a/ci/Jenkinsfile b/ci/Jenkinsfile deleted file mode 100644 index a7da2e54f..000000000 --- a/ci/Jenkinsfile +++ /dev/null @@ -1,2 +0,0 @@ -// Warning: This file is automatically synced from https://github.com/ipfs/ci-sync so if you want to change it, please change it there and ask someone to sync all repositories. -javascript() diff --git a/circle.yml b/circle.yml deleted file mode 100644 index e0338e62d..000000000 --- a/circle.yml +++ /dev/null @@ -1,19 +0,0 @@ -# Warning: This file is automatically synced from https://github.com/ipfs/ci-sync so if you want to change it, please change it there and ask someone to sync all repositories. -machine: - node: - version: stable - -test: - post: - - npm run coverage -- --upload --providers coveralls - -dependencies: - pre: - - google-chrome --version - - curl -L -o google-chrome.deb https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb - - sudo dpkg -i google-chrome.deb || true - - sudo apt-get update - - sudo apt-get install -f - - sudo apt-get install --only-upgrade lsb-base - - sudo dpkg -i google-chrome.deb - - google-chrome --version diff --git a/src/files-regular/get-pull-stream.js b/src/files-regular/get-pull-stream.js index d86088e30..c7d8aa7a4 100644 --- a/src/files-regular/get-pull-stream.js +++ b/src/files-regular/get-pull-stream.js @@ -3,7 +3,6 @@ const cleanCID = require('../utils/clean-cid') const TarStreamToObjects = require('../utils/tar-stream-to-objects') const v = require('is-ipfs') -const through = require('through2') const pull = require('pull-stream') const toPull = require('stream-to-pull-stream') const deferred = require('pull-defer') @@ -28,15 +27,15 @@ module.exports = (send) => { send.andTransform(request, TarStreamToObjects, (err, stream) => { if (err) { return p.end(err) } - const files = [] - stream.pipe(through.obj((file, enc, next) => { - if (file.content) { - files.push({ path: file.path, content: toPull(file.content) }) - } else { - files.push(file) - } - next() - }, () => p.resolve(pull.values(files)))) + p.resolve( + pull( + toPull.source(stream), + pull.map(file => { + const { path, content } = file + return content ? { path, content: toPull.source(content) } : file + }) + ) + ) }) return p From 2c90620641a92a4f21142c0399540e1ffa3a0529 Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Tue, 12 Feb 2019 22:28:11 +0000 Subject: [PATCH 007/233] perf: use test profile (#942) License: MIT Signed-off-by: Alan Shaw --- package.json | 2 +- test/commands.spec.js | 2 +- test/constructor.spec.js | 2 +- test/custom-headers.spec.js | 2 +- test/dag.spec.js | 2 +- test/diag.spec.js | 2 +- test/files-mfs.spec.js | 2 +- test/get.spec.js | 2 +- test/key.spec.js | 2 +- test/log.spec.js | 2 +- test/name.spec.js | 4 ++-- test/ping.spec.js | 4 ++-- test/pubsub-in-browser.spec.js | 2 +- test/refs.spec.js | 2 +- test/repo.spec.js | 2 +- test/stats.spec.js | 2 +- test/util.spec.js | 2 +- test/utils/interface-common-factory.js | 2 +- 18 files changed, 20 insertions(+), 20 deletions(-) diff --git a/package.json b/package.json index 24e10c409..4200d5b60 100644 --- a/package.json +++ b/package.json @@ -84,7 +84,7 @@ "eslint-plugin-react": "^7.11.1", "go-ipfs-dep": "~0.4.18", "interface-ipfs-core": "~0.96.0", - "ipfsd-ctl": "~0.40.0", + "ipfsd-ctl": "github:ipfs/js-ipfsd-ctl", "nock": "^10.0.2", "pull-stream": "^3.6.9", "stream-equal": "^1.1.1" diff --git a/test/commands.spec.js b/test/commands.spec.js index dd97269ba..3fb4f02e0 100644 --- a/test/commands.spec.js +++ b/test/commands.spec.js @@ -17,7 +17,7 @@ describe('.commands', function () { let ipfs before((done) => { - f.spawn({ initOptions: { bits: 1024 } }, (err, _ipfsd) => { + f.spawn({ initOptions: { bits: 1024, profile: 'test' } }, (err, _ipfsd) => { expect(err).to.not.exist() ipfsd = _ipfsd ipfs = ipfsClient(_ipfsd.apiAddr) diff --git a/test/constructor.spec.js b/test/constructor.spec.js index f14d9635c..ab3ad26a2 100644 --- a/test/constructor.spec.js +++ b/test/constructor.spec.js @@ -84,7 +84,7 @@ describe('ipfs-http-client constructor tests', () => { before(function (done) { this.timeout(60 * 1000) // slow CI - f.spawn({ initOptions: { bits: 1024 } }, (err, node) => { + f.spawn({ initOptions: { bits: 1024, profile: 'test' } }, (err, node) => { expect(err).to.not.exist() ipfsd = node apiAddr = node.apiAddr.toString() diff --git a/test/custom-headers.spec.js b/test/custom-headers.spec.js index bda3c60b0..1e1748515 100644 --- a/test/custom-headers.spec.js +++ b/test/custom-headers.spec.js @@ -18,7 +18,7 @@ describe('custom headers', function () { let ipfsd // initialize ipfs with custom headers before(done => { - f.spawn({ initOptions: { bits: 1024 } }, (err, _ipfsd) => { + f.spawn({ initOptions: { bits: 1024, profile: 'test' } }, (err, _ipfsd) => { expect(err).to.not.exist() ipfsd = _ipfsd ipfs = ipfsClient({ diff --git a/test/dag.spec.js b/test/dag.spec.js index 9c92c2d14..0b1a2f314 100644 --- a/test/dag.spec.js +++ b/test/dag.spec.js @@ -21,7 +21,7 @@ describe('.dag', function () { this.timeout(20 * 1000) before(function (done) { series([ - (cb) => f.spawn({ initOptions: { bits: 1024 } }, (err, _ipfsd) => { + (cb) => f.spawn({ initOptions: { bits: 1024, profile: 'test' } }, (err, _ipfsd) => { expect(err).to.not.exist() ipfsd = _ipfsd ipfs = ipfsClient(_ipfsd.apiAddr) diff --git a/test/diag.spec.js b/test/diag.spec.js index c3afffe05..3f12106e0 100644 --- a/test/diag.spec.js +++ b/test/diag.spec.js @@ -20,7 +20,7 @@ describe('.diag', function () { let ipfs before((done) => { - f.spawn({ initOptions: { bits: 1024 } }, (err, _ipfsd) => { + f.spawn({ initOptions: { bits: 1024, profile: 'test' } }, (err, _ipfsd) => { expect(err).to.not.exist() ipfsd = _ipfsd ipfs = ipfsClient(_ipfsd.apiAddr) diff --git a/test/files-mfs.spec.js b/test/files-mfs.spec.js index 38fc35a40..b550105a6 100644 --- a/test/files-mfs.spec.js +++ b/test/files-mfs.spec.js @@ -38,7 +38,7 @@ describe('.files (the MFS API part)', function () { const expectedMultihash = 'Qma4hjFTnCasJ8PVp3mZbZK5g2vGDT4LByLJ7m8ciyRFZP' before((done) => { - f.spawn({ initOptions: { bits: 1024 } }, (err, _ipfsd) => { + f.spawn({ initOptions: { bits: 1024, profile: 'test' } }, (err, _ipfsd) => { expect(err).to.not.exist() ipfsd = _ipfsd ipfs = ipfsClient(_ipfsd.apiAddr) diff --git a/test/get.spec.js b/test/get.spec.js index 84abf5c80..c789ce971 100644 --- a/test/get.spec.js +++ b/test/get.spec.js @@ -31,7 +31,7 @@ describe('.get (specific go-ipfs features)', function () { before(function (done) { series([ - (cb) => f.spawn({ initOptions: { bits: 1024 } }, (err, _ipfsd) => { + (cb) => f.spawn({ initOptions: { bits: 1024, profile: 'test' } }, (err, _ipfsd) => { expect(err).to.not.exist() ipfsd = _ipfsd ipfs = ipfsClient(_ipfsd.apiAddr) diff --git a/test/key.spec.js b/test/key.spec.js index 5c729a90e..8ed35d42b 100644 --- a/test/key.spec.js +++ b/test/key.spec.js @@ -17,7 +17,7 @@ describe('.key', function () { let ipfs before((done) => { - f.spawn({ initOptions: { bits: 1024 } }, (err, _ipfsd) => { + f.spawn({ initOptions: { bits: 1024, profile: 'test' } }, (err, _ipfsd) => { expect(err).to.not.exist() ipfsd = _ipfsd ipfs = ipfsClient(_ipfsd.apiAddr) diff --git a/test/log.spec.js b/test/log.spec.js index ebccc029c..16782d66a 100644 --- a/test/log.spec.js +++ b/test/log.spec.js @@ -17,7 +17,7 @@ describe('.log', function () { let ipfs before((done) => { - f.spawn({ initOptions: { bits: 1024 } }, (err, _ipfsd) => { + f.spawn({ initOptions: { bits: 1024, profile: 'test' } }, (err, _ipfsd) => { expect(err).to.not.exist() ipfsd = _ipfsd ipfs = ipfsClient(_ipfsd.apiAddr) diff --git a/test/name.spec.js b/test/name.spec.js index 3b352e6b9..67c19f94a 100644 --- a/test/name.spec.js +++ b/test/name.spec.js @@ -28,7 +28,7 @@ describe('.name', () => { series([ (cb) => { - f.spawn({ initOptions: { bits: 1024 } }, (err, _ipfsd) => { + f.spawn({ initOptions: { bits: 1024, profile: 'test' } }, (err, _ipfsd) => { expect(err).to.not.exist() ipfsd = _ipfsd ipfs = ipfsClient(_ipfsd.apiAddr) @@ -36,7 +36,7 @@ describe('.name', () => { }) }, (cb) => { - f.spawn({ initOptions: { bits: 1024 } }, (err, node) => { + f.spawn({ initOptions: { bits: 1024, profile: 'test' } }, (err, node) => { expect(err).to.not.exist() other = node.api otherd = node diff --git a/test/ping.spec.js b/test/ping.spec.js index 2dede0328..c8a856e13 100644 --- a/test/ping.spec.js +++ b/test/ping.spec.js @@ -34,7 +34,7 @@ describe('.ping', function () { series([ (cb) => { - f.spawn({ initOptions: { bits: 1024 } }, (err, _ipfsd) => { + f.spawn({ initOptions: { bits: 1024, profile: 'test' } }, (err, _ipfsd) => { expect(err).to.not.exist() ipfsd = _ipfsd ipfs = ipfsClient(_ipfsd.apiAddr) @@ -42,7 +42,7 @@ describe('.ping', function () { }) }, (cb) => { - f.spawn({ initOptions: { bits: 1024 } }, (err, node) => { + f.spawn({ initOptions: { bits: 1024, profile: 'test' } }, (err, node) => { expect(err).to.not.exist() other = node.api otherd = node diff --git a/test/pubsub-in-browser.spec.js b/test/pubsub-in-browser.spec.js index 0f7dc3ce7..ff1a22347 100644 --- a/test/pubsub-in-browser.spec.js +++ b/test/pubsub-in-browser.spec.js @@ -47,7 +47,7 @@ describe('.pubsub is not supported in the browser, yet!', function () { let ipfsd before((done) => { - f.spawn({ initOptions: { bits: 1024 } }, (err, _ipfsd) => { + f.spawn({ initOptions: { bits: 1024, profile: 'test' } }, (err, _ipfsd) => { expect(err).to.not.exist() ipfsd = _ipfsd ipfs = ipfsClient(_ipfsd.apiAddr) diff --git a/test/refs.spec.js b/test/refs.spec.js index 06fe10142..9ffcf4ebe 100644 --- a/test/refs.spec.js +++ b/test/refs.spec.js @@ -35,7 +35,7 @@ describe('.refs', function () { } waterfall([ - (cb) => f.spawn({ initOptions: { bits: 1024 } }, cb), + (cb) => f.spawn({ initOptions: { bits: 1024, profile: 'test' } }, cb), (_ipfsd, cb) => { ipfsd = _ipfsd ipfs = ipfsClient(_ipfsd.apiAddr) diff --git a/test/repo.spec.js b/test/repo.spec.js index 142ff5659..e01868810 100644 --- a/test/repo.spec.js +++ b/test/repo.spec.js @@ -16,7 +16,7 @@ describe('.repo', function () { let ipfsd before((done) => { - f.spawn({ initOptions: { bits: 1024 } }, (err, _ipfsd) => { + f.spawn({ initOptions: { bits: 1024, profile: 'test' } }, (err, _ipfsd) => { expect(err).to.not.exist() ipfsd = _ipfsd ipfs = ipfsClient(_ipfsd.apiAddr) diff --git a/test/stats.spec.js b/test/stats.spec.js index 4c93da490..4597e0397 100644 --- a/test/stats.spec.js +++ b/test/stats.spec.js @@ -16,7 +16,7 @@ describe('stats', function () { let ipfsd before((done) => { - f.spawn({ initOptions: { bits: 1024 } }, (err, _ipfsd) => { + f.spawn({ initOptions: { bits: 1024, profile: 'test' } }, (err, _ipfsd) => { expect(err).to.not.exist() ipfsd = _ipfsd ipfs = ipfsClient(_ipfsd.apiAddr) diff --git a/test/util.spec.js b/test/util.spec.js index 002a7777f..9915c2940 100644 --- a/test/util.spec.js +++ b/test/util.spec.js @@ -20,7 +20,7 @@ describe('.util', () => { before(function (done) { this.timeout(20 * 1000) // slow CI - f.spawn({ initOptions: { bits: 1024 } }, (err, _ipfsd) => { + f.spawn({ initOptions: { bits: 1024, profile: 'test' } }, (err, _ipfsd) => { expect(err).to.not.exist() ipfsd = _ipfsd ipfs = ipfsClient(_ipfsd.apiAddr) diff --git a/test/utils/interface-common-factory.js b/test/utils/interface-common-factory.js index db3960e59..ad5010080 100644 --- a/test/utils/interface-common-factory.js +++ b/test/utils/interface-common-factory.js @@ -9,7 +9,7 @@ function createFactory (options) { options = options || {} options.factoryOptions = options.factoryOptions || {} - options.spawnOptions = options.spawnOptions || { initOptions: { bits: 1024 } } + options.spawnOptions = options.spawnOptions || { initOptions: { bits: 1024, profile: 'test' } } const ipfsFactory = IPFSFactory.create(options.factoryOptions) From e69aca1e2dbc20cfd8ce948dc1701d018aacaa23 Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Tue, 12 Feb 2019 22:39:38 +0000 Subject: [PATCH 008/233] docs: update name-api example (#944) Updates deps and fixes example code! License: MIT Signed-off-by: Alan Shaw --- examples/name-api/index.js | 8 +- examples/name-api/package-lock.json | 2131 ++++++++++----------------- examples/name-api/package.json | 4 +- 3 files changed, 812 insertions(+), 1331 deletions(-) diff --git a/examples/name-api/index.js b/examples/name-api/index.js index 1c1c75a30..931f5560e 100644 --- a/examples/name-api/index.js +++ b/examples/name-api/index.js @@ -38,7 +38,7 @@ const enableForms = () => { const init = () => { ipfs.id() .then(res => { - showStatus(`daemon active\nid: ${res.ID}`, COLORS.success) + showStatus(`daemon active\nid: ${res.id}`, COLORS.success) enableForms() }) .catch(err => { @@ -77,7 +77,7 @@ const publish = (path) => { ipfs.name.publish(path) .then(res => { - const name = res.Name + const name = res.name showStatus('success!', COLORS.success) DOM.publishResultsDiv.classList.remove('hidden') DOM.publishResult.innerText = `/ipns/${name}` @@ -95,9 +95,7 @@ const resolve = (name) => { DOM.resolveResultsDiv.classList.add('hidden') ipfs.name.resolve(name) - .then(res => { - const path = res.Path - + .then(path => { showStatus('success!', COLORS.success) DOM.resolveResultsDiv.classList.remove('hidden') DOM.resolveResult.innerText = path diff --git a/examples/name-api/package-lock.json b/examples/name-api/package-lock.json index 863aa15c4..aed871bd3 100644 --- a/examples/name-api/package-lock.json +++ b/examples/name-api/package-lock.json @@ -1,50 +1,47 @@ { - "name": "js-ipfs-api-example-name-publish-resolve", + "name": "js-ipfs-http-client-example-name-publish-resolve", "version": "1.0.0", "lockfileVersion": 1, + "requires": true, "dependencies": { - "@types/mkdirp": { - "version": "0.3.29", - "resolved": "https://registry.npmjs.org/@types/mkdirp/-/mkdirp-0.3.29.tgz", - "integrity": "sha1-fyrX7FX5FEgvybHsS7GuYCjUYGY=", + "JSONStream": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", + "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", "dev": true, - "optional": true - }, - "@types/node": { - "version": "6.0.73", - "resolved": "https://registry.npmjs.org/@types/node/-/node-6.0.73.tgz", - "integrity": "sha1-hdxLtvElN3x13dJRmh7rY/Ck7XA=", - "dev": true + "requires": { + "jsonparse": "^1.2.0", + "through": ">=2.2.7 <3" + } }, "acorn": { - "version": "4.0.13", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz", - "integrity": "sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c=", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.1.0.tgz", + "integrity": "sha512-MW/FjM+IvU9CgBzjO3UIPCE2pyEwUsoFl+VGdczOPEdxfGFjuKny/gN54mOuX7Qxmb9Rg9MCn2oKiSUeW+pjrw==", "dev": true }, - "amdefine": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", - "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", - "dev": true, - "optional": true - }, - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "acorn-dynamic-import": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/acorn-dynamic-import/-/acorn-dynamic-import-4.0.0.tgz", + "integrity": "sha512-d3OEjQV4ROpoflsnUA8HozoIR504TFxNivYEUi6uwz0IYhBkTDXGuWlNdMtybRt3nqVx/L6XqMt0FxkXuWKZhw==", "dev": true }, - "aproba": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.1.1.tgz", - "integrity": "sha1-ldNgDwdxCqDpKYxyatXs8urLq6s=", - "dev": true + "acorn-node": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.6.2.tgz", + "integrity": "sha512-rIhNEZuNI8ibQcL7ANm/mGyPukIaZsRNX9psFNQURyJW0nu6k8wjSDld20z6v2mDBWqX13pIEnk9gGZJHIlEXg==", + "dev": true, + "requires": { + "acorn": "^6.0.2", + "acorn-dynamic-import": "^4.0.0", + "acorn-walk": "^6.1.0", + "xtend": "^4.0.1" + } }, - "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=", + "acorn-walk": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.1.1.tgz", + "integrity": "sha512-OtUw6JUTgxA2QoqqmrmQ7F2NYqiBPi/L2jqHyFtllhOUvXYQXf0Z1CYUinIfyT4bTCGmrA7gX9FvHA81uzCoVw==", "dev": true }, "array-filter": { @@ -66,22 +63,41 @@ "dev": true }, "asn1.js": { - "version": "4.9.1", - "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.9.1.tgz", - "integrity": "sha1-SLokC0WpKA6UdImQull9IWYX/UA=", - "dev": true + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", + "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", + "dev": true, + "requires": { + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } }, "assert": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/assert/-/assert-1.4.1.tgz", "integrity": "sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE=", - "dev": true - }, - "astw": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/astw/-/astw-2.2.0.tgz", - "integrity": "sha1-e9QXhNMkk5h66yOba04cV6hzuRc=", - "dev": true + "dev": true, + "requires": { + "util": "0.10.3" + }, + "dependencies": { + "inherits": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", + "dev": true + }, + "util": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", + "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", + "dev": true, + "requires": { + "inherits": "2.0.1" + } + } + } }, "async": { "version": "1.5.2", @@ -90,64 +106,32 @@ "dev": true }, "balanced-match": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz", - "integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg=", - "dev": true - }, - "base-x": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/base-x/-/base-x-2.0.6.tgz", - "integrity": "sha1-RYKpHrzsme4G9OQDIDCwzxwpQdg=", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", "dev": true }, "base64-js": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.2.0.tgz", - "integrity": "sha1-o5mS1yNYSBGYK+XikLtqU9hnAPE=", - "dev": true - }, - "bindings": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.2.1.tgz", - "integrity": "sha1-FK1hE4EtLTfXLme0ystLtyZQXxE=", - "dev": true - }, - "bip66": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/bip66/-/bip66-1.1.5.tgz", - "integrity": "sha1-AfqHSHhcpwlV1QESF9GzE5lpyiI=", - "dev": true - }, - "bl": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.1.tgz", - "integrity": "sha1-ysMo977kVzDUBLaSID/LWQ4XLV4=", - "dev": true - }, - "blakejs": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/blakejs/-/blakejs-1.1.0.tgz", - "integrity": "sha1-ad+S75U6qIylGjLfarHFShVfx6U=", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.0.tgz", + "integrity": "sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw==", "dev": true }, "bn.js": { - "version": "4.11.6", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz", - "integrity": "sha1-UzRK2xRhehP26N0s4okF0cC6MhU=", + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", + "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", "dev": true }, "brace-expansion": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.7.tgz", - "integrity": "sha1-Pv/DxQ4ABTH7cg6v+A8K6O8jz1k=", - "dev": true - }, - "brfs": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/brfs/-/brfs-1.4.3.tgz", - "integrity": "sha1-22ddb16SPm3wh/ylhZyQkKrtMhY=", - "dev": true + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } }, "brorand": { "version": "1.1.0", @@ -156,16 +140,27 @@ "dev": true }, "browser-pack": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/browser-pack/-/browser-pack-6.0.2.tgz", - "integrity": "sha1-+GzWzvT1MAyOY+B6TVEvZfv/RTE=", - "dev": true + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/browser-pack/-/browser-pack-6.1.0.tgz", + "integrity": "sha512-erYug8XoqzU3IfcU8fUgyHqyOXqIE4tUTTQ+7mqUjQlvnXkOO6OlT9c/ZoJVHYoAaqGxr09CN53G7XIsO4KtWA==", + "dev": true, + "requires": { + "JSONStream": "^1.0.3", + "combine-source-map": "~0.8.0", + "defined": "^1.0.0", + "safe-buffer": "^5.1.1", + "through2": "^2.0.0", + "umd": "^3.0.0" + } }, "browser-resolve": { - "version": "1.11.2", - "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-1.11.2.tgz", - "integrity": "sha1-j/CbCixCFxihBRwmCzLkj0QpOM4=", + "version": "1.11.3", + "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-1.11.3.tgz", + "integrity": "sha512-exDi1BYWB/6raKHmDTCicQfTkqwN5fioMFV4j8BsfMU4R2DK/QfZfK7kOVkmWCNANf0snkBzqGqAJBao9gZMdQ==", "dev": true, + "requires": { + "resolve": "1.1.7" + }, "dependencies": { "resolve": { "version": "1.1.7", @@ -176,75 +171,146 @@ } }, "browserify": { - "version": "14.4.0", - "resolved": "https://registry.npmjs.org/browserify/-/browserify-14.4.0.tgz", - "integrity": "sha1-CJo0Y69Y0OSNjNQHCz90ZU1avKk=", - "dev": true + "version": "16.2.3", + "resolved": "https://registry.npmjs.org/browserify/-/browserify-16.2.3.tgz", + "integrity": "sha512-zQt/Gd1+W+IY+h/xX2NYMW4orQWhqSwyV+xsblycTtpOuB27h1fZhhNQuipJ4t79ohw4P4mMem0jp/ZkISQtjQ==", + "dev": true, + "requires": { + "JSONStream": "^1.0.3", + "assert": "^1.4.0", + "browser-pack": "^6.0.1", + "browser-resolve": "^1.11.0", + "browserify-zlib": "~0.2.0", + "buffer": "^5.0.2", + "cached-path-relative": "^1.0.0", + "concat-stream": "^1.6.0", + "console-browserify": "^1.1.0", + "constants-browserify": "~1.0.0", + "crypto-browserify": "^3.0.0", + "defined": "^1.0.0", + "deps-sort": "^2.0.0", + "domain-browser": "^1.2.0", + "duplexer2": "~0.1.2", + "events": "^2.0.0", + "glob": "^7.1.0", + "has": "^1.0.0", + "htmlescape": "^1.1.0", + "https-browserify": "^1.0.0", + "inherits": "~2.0.1", + "insert-module-globals": "^7.0.0", + "labeled-stream-splicer": "^2.0.0", + "mkdirp": "^0.5.0", + "module-deps": "^6.0.0", + "os-browserify": "~0.3.0", + "parents": "^1.0.1", + "path-browserify": "~0.0.0", + "process": "~0.11.0", + "punycode": "^1.3.2", + "querystring-es3": "~0.2.0", + "read-only-stream": "^2.0.0", + "readable-stream": "^2.0.2", + "resolve": "^1.1.4", + "shasum": "^1.0.0", + "shell-quote": "^1.6.1", + "stream-browserify": "^2.0.0", + "stream-http": "^2.0.0", + "string_decoder": "^1.1.1", + "subarg": "^1.0.0", + "syntax-error": "^1.1.1", + "through2": "^2.0.0", + "timers-browserify": "^1.0.1", + "tty-browserify": "0.0.1", + "url": "~0.11.0", + "util": "~0.10.1", + "vm-browserify": "^1.0.0", + "xtend": "^4.0.0" + } }, "browserify-aes": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.0.6.tgz", - "integrity": "sha1-Xncl297x/Vkw1OurSFZ85FHEigo=", - "dev": true + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", + "dev": true, + "requires": { + "buffer-xor": "^1.0.3", + "cipher-base": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.3", + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } }, "browserify-cipher": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.0.tgz", - "integrity": "sha1-mYgkSHS/XtTijalWZtzWasj8Njo=", - "dev": true + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", + "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", + "dev": true, + "requires": { + "browserify-aes": "^1.0.4", + "browserify-des": "^1.0.0", + "evp_bytestokey": "^1.0.0" + } }, "browserify-des": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.0.tgz", - "integrity": "sha1-2qJ3cXRwki7S/hhZQRihdUOXId0=", - "dev": true + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", + "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", + "dev": true, + "requires": { + "cipher-base": "^1.0.1", + "des.js": "^1.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } }, "browserify-rsa": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", - "dev": true + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "randombytes": "^2.0.1" + } }, "browserify-sign": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz", "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=", - "dev": true + "dev": true, + "requires": { + "bn.js": "^4.1.1", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.2", + "elliptic": "^6.0.0", + "inherits": "^2.0.1", + "parse-asn1": "^5.0.0" + } }, "browserify-zlib": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.1.4.tgz", - "integrity": "sha1-uzX4pRn2AOD6a4SFJByXnQFB+y0=", - "dev": true - }, - "bs58": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.0.tgz", - "integrity": "sha1-ZfXer2105hNamfdjymIJq0JLkXI=", - "dev": true + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", + "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", + "dev": true, + "requires": { + "pako": "~1.0.5" + } }, "buffer": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.0.6.tgz", - "integrity": "sha1-LqZp9+7Atu2gWwj4tf9mGyhXNYg=", - "dev": true - }, - "buffer-equal": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-0.0.1.tgz", - "integrity": "sha1-kbx0sR6kBbyRa8aqkI+q+ltKrEs=", - "dev": true - }, - "buffer-loader": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/buffer-loader/-/buffer-loader-0.0.1.tgz", - "integrity": "sha1-TWd8qS3YiTEIeLAqL7z6txICTPI=", - "dev": true + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.2.1.tgz", + "integrity": "sha512-c+Ko0loDaFfuPWiL02ls9Xd3GO3cPVmUobQ6t3rXNUk304u6hGq+8N/kFi+QEIKhzK3uwolVhLzszmfLmMLnqg==", + "dev": true, + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } }, - "buffer-shims": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz", - "integrity": "sha1-mXjOMXOIxkmth5MCjDR37wRKi1E=", + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", "dev": true }, "buffer-xor": { @@ -260,34 +326,20 @@ "dev": true }, "cached-path-relative": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cached-path-relative/-/cached-path-relative-1.0.1.tgz", - "integrity": "sha1-0JxLUoAKpMB44t2BqGmqyQ0uVOc=", - "dev": true - }, - "chownr": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.0.1.tgz", - "integrity": "sha1-4qdQQqlVGQi+vSW4Uj1fl2nXkYE=", - "dev": true - }, - "cids": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/cids/-/cids-0.5.0.tgz", - "integrity": "sha1-3QRhyoNJtaSv7FdmqsWpD+4zXoM=", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/cached-path-relative/-/cached-path-relative-1.0.2.tgz", + "integrity": "sha512-5r2GqsoEb4qMTTN9J+WzXfjov+hjxT+j3u5K+kIVNIwAd99DLCJE9pBIMP1qVeybV6JiijL385Oz0DcYxfbOIg==", "dev": true }, "cipher-base": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.3.tgz", - "integrity": "sha1-7qvxlEGc6QDaMBjCB9IS8qbfCgc=", - "dev": true - }, - "code-point-at": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", - "dev": true + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } }, "colors": { "version": "1.0.3", @@ -296,10 +348,16 @@ "dev": true }, "combine-source-map": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/combine-source-map/-/combine-source-map-0.7.2.tgz", - "integrity": "sha1-CHAxKFazB6h8xKxIbzqaYq7MwJ4=", - "dev": true + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/combine-source-map/-/combine-source-map-0.8.0.tgz", + "integrity": "sha1-pY0N8ELBhvz4IqjoAV9UUNLXmos=", + "dev": true, + "requires": { + "convert-source-map": "~1.1.0", + "inline-source-map": "~0.6.0", + "lodash.memoize": "~3.0.3", + "source-map": "~0.5.3" + } }, "concat-map": { "version": "0.0.1", @@ -308,36 +366,25 @@ "dev": true }, "concat-stream": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.5.2.tgz", - "integrity": "sha1-cIl4Yk2FavQaWnQd790mHadSwmY=", + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", "dev": true, - "dependencies": { - "readable-stream": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", - "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=", - "dev": true - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - } + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" } }, "console-browserify": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=", - "dev": true - }, - "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=", - "dev": true + "dev": true, + "requires": { + "date-now": "^0.1.4" + } }, "constants-browserify": { "version": "1.0.0", @@ -364,28 +411,60 @@ "dev": true }, "create-ecdh": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.0.tgz", - "integrity": "sha1-iIxyNZbN92EvZJgjPuvXo1MBc30=", - "dev": true + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz", + "integrity": "sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw==", + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "elliptic": "^6.0.0" + } }, "create-hash": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.1.3.tgz", - "integrity": "sha1-YGBCrIuSYnUPSDyt2rD1gZFy2P0=", - "dev": true + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "dev": true, + "requires": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" + } }, "create-hmac": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.6.tgz", - "integrity": "sha1-rLniIaThe9sHbpBlfEK5PjcmzwY=", - "dev": true + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "dev": true, + "requires": { + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } }, "crypto-browserify": { - "version": "3.11.0", - "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.11.0.tgz", - "integrity": "sha1-NlKgkGq5sqfgw85mpAjpV6JIVSI=", - "dev": true + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", + "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", + "dev": true, + "requires": { + "browserify-cipher": "^1.0.0", + "browserify-sign": "^4.0.0", + "create-ecdh": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.0", + "diffie-hellman": "^5.0.0", + "inherits": "^2.0.1", + "pbkdf2": "^3.0.3", + "public-encrypt": "^4.0.0", + "randombytes": "^2.0.0", + "randomfill": "^1.0.3" + } }, "date-now": { "version": "0.1.4", @@ -394,16 +473,13 @@ "dev": true }, "debug": { - "version": "2.6.8", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz", - "integrity": "sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw=", - "dev": true - }, - "deep-extend": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.4.2.tgz", - "integrity": "sha1-SLaZwn4zS/ifEIkr5DL25MfTSn8=", - "dev": true + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } }, "defined": { "version": "1.0.0", @@ -411,166 +487,122 @@ "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=", "dev": true }, - "delegates": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", - "dev": true - }, "deps-sort": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/deps-sort/-/deps-sort-2.0.0.tgz", "integrity": "sha1-CRckkC6EZYJg65EHSMzNGvbiH7U=", - "dev": true + "dev": true, + "requires": { + "JSONStream": "^1.0.3", + "shasum": "^1.0.0", + "subarg": "^1.0.0", + "through2": "^2.0.0" + } }, "des.js": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz", "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=", - "dev": true - }, - "detect-node": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.0.3.tgz", - "integrity": "sha1-ogM8CcyOFY03dI+951B4Mr1s4Sc=", - "dev": true + "dev": true, + "requires": { + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } }, "detective": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/detective/-/detective-4.5.0.tgz", - "integrity": "sha1-blqMaybmx6JUsca210kNmOyR7dE=", - "dev": true + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/detective/-/detective-5.2.0.tgz", + "integrity": "sha512-6SsIx+nUUbuK0EthKjv0zrdnajCCXVYGmbYYiYjFVpzcjwEs/JMDZ8tPRG29J/HhN56t3GJp2cGSWDRjjot8Pg==", + "dev": true, + "requires": { + "acorn-node": "^1.6.1", + "defined": "^1.0.0", + "minimist": "^1.1.1" + } }, "diffie-hellman": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.2.tgz", - "integrity": "sha1-tYNXOScM/ias9jIJn97SoH8gnl4=", - "dev": true + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", + "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "miller-rabin": "^4.0.0", + "randombytes": "^2.0.0" + } }, "domain-browser": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.1.7.tgz", - "integrity": "sha1-hnqksJP6oF8d4IwG9NeyH9+GmLw=", - "dev": true - }, - "drbg.js": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/drbg.js/-/drbg.js-1.0.1.tgz", - "integrity": "sha1-Pja2xCs3BDgjzbwzLVjzHiRFSAs=", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", + "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==", "dev": true }, "duplexer2": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", - "dev": true + "dev": true, + "requires": { + "readable-stream": "^2.0.2" + } }, "ecstatic": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/ecstatic/-/ecstatic-2.1.0.tgz", - "integrity": "sha1-R3pKayXOyxEvaX29LH+jVBVOpr4=", - "dev": true + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/ecstatic/-/ecstatic-3.3.1.tgz", + "integrity": "sha512-/rrctvxZ78HMI/tPIsqdvFKHHscxR3IJuKrZI2ZoUgkt2SiufyLFBmcco+aqQBIu6P1qBsUNG3drAAGLx80vTQ==", + "dev": true, + "requires": { + "he": "^1.1.1", + "mime": "^1.6.0", + "minimist": "^1.1.0", + "url-join": "^2.0.5" + } }, "elliptic": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.0.tgz", - "integrity": "sha1-ysmvh2LIWDYYcAPI3+GT5eLq5d8=", - "dev": true - }, - "end-of-stream": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.0.tgz", - "integrity": "sha1-epDYM+/abPpurA9JSduw+tOmMgY=", - "dev": true - }, - "escodegen": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.3.3.tgz", - "integrity": "sha1-8CQBb1qI4Eb9EgBQVek5gC5sXyM=", + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.1.tgz", + "integrity": "sha512-BsXLz5sqX8OHcsh7CqBMztyXARmGQ3LWPtGjJi6DiJHq5C/qvi9P3OqgswKSDftbu8+IoI/QDTAm2fFnQ9SZSQ==", "dev": true, - "dependencies": { - "source-map": { - "version": "0.1.43", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", - "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=", - "dev": true, - "optional": true - } + "requires": { + "bn.js": "^4.4.0", + "brorand": "^1.0.1", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.0" } }, - "esprima": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-1.1.1.tgz", - "integrity": "sha1-W28VR/TRAuZw4UDFCb5ncdautUk=", - "dev": true - }, - "estraverse": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.5.1.tgz", - "integrity": "sha1-hno+jlip+EYYr7bC3bzZFrfLr3E=", - "dev": true - }, - "esutils": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-1.0.0.tgz", - "integrity": "sha1-gVHTWOIMisx/t0XnRywAJf5JZXA=", - "dev": true - }, "eventemitter3": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-1.2.0.tgz", - "integrity": "sha1-HIaZHYFq0eUEdQ5zh0Ik7PO+xQg=", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.0.tgz", + "integrity": "sha512-ivIvhpq/Y0uSjcHDcOIccjmYjGLcP09MFGE7ysAwkAvkXfpZlC985pH2/ui64DKazbTW/4kN3yqozUxlXzI6cA==", "dev": true }, "events": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", - "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/events/-/events-2.1.0.tgz", + "integrity": "sha512-3Zmiobend8P9DjmKAty0Era4jV8oJ0yGYe2nJJAxgymF9+N8F2m0hhZiMoWtcfepExzNKZumFU3ksdQbInGWCg==", "dev": true }, "evp_bytestokey": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.0.tgz", - "integrity": "sha1-SXtmrZ/vZc18CKYYCCS6FHa2blM=", - "dev": true - }, - "expand-template": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-1.0.3.tgz", - "integrity": "sha1-bDAzIxd6YrGyLAcCefeGEoe2mxo=", - "dev": true - }, - "falafel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/falafel/-/falafel-1.2.0.tgz", - "integrity": "sha1-wY0k71CRF0pJfzGM0ksCaiXN2rQ=", + "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", "dev": true, - "dependencies": { - "acorn": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-1.2.2.tgz", - "integrity": "sha1-yM4n3grMdtiW0rH6099YjZ6C8BQ=", - "dev": true - }, - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - } + "requires": { + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" } }, - "flatmap": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/flatmap/-/flatmap-0.0.3.tgz", - "integrity": "sha1-Hxik2TgVLUlZZfnJWNkjqy3WabQ=", - "dev": true - }, - "foreach": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", - "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=", - "dev": true + "follow-redirects": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.6.1.tgz", + "integrity": "sha512-t2JCjbzxQpWvbhts3l6SH1DKzSrx8a+SsaVf4h6bG4kOXUuPYS/kg2Lr4gQSb7eemaHqJkOThF1BGyjlUkO1GQ==", + "dev": true, + "requires": { + "debug": "=3.1.0" + } }, "fs.realpath": { "version": "1.0.0", @@ -579,83 +611,77 @@ "dev": true }, "function-bind": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.0.tgz", - "integrity": "sha1-FhdnFMgBeY5Ojyz391KUZ7tKV3E=", - "dev": true - }, - "gauge": { - "version": "2.7.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", - "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", - "dev": true - }, - "generate-function": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz", - "integrity": "sha1-aFj+fAlpt9TpCTM3ZHrHn2DfvnQ=", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", "dev": true }, - "generate-object-property": { + "get-assigned-identifiers": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", - "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=", - "dev": true - }, - "github-from-package": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", - "integrity": "sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4=", + "resolved": "https://registry.npmjs.org/get-assigned-identifiers/-/get-assigned-identifiers-1.2.0.tgz", + "integrity": "sha512-mBBwmeGTrxEMO4pMaaf/uUEFHnYtwr8FTe8Y/mer4rcV/bye0qGm6pw1bGZFGStxC5O76c5ZAVBGnqHmOaJpdQ==", "dev": true }, "glob": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", - "dev": true - }, - "glob-escape": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/glob-escape/-/glob-escape-0.0.2.tgz", - "integrity": "sha1-nCf3gh7RwTd1gvPv2VWOP2dWKO0=", - "dev": true + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } }, "has": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.1.tgz", - "integrity": "sha1-hGFzP1OLCDfJNh45qauelwTcLyg=", - "dev": true - }, - "has-unicode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", - "dev": true + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } }, "hash-base": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-2.0.2.tgz", - "integrity": "sha1-ZuodhW206KVHDK32/OI65SRO8uE=", - "dev": true + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", + "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } }, "hash.js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.0.3.tgz", - "integrity": "sha1-EzL/ABVsCg/92CNgE9B7d6BFFXM=", - "dev": true + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } }, "he": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/he/-/he-0.5.0.tgz", - "integrity": "sha1-LAX/rvkLaOhg8/0rVO9YCYknfuI=", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", "dev": true }, "hmac-drbg": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", - "dev": true - }, + "dev": true, + "requires": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, "htmlescape": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/htmlescape/-/htmlescape-1.1.1.tgz", @@ -663,16 +689,31 @@ "dev": true }, "http-proxy": { - "version": "1.16.2", - "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.16.2.tgz", - "integrity": "sha1-Bt/ykpUr9k2+hHH6nfcwZtTzd0I=", - "dev": true + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.17.0.tgz", + "integrity": "sha512-Taqn+3nNvYRfJ3bGvKfBSRwy1v6eePlm3oc/aWVxZp57DQr5Eq3xhKJi7Z4hZpS8PC3H4qI+Yly5EmFacGuA/g==", + "dev": true, + "requires": { + "eventemitter3": "^3.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + } }, "http-server": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/http-server/-/http-server-0.10.0.tgz", - "integrity": "sha1-sqRGsWqduH7TxiK6m+sbCFsSNKc=", - "dev": true + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/http-server/-/http-server-0.11.1.tgz", + "integrity": "sha512-6JeGDGoujJLmhjiRGlt8yK8Z9Kl0vnl/dQoQZlc4oeqaUoAKQg94NILLfrY3oWzSyFaQCVNTcKE5PZ3cH8VP9w==", + "dev": true, + "requires": { + "colors": "1.0.3", + "corser": "~2.0.0", + "ecstatic": "^3.0.0", + "http-proxy": "^1.8.1", + "opener": "~1.4.0", + "optimist": "0.6.x", + "portfinder": "^1.0.13", + "union": "~0.4.3" + } }, "https-browserify": { "version": "1.0.0", @@ -681,22 +722,20 @@ "dev": true }, "ieee754": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.8.tgz", - "integrity": "sha1-vjPUCsEO8ZJnAfbwii2G+/0a0+Q=", - "dev": true - }, - "indexof": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", - "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.12.tgz", + "integrity": "sha512-GguP+DRY+pJ3soyIiGPTvdiVXjZ+DbXOxGpXn3eMvNW4x4irjqXm4wHKscC+TfxSJ0yw/S1F24tqdMNsMZTiLA==", "dev": true }, "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } }, "inherits": { "version": "2.0.3", @@ -704,166 +743,37 @@ "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", "dev": true }, - "ini": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.4.tgz", - "integrity": "sha1-BTfLedr1m1mhpRff9wbIbsA5Fi4=", - "dev": true - }, "inline-source-map": { "version": "0.6.2", "resolved": "https://registry.npmjs.org/inline-source-map/-/inline-source-map-0.6.2.tgz", "integrity": "sha1-+Tk0ccGKedFyT4Y/o4tYY3Ct4qU=", - "dev": true - }, - "insert-module-globals": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/insert-module-globals/-/insert-module-globals-7.0.1.tgz", - "integrity": "sha1-wDv04BywhtW15azorQr+eInWOMM=", - "dev": true - }, - "ip": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", - "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=", - "dev": true - }, - "ipfs-api": { - "version": "14.0.2", - "resolved": "https://registry.npmjs.org/ipfs-api/-/ipfs-api-14.0.2.tgz", - "integrity": "sha1-PDuTG3GI3HMC3CtzxGXWFMpqY0k=", "dev": true, - "dependencies": { - "async": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/async/-/async-2.4.1.tgz", - "integrity": "sha1-YqVrJ5yYoR0JhwlqAcw+6463u9c=", - "dev": true - }, - "concat-stream": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.0.tgz", - "integrity": "sha1-CqxmL9Ur54lk1VMvaUeE5wEQrPc=", - "dev": true, - "dependencies": { - "readable-stream": { - "version": "2.2.9", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.2.9.tgz", - "integrity": "sha1-z3jsb0ptHrQ9JkiMrJfwQudLf8g=", - "dev": true - } - } - }, - "qs": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.4.0.tgz", - "integrity": "sha1-E+JtKK1rD/qpExLNO/cI7TUecjM=", - "dev": true - }, - "readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dev": true, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - } - } - } + "requires": { + "source-map": "~0.5.3" } }, - "ipfs-block": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/ipfs-block/-/ipfs-block-0.6.0.tgz", - "integrity": "sha1-/qSrvHoI9eFzNwQ0glA0tnjuuNA=", - "dev": true, - "dependencies": { - "cids": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/cids/-/cids-0.4.2.tgz", - "integrity": "sha1-8UFOePpGb+l6fOnNbAOJKZO+8wc=", - "dev": true - } - } - }, - "ipfs-unixfs": { - "version": "0.1.11", - "resolved": "https://registry.npmjs.org/ipfs-unixfs/-/ipfs-unixfs-0.1.11.tgz", - "integrity": "sha1-RZfqYNOkxR7T4F2hB+BHOwGES9Q=", - "dev": true - }, - "ipld-dag-pb": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/ipld-dag-pb/-/ipld-dag-pb-0.11.0.tgz", - "integrity": "sha1-DrFpJSmuurr+j177SE43R3DgDIU=", + "insert-module-globals": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/insert-module-globals/-/insert-module-globals-7.2.0.tgz", + "integrity": "sha512-VE6NlW+WGn2/AeOMd496AHFYmE7eLKkUY6Ty31k4og5vmA3Fjuwe9v6ifH6Xx/Hz27QvdoMoviw1/pqWRB09Sw==", "dev": true, - "dependencies": { - "async": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/async/-/async-2.4.1.tgz", - "integrity": "sha1-YqVrJ5yYoR0JhwlqAcw+6463u9c=", - "dev": true - }, - "cids": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/cids/-/cids-0.4.2.tgz", - "integrity": "sha1-8UFOePpGb+l6fOnNbAOJKZO+8wc=", - "dev": true - } + "requires": { + "JSONStream": "^1.0.3", + "acorn-node": "^1.5.2", + "combine-source-map": "^0.8.0", + "concat-stream": "^1.6.1", + "is-buffer": "^1.1.0", + "path-is-absolute": "^1.0.1", + "process": "~0.11.0", + "through2": "^2.0.0", + "undeclared-identifiers": "^1.1.2", + "xtend": "^4.0.0" } }, "is-buffer": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.5.tgz", - "integrity": "sha1-Hzsm72E7IUuIy8ojzGwB2Hlh7sw=", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true - }, - "is-ipfs": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/is-ipfs/-/is-ipfs-0.3.0.tgz", - "integrity": "sha1-yZNfIrGd9QqX57Jl+VreTCka05U=", - "dev": true, - "dependencies": { - "multihashes": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/multihashes/-/multihashes-0.3.3.tgz", - "integrity": "sha1-GNdNjCOTrzmq8KyPT9bYiNQ/Lyk=", - "dev": true - } - } - }, - "is-promise": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-1.0.1.tgz", - "integrity": "sha1-MVc3YcBX4zwukaq56W2gjO++duU=", - "dev": true - }, - "is-property": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", - "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=", - "dev": true - }, - "is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", "dev": true }, "isarray": { @@ -872,29 +782,14 @@ "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", "dev": true }, - "isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", - "dev": true - }, - "js-sha3": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.5.7.tgz", - "integrity": "sha1-DU/9gALVMzqrr0oj7tL2N0yfKOc=", - "dev": true - }, "json-stable-stringify": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-0.0.1.tgz", "integrity": "sha1-YRwj6BTbN1Un34URk9tZ3Sryf0U=", - "dev": true - }, - "json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", - "dev": true + "dev": true, + "requires": { + "jsonify": "~0.0.0" + } }, "jsonify": { "version": "0.0.0", @@ -908,118 +803,62 @@ "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", "dev": true }, - "JSONStream": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.1.tgz", - "integrity": "sha1-cH92HgHa6eFvG8+TcDt4xwlmV5o=", - "dev": true - }, - "keypair": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/keypair/-/keypair-1.0.1.tgz", - "integrity": "sha1-dgNxknCvtlZO04oiCHoG/Jqk6hs=", - "dev": true - }, "labeled-stream-splicer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/labeled-stream-splicer/-/labeled-stream-splicer-2.0.0.tgz", - "integrity": "sha1-pS4dE4AkwAuGscDJH2d5GLiuClk=", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/labeled-stream-splicer/-/labeled-stream-splicer-2.0.1.tgz", + "integrity": "sha512-MC94mHZRvJ3LfykJlTUipBqenZz1pacOZEMhhQ8dMGcDHs0SBE5GbsavUXV7YtP3icBW17W0Zy1I0lfASmo9Pg==", "dev": true, + "requires": { + "inherits": "^2.0.1", + "isarray": "^2.0.4", + "stream-splicer": "^2.0.0" + }, "dependencies": { "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.4.tgz", + "integrity": "sha512-GMxXOiUirWg1xTKRipM0Ek07rX+ubx4nNVElTJdNLYmNO/2YrDkgJGw9CljXn+r4EWiDQg/8lsRdHyg2PJuUaA==", "dev": true } } }, - "lexical-scope": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/lexical-scope/-/lexical-scope-1.2.0.tgz", - "integrity": "sha1-/Ope3HBKSzqHls3KQZw6CvryLfQ=", - "dev": true - }, - "libp2p-crypto": { - "version": "0.8.8", - "resolved": "https://registry.npmjs.org/libp2p-crypto/-/libp2p-crypto-0.8.8.tgz", - "integrity": "sha1-3IpJy87bUjnel3YZ8tGN+fwRDzk=", - "dev": true, - "dependencies": { - "async": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/async/-/async-2.4.1.tgz", - "integrity": "sha1-YqVrJ5yYoR0JhwlqAcw+6463u9c=", - "dev": true - } - } - }, - "libp2p-crypto-secp256k1": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/libp2p-crypto-secp256k1/-/libp2p-crypto-secp256k1-0.1.4.tgz", - "integrity": "sha1-IRN4/jqFnYmtEgOqng111obIW98=", - "dev": true, - "dependencies": { - "async": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/async/-/async-2.4.1.tgz", - "integrity": "sha1-YqVrJ5yYoR0JhwlqAcw+6463u9c=", - "dev": true - } - } - }, - "lodash": { - "version": "4.17.4", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", - "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=", - "dev": true - }, - "lodash.filter": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.filter/-/lodash.filter-4.6.0.tgz", - "integrity": "sha1-ZosdSYFgOuHMWm+nYBQ+SAtMSs4=", - "dev": true - }, - "lodash.map": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.map/-/lodash.map-4.6.0.tgz", - "integrity": "sha1-dx7Hg540c9nEzeKLGTlMNWL09tM=", - "dev": true - }, "lodash.memoize": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-3.0.4.tgz", "integrity": "sha1-LcvSwofLwKVcxCMovQxzYVDVPj8=", "dev": true }, - "lodash.uniqby": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/lodash.uniqby/-/lodash.uniqby-4.7.0.tgz", - "integrity": "sha1-2ZwHpmnp5tJOE2Lf4mbGdhavEwI=", - "dev": true - }, - "lru-cache": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.0.2.tgz", - "integrity": "sha1-HRdnnAac2l0ECZGgnbwsDbN35V4=", - "dev": true + "md5.js": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", + "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "dev": true, + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } }, "miller-rabin": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.0.tgz", - "integrity": "sha1-SmL7HUKTPAVYOYL0xxb2+55sbT0=", - "dev": true + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", + "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "dev": true, + "requires": { + "bn.js": "^4.0.0", + "brorand": "^1.0.1" + } }, "mime": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.3.6.tgz", - "integrity": "sha1-WR2E02U6awtKO5343lqoEI5y5eA=", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", "dev": true }, "minimalistic-assert": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.0.tgz", - "integrity": "sha1-cCvi3aazf0g2vLP121ZkG2Sh09M=", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", "dev": true }, "minimalistic-crypto-utils": { @@ -1032,7 +871,10 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } }, "minimist": { "version": "1.2.0", @@ -1045,6 +887,9 @@ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", "dev": true, + "requires": { + "minimist": "0.0.8" + }, "dependencies": { "minimist": { "version": "0.0.8", @@ -1055,10 +900,27 @@ } }, "module-deps": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/module-deps/-/module-deps-4.1.1.tgz", - "integrity": "sha1-IyFYM/HaE/1gbMuAh7RIUty4If0=", - "dev": true + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/module-deps/-/module-deps-6.2.0.tgz", + "integrity": "sha512-hKPmO06so6bL/ZvqVNVqdTVO8UAYsi3tQWlCa+z9KuWhoN4KDQtb5hcqQQv58qYiDE21wIvnttZEPiDgEbpwbA==", + "dev": true, + "requires": { + "JSONStream": "^1.0.3", + "browser-resolve": "^1.7.0", + "cached-path-relative": "^1.0.0", + "concat-stream": "~1.6.0", + "defined": "^1.0.0", + "detective": "^5.0.2", + "duplexer2": "^0.1.2", + "inherits": "^2.0.1", + "parents": "^1.0.0", + "readable-stream": "^2.0.2", + "resolve": "^1.4.0", + "stream-combiner2": "^1.1.1", + "subarg": "^1.0.0", + "through2": "^2.0.0", + "xtend": "^4.0.0" + } }, "ms": { "version": "2.0.0", @@ -1066,136 +928,14 @@ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", "dev": true }, - "multiaddr": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/multiaddr/-/multiaddr-2.3.0.tgz", - "integrity": "sha1-VmNIJPSLy9hAX9VDTDGyd0JMYvw=", - "dev": true - }, - "multibase": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/multibase/-/multibase-0.3.4.tgz", - "integrity": "sha1-+6iwqslyT2LiR4JVfioGLjDTrn8=", - "dev": true, - "dependencies": { - "base-x": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.0.tgz", - "integrity": "sha1-d7VvAxEHC3gLPIpfU0vqxH5QZwI=", - "dev": true - } - } - }, - "multicodec": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/multicodec/-/multicodec-0.1.7.tgz", - "integrity": "sha1-ZY8tFfQvoZ5mCS/pF6BRob8H5B4=", - "dev": true - }, - "multihashes": { - "version": "0.4.5", - "resolved": "https://registry.npmjs.org/multihashes/-/multihashes-0.4.5.tgz", - "integrity": "sha1-mwU8Uf3HTXce3eIOG8kdS77D+mk=", - "dev": true - }, - "multihashing-async": { - "version": "0.4.5", - "resolved": "https://registry.npmjs.org/multihashing-async/-/multihashing-async-0.4.5.tgz", - "integrity": "sha1-6UtAimjDbDkxgBRuP62RJhCOtqk=", - "dev": true, - "dependencies": { - "async": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/async/-/async-2.4.1.tgz", - "integrity": "sha1-YqVrJ5yYoR0JhwlqAcw+6463u9c=", - "dev": true - } - } - }, - "multipart-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/multipart-stream/-/multipart-stream-2.0.1.tgz", - "integrity": "sha1-GVyctLLEHnjHKh6POMfQ66HNC6A=", - "dev": true - }, - "murmurhash3js": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/murmurhash3js/-/murmurhash3js-3.0.1.tgz", - "integrity": "sha1-Ppg+W0fCoG9DpxMXTn5DXKBEuZg=", - "dev": true - }, - "nan": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.6.2.tgz", - "integrity": "sha1-5P805slf37WuzAjeZZb0NgWn20U=", - "dev": true - }, - "ndjson": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/ndjson/-/ndjson-1.5.0.tgz", - "integrity": "sha1-rmA7NrE0vOw0e0UkIrC/mNWDLsg=", - "dev": true - }, - "node-abi": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.0.2.tgz", - "integrity": "sha1-APPgpYEA60gBM7SMmaMswfnmyT4=", - "dev": true - }, - "node-webcrypto-ossl": { - "version": "1.0.24", - "resolved": "https://registry.npmjs.org/node-webcrypto-ossl/-/node-webcrypto-ossl-1.0.24.tgz", - "integrity": "sha1-HuMdbHZDuG+0mgkYjwK0mv5DZ2k=", - "dev": true, - "optional": true - }, - "nodeify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/nodeify/-/nodeify-1.0.1.tgz", - "integrity": "sha1-ZKtpp7268DzhB7TwM1yHwLnpGx0=", - "dev": true - }, - "noop-logger": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/noop-logger/-/noop-logger-0.1.1.tgz", - "integrity": "sha1-lKKxYzxPExdVMAfYlm/Q6EG2pMI=", - "dev": true - }, - "npmlog": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.0.tgz", - "integrity": "sha512-ocolIkZYZt8UveuiDS0yAkkIjid1o7lPG8cYm05yNYzBn8ykQtaiPMEGp8fY9tKdDgm8okpdKzkvu1y9hUYugA==", - "dev": true - }, - "number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", - "dev": true - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true - }, - "object-inspect": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-0.4.0.tgz", - "integrity": "sha1-9RV8EWwUVbJDsG7pdwM5LFrYn+w=", - "dev": true - }, - "object-keys": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.11.tgz", - "integrity": "sha1-xUYBd4rVYPEULODgG8yotW0TQm0=", - "dev": true - }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true + "dev": true, + "requires": { + "wrappy": "1" + } }, "opener": { "version": "1.4.3", @@ -1208,6 +948,10 @@ "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", "dev": true, + "requires": { + "minimist": "~0.0.1", + "wordwrap": "~0.0.2" + }, "dependencies": { "minimist": { "version": "0.0.10", @@ -1218,39 +962,44 @@ } }, "os-browserify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.1.2.tgz", - "integrity": "sha1-ScoCk+CxlZCl9d4Qx/JlphfY/lQ=", - "dev": true - }, - "os-homedir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", + "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=", "dev": true }, "pako": { - "version": "0.2.9", - "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", - "integrity": "sha1-8/dSL073gjSNqBYbrZ7P1Rv4OnU=", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.8.tgz", + "integrity": "sha512-6i0HVbUfcKaTv+EG8ZTr75az7GFXcLYk9UyLEg7Notv/Ma+z/UG3TCoz6GiNeOrn1E/e63I0X/Hpw18jHOTUnA==", "dev": true }, "parents": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parents/-/parents-1.0.1.tgz", "integrity": "sha1-/t1NK/GTp3dF/nHjcdc8MwfZx1E=", - "dev": true + "dev": true, + "requires": { + "path-platform": "~0.11.15" + } }, "parse-asn1": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.0.tgz", - "integrity": "sha1-N8T5t+06tlx0gXtfJICTf7+XxxI=", - "dev": true + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.3.tgz", + "integrity": "sha512-VrPoetlz7B/FqjBLD2f5wBVZvsZVLnRUrxVLfRYhGXCODa/NWE4p3Wp+6+aV3ZPL3KM7/OZmxDIwwijD7yuucg==", + "dev": true, + "requires": { + "asn1.js": "^4.0.0", + "browserify-aes": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.0", + "pbkdf2": "^3.0.3", + "safe-buffer": "^5.1.1" + } }, "path-browserify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz", - "integrity": "sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo=", + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.1.tgz", + "integrity": "sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ==", "dev": true }, "path-is-absolute": { @@ -1260,9 +1009,9 @@ "dev": true }, "path-parse": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz", - "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", "dev": true }, "path-platform": { @@ -1272,64 +1021,40 @@ "dev": true }, "pbkdf2": { - "version": "3.0.12", - "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.12.tgz", - "integrity": "sha1-vjZ4XFBn6kjYBv+SMojF91C2uKI=", - "dev": true - }, - "peer-id": { - "version": "0.8.7", - "resolved": "https://registry.npmjs.org/peer-id/-/peer-id-0.8.7.tgz", - "integrity": "sha1-yb2dFYjUzM5xdSqQSa+p8QF2oz0=", + "version": "3.0.17", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.17.tgz", + "integrity": "sha512-U/il5MsrZp7mGg3mSQfn742na2T+1/vHDCG5/iTI3X9MKUuYUZVLQhyRsg06mCgDBTd57TxzgZt7P+fYfjRLtA==", "dev": true, - "dependencies": { - "async": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/async/-/async-2.4.1.tgz", - "integrity": "sha1-YqVrJ5yYoR0JhwlqAcw+6463u9c=", - "dev": true - } + "requires": { + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4", + "ripemd160": "^2.0.1", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" } }, - "peer-info": { - "version": "0.9.2", - "resolved": "https://registry.npmjs.org/peer-info/-/peer-info-0.9.2.tgz", - "integrity": "sha1-15sWsXr/UnVwtrrqkTRjSeay0Lw=", - "dev": true - }, - "pem-jwk": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/pem-jwk/-/pem-jwk-1.5.1.tgz", - "integrity": "sha1-eoY3/S9nqCflfAxC4cI8P9Us+wE=", + "portfinder": { + "version": "1.0.20", + "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.20.tgz", + "integrity": "sha512-Yxe4mTyDzTd59PZJY4ojZR8F+E5e97iq2ZOHPz3HDgSvYC5siNad2tLooQ5y5QHyQhc3xVqvyk/eNA3wuoa7Sw==", "dev": true, + "requires": { + "async": "^1.5.2", + "debug": "^2.2.0", + "mkdirp": "0.5.x" + }, "dependencies": { - "asn1.js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-1.0.3.tgz", - "integrity": "sha1-KBuj7B8kSP52X5Kk7s+IP+E2S1Q=", - "dev": true - }, - "bn.js": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-1.3.0.tgz", - "integrity": "sha1-DbTL+W+PI7dC9by50ap6mZSgXoM=", + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, - "optional": true + "requires": { + "ms": "2.0.0" + } } } }, - "portfinder": { - "version": "1.0.13", - "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.13.tgz", - "integrity": "sha1-uzLs2HwnEErm7kS1o8y/Drsa7ek=", - "dev": true - }, - "prebuild-install": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-2.1.2.tgz", - "integrity": "sha1-2a4MqFMw4Dli2TKS+VqLRMLr9QU=", - "dev": true - }, "process": { "version": "0.11.10", "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", @@ -1337,64 +1062,24 @@ "dev": true }, "process-nextick-args": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", - "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", - "dev": true - }, - "promise": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/promise/-/promise-1.3.0.tgz", - "integrity": "sha1-5cyaTIJ45GZP/twBx9qEhCsEAXU=", - "dev": true - }, - "promisify-es6": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/promisify-es6/-/promisify-es6-1.0.2.tgz", - "integrity": "sha1-Ywk1U+Ob5QNtdXtFX7k9FV2ktYk=", - "dev": true - }, - "protocol-buffers": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/protocol-buffers/-/protocol-buffers-3.2.1.tgz", - "integrity": "sha1-NyWOF+JKCC8G67F3MekoUdHHaIk=", - "dev": true - }, - "protocol-buffers-schema": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/protocol-buffers-schema/-/protocol-buffers-schema-3.3.1.tgz", - "integrity": "sha1-rRURQYd8aviChkeFGvZqDbaSdfU=", - "dev": true - }, - "pseudomap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", "dev": true }, "public-encrypt": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.0.tgz", - "integrity": "sha1-OfaZ86RlYN1eusvKaTyvfGXBjMY=", - "dev": true - }, - "pull-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/pull-stream/-/pull-stream-3.6.0.tgz", - "integrity": "sha1-WdAzpoFdTjCX1Hw9KxiTqeWKI1E=", - "dev": true - }, - "pull-traverse": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/pull-traverse/-/pull-traverse-1.0.3.tgz", - "integrity": "sha1-dPtde+f6a9enjpeTPhmbeUWGaTg=", - "dev": true - }, - "pump": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pump/-/pump-1.0.2.tgz", - "integrity": "sha1-Oz7mUS+U8OV1U4wXmV+fFpkKXVE=", - "dev": true + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", + "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "parse-asn1": "^5.0.0", + "randombytes": "^2.0.1", + "safe-buffer": "^5.1.2" + } }, "punycode": { "version": "1.4.1", @@ -1420,35 +1105,59 @@ "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=", "dev": true }, - "quote-stream": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/quote-stream/-/quote-stream-1.0.2.tgz", - "integrity": "sha1-hJY/jJwmuULhU/7rU6rnRlK34LI=", - "dev": true - }, "randombytes": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.3.tgz", - "integrity": "sha1-Z0yZdgkBw8QRJ3GjHlIdw0nMCew=", - "dev": true + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.6.tgz", + "integrity": "sha512-CIQ5OFxf4Jou6uOKe9t1AOgqpeU5fd70A8NPdHSGeYXqXsPe6peOwI0cUl88RWZ6sP1vPMV3avd/R6cZ5/sP1A==", + "dev": true, + "requires": { + "safe-buffer": "^5.1.0" + } }, - "rc": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.1.tgz", - "integrity": "sha1-LgPo5C7kULjLPc5lvhv4l04d/ZU=", - "dev": true + "randomfill": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", + "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", + "dev": true, + "requires": { + "randombytes": "^2.0.5", + "safe-buffer": "^5.1.0" + } }, "read-only-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/read-only-stream/-/read-only-stream-2.0.0.tgz", "integrity": "sha1-JyT9aoET1zdkrCiNQ4YnDB2/F/A=", - "dev": true + "dev": true, + "requires": { + "readable-stream": "^2.0.2" + } }, "readable-stream": { - "version": "2.2.9", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.2.9.tgz", - "integrity": "sha1-z3jsb0ptHrQ9JkiMrJfwQudLf8g=", - "dev": true + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "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.1" + }, + "dependencies": { + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } }, "requires-port": { "version": "1.0.0", @@ -1457,330 +1166,143 @@ "dev": true }, "resolve": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.3.3.tgz", - "integrity": "sha1-ZVkHw0aahoDcLeOidaj91paR8OU=", - "dev": true - }, - "ripemd160": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.1.tgz", - "integrity": "sha1-D0WEKVxTo2KK9+bXmsohzlfRxuc=", - "dev": true - }, - "rsa-pem-to-jwk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/rsa-pem-to-jwk/-/rsa-pem-to-jwk-1.1.3.tgz", - "integrity": "sha1-JF52vbfnI0z+58oDLTG1TDj6uY4=", + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.10.0.tgz", + "integrity": "sha512-3sUr9aq5OfSg2S9pNtPA9hL1FVEAjvfOC4leW0SNf/mpnaakz2a9femSd6LqAww2RaFctwyf1lCqnTHuF1rxDg==", "dev": true, - "dependencies": { - "object-assign": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-2.1.1.tgz", - "integrity": "sha1-Q8NuXVaf+OSBbE76i+AtJpZ8GKo=", - "dev": true - } + "requires": { + "path-parse": "^1.0.6" } }, - "rsa-unpack": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/rsa-unpack/-/rsa-unpack-0.0.6.tgz", - "integrity": "sha1-9Q69VqYoN45jHylxYQJs6atO3bo=", + "ripemd160": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", + "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", "dev": true, - "dependencies": { - "optimist": { - "version": "0.3.7", - "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.3.7.tgz", - "integrity": "sha1-yQlBrVnkJzMokjB00s8ufLxuwNk=", - "dev": true - } + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" } }, "safe-buffer": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.0.1.tgz", - "integrity": "sha1-0mPKVGls2KMGtcplUekt5XkY++c=", - "dev": true - }, - "sandwich-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/sandwich-stream/-/sandwich-stream-1.0.0.tgz", - "integrity": "sha1-eDDkV5e1kzKH8fmyj4cZB0ViYvI=", - "dev": true - }, - "secp256k1": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-3.2.5.tgz", - "integrity": "sha1-Dd5bJ+UCFmX23/ynssPgEMbBPJM=", - "dev": true - }, - "set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "dev": true }, "sha.js": { - "version": "2.4.8", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.8.tgz", - "integrity": "sha1-NwaMLEdra69ALRSknGf1l5IfY08=", - "dev": true - }, - "shallow-copy": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/shallow-copy/-/shallow-copy-0.0.1.tgz", - "integrity": "sha1-QV9CcC1z2BAzApLMXuhurhoRoXA=", - "dev": true + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } }, "shasum": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/shasum/-/shasum-1.0.2.tgz", "integrity": "sha1-5wEjENj0F/TetXEhUOVni4euVl8=", - "dev": true + "dev": true, + "requires": { + "json-stable-stringify": "~0.0.0", + "sha.js": "~2.4.4" + } }, "shell-quote": { "version": "1.6.1", "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.6.1.tgz", "integrity": "sha1-9HgZSczkAmlxJ0MOo7PFR29IF2c=", - "dev": true - }, - "signal-exit": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", - "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", - "dev": true - }, - "signed-varint": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/signed-varint/-/signed-varint-2.0.1.tgz", - "integrity": "sha1-UKmYnafJjCxh2tEZvJdHDvhSgSk=", - "dev": true + "dev": true, + "requires": { + "array-filter": "~0.0.0", + "array-map": "~0.0.0", + "array-reduce": "~0.0.0", + "jsonify": "~0.0.0" + } }, - "simple-get": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-1.4.3.tgz", - "integrity": "sha1-6XVe2kB+ltpAxeUVjJ6jezO+y+s=", + "simple-concat": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.0.tgz", + "integrity": "sha1-c0TLuLbib7J9ZrL8hvn21Zl1IcY=", "dev": true }, "source-map": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz", - "integrity": "sha1-dc449SvwczxafwwRjYEzSiu19BI=", - "dev": true - }, - "split2": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/split2/-/split2-2.1.1.tgz", - "integrity": "sha1-eh9VHhdqkOzTNF9yRqDP4XXvT9A=", - "dev": true - }, - "stable": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.6.tgz", - "integrity": "sha1-kQ9dKu17Ugxud3SZwfMuE5/eyxA=", + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", "dev": true }, - "static-eval": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/static-eval/-/static-eval-0.2.4.tgz", - "integrity": "sha1-t9NNg4k3uWn5ZBygfUj47eJj6ns=", + "stream-browserify": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz", + "integrity": "sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg==", "dev": true, - "dependencies": { - "escodegen": { - "version": "0.0.28", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-0.0.28.tgz", - "integrity": "sha1-Dk/xcV8yh3XWyrUaxEpAbNer/9M=", - "dev": true - }, - "esprima": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-1.0.4.tgz", - "integrity": "sha1-n1V+CPw7TSbs6d00+Pv0drYlha0=", - "dev": true - }, - "estraverse": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.3.2.tgz", - "integrity": "sha1-N8K4k+8T1yPydth41g2FNRUqbEI=", - "dev": true - } + "requires": { + "inherits": "~2.0.1", + "readable-stream": "^2.0.2" } }, - "static-module": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/static-module/-/static-module-1.3.2.tgz", - "integrity": "sha1-Mp+58iOlZiZr2nGEO32TLHZxdPM=", - "dev": true, - "dependencies": { - "concat-stream": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.0.tgz", - "integrity": "sha1-CqxmL9Ur54lk1VMvaUeE5wEQrPc=", - "dev": true, - "dependencies": { - "readable-stream": { - "version": "2.2.9", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.2.9.tgz", - "integrity": "sha1-z3jsb0ptHrQ9JkiMrJfwQudLf8g=", - "dev": true - } - } - }, - "duplexer2": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz", - "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=", - "dev": true, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dev": true - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - } - } - }, - "minimist": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", - "dev": true - }, - "object-keys": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz", - "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=", - "dev": true - }, - "quote-stream": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/quote-stream/-/quote-stream-0.0.0.tgz", - "integrity": "sha1-zeKelMQJsW4Z3HCYuJtmWPlyHTs=", - "dev": true - }, - "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - } - } - }, - "through2": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.4.2.tgz", - "integrity": "sha1-2/WGYDEVHsg1K7bE22SiKSqEC5s=", - "dev": true - }, - "xtend": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz", - "integrity": "sha1-bv7MKk2tjmlixJAbM3znuoe10os=", - "dev": true - } - } - }, - "stream-browserify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.1.tgz", - "integrity": "sha1-ZiZu5fm9uZQKTkUUyvtDu3Hlyds=", - "dev": true - }, "stream-combiner2": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/stream-combiner2/-/stream-combiner2-1.1.1.tgz", "integrity": "sha1-+02KFCDqNidk4hrUeAOXvry0HL4=", - "dev": true + "dev": true, + "requires": { + "duplexer2": "~0.1.0", + "readable-stream": "^2.0.2" + } }, "stream-http": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.7.1.tgz", - "integrity": "sha1-VGpRdBrVprB+njGwsQRBqRffUoo=", - "dev": true + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz", + "integrity": "sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==", + "dev": true, + "requires": { + "builtin-status-codes": "^3.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.3.6", + "to-arraybuffer": "^1.0.0", + "xtend": "^4.0.0" + } }, "stream-splicer": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/stream-splicer/-/stream-splicer-2.0.0.tgz", "integrity": "sha1-G2O+Q4oTPktnHMGTUZdgAXWRDYM=", - "dev": true - }, - "streamifier": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/streamifier/-/streamifier-0.1.1.tgz", - "integrity": "sha1-l+mNj6TRBdYqJpHR3AfoINuN/E8=", - "dev": true + "dev": true, + "requires": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.2" + } }, "string_decoder": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.1.tgz", - "integrity": "sha1-YuIA8DmVWmgQ2N8KM//A8BNmLZg=", - "dev": true - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true - }, - "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 + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.2.0.tgz", + "integrity": "sha512-6YqyX6ZWEYguAxgZzHGL7SsCeGx3V2TtOTqZz1xSTSWnqsbWwbptafNyvf/ACquZUXV3DANr5BDIwNYe1mN42w==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } }, "subarg": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/subarg/-/subarg-1.0.0.tgz", "integrity": "sha1-9izxdYHplrSPyWVpn1TAauJouNI=", - "dev": true + "dev": true, + "requires": { + "minimist": "^1.1.0" + } }, "syntax-error": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/syntax-error/-/syntax-error-1.3.0.tgz", - "integrity": "sha1-HtkmbE1AvnXcVb+bsct3Biu5bKE=", - "dev": true - }, - "tar-fs": { - "version": "1.15.2", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-1.15.2.tgz", - "integrity": "sha1-dh9bMpMsezlGGmDVN/rqDYCEgww=", - "dev": true - }, - "tar-stream": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.5.4.tgz", - "integrity": "sha1-NlSc8E7RrumyowwBQyUiONr5QBY=", - "dev": true + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/syntax-error/-/syntax-error-1.4.0.tgz", + "integrity": "sha512-YPPlu67mdnHGTup2A8ff7BC2Pjq0e0Yp/IyTFN03zWO0RcK07uLcbi7C2KpGR2FvWbaB0+bfE27a+sBKebSo7w==", + "dev": true, + "requires": { + "acorn-node": "^1.2.0" + } }, "through": { "version": "2.3.8", @@ -1789,16 +1311,23 @@ "dev": true }, "through2": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", - "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", - "dev": true + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } }, "timers-browserify": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-1.4.2.tgz", "integrity": "sha1-ycWLV1voQHN1y14kYtrO50NZ9B0=", - "dev": true + "dev": true, + "requires": { + "process": "~0.11.0" + } }, "to-arraybuffer": { "version": "1.0.1", @@ -1806,28 +1335,10 @@ "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=", "dev": true }, - "tslib": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.7.1.tgz", - "integrity": "sha1-vIAEFkaRkjp5/oN4u+s9ogF1OOw=", - "dev": true - }, "tty-browserify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", - "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=", - "dev": true - }, - "tunnel-agent": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz", - "integrity": "sha1-Y3PbdpCf5XDgjXNYM2Xtgop07us=", - "dev": true - }, - "tweetnacl": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.0.tgz", - "integrity": "sha1-cT2LgY2kIGh0C/aDhtBHnmb8ins=", + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.1.tgz", + "integrity": "sha512-C3TaO7K81YvjCgQH9Q1S3R3P3BtN3RIM8n+OvX4il1K1zgE8ZhI0op7kClgkxtutIE8hQrcrHBXvIheqKUUCxw==", "dev": true }, "typedarray": { @@ -1836,36 +1347,42 @@ "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", "dev": true }, - "typescript": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.3.3.tgz", - "integrity": "sha1-ljnzw7QBSOjKl/4IpR3RiRu2viI=", - "dev": true, - "optional": true - }, "umd": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/umd/-/umd-3.0.1.tgz", - "integrity": "sha1-iuVW4RAR9jwllnCKiDclnwGz1g4=", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/umd/-/umd-3.0.3.tgz", + "integrity": "sha512-4IcGSufhFshvLNcMCV80UnQVlZ5pMOC8mvNPForqwA4+lzYQuetTESLDQkeLmihq8bRcnpbQa48Wb8Lh16/xow==", "dev": true }, + "undeclared-identifiers": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/undeclared-identifiers/-/undeclared-identifiers-1.1.2.tgz", + "integrity": "sha512-13EaeocO4edF/3JKime9rD7oB6QI8llAGhgn5fKOPyfkJbRb6NFv9pYV6dFEmpa4uRjKeBqLZP8GpuzqHlKDMQ==", + "dev": true, + "requires": { + "acorn-node": "^1.3.0", + "get-assigned-identifiers": "^1.2.0", + "simple-concat": "^1.0.0", + "xtend": "^4.0.1" + } + }, "union": { "version": "0.4.6", "resolved": "https://registry.npmjs.org/union/-/union-0.4.6.tgz", "integrity": "sha1-GY+9rrolTniLDvy2MLwR8kopWeA=", - "dev": true - }, - "unzip-response": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/unzip-response/-/unzip-response-1.0.2.tgz", - "integrity": "sha1-uYTwh3/AqJwsdzzB73tbIytbBv4=", - "dev": true + "dev": true, + "requires": { + "qs": "~2.3.3" + } }, "url": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", "dev": true, + "requires": { + "punycode": "1.3.2", + "querystring": "0.2.0" + }, "dependencies": { "punycode": { "version": "1.3.2", @@ -1876,23 +1393,18 @@ } }, "url-join": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/url-join/-/url-join-1.1.0.tgz", - "integrity": "sha1-dBxsL0WWxIMNZxhGCSDQySIC3Hg=", + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/url-join/-/url-join-2.0.5.tgz", + "integrity": "sha1-WvIvGMBSoACkjXuCxenC4v7tpyg=", "dev": true }, "util": { - "version": "0.10.3", - "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", - "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", + "version": "0.10.4", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz", + "integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==", "dev": true, - "dependencies": { - "inherits": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", - "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", - "dev": true - } + "requires": { + "inherits": "2.0.3" } }, "util-deprecate": { @@ -1901,33 +1413,10 @@ "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", "dev": true }, - "varint": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/varint/-/varint-5.0.0.tgz", - "integrity": "sha1-2Ca4n3SQcy+rwMDtaT7Uddyynr8=", - "dev": true - }, "vm-browserify": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz", - "integrity": "sha1-XX6kW7755Kb/ZflUOOCofDV9WnM=", - "dev": true - }, - "webcrypto-core": { - "version": "0.1.16", - "resolved": "https://registry.npmjs.org/webcrypto-core/-/webcrypto-core-0.1.16.tgz", - "integrity": "sha1-3kkUtZFI23Moe8T45hz0+y9W8CA=", - "dev": true, - "optional": true - }, - "webcrypto-shim": { - "version": "github:dignifiedquire/webcrypto-shim#effe03d3401ccbfb4837191bc393bb347e0c0f0a", - "dev": true - }, - "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==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.0.tgz", + "integrity": "sha512-iq+S7vZJE60yejDYM0ek6zg308+UZsdtPExWP9VZoCFCz1zkJoXFnAX7aZfd/ZwrkidzdUZL0C/ryW+JwAiIGw==", "dev": true }, "wordwrap": { @@ -1947,12 +1436,6 @@ "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", "dev": true - }, - "yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", - "dev": true } } } diff --git a/examples/name-api/package.json b/examples/name-api/package.json index b8b0cab35..697ffb68a 100644 --- a/examples/name-api/package.json +++ b/examples/name-api/package.json @@ -9,7 +9,7 @@ "author": "Tara Vancil ", "license": "MIT", "devDependencies": { - "browserify": "^14.4.0", - "http-server": "~0.10.0" + "browserify": "^16.2.3", + "http-server": "^0.11.1" } } From eb4f8bd9a8860fed733968ec96ad0c6ac3ca115f Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Wed, 13 Feb 2019 06:20:52 +0000 Subject: [PATCH 009/233] docs: update bundle-webpack example (#945) License: MIT Signed-off-by: Alan Shaw --- examples/bundle-webpack/.babelrc | 3 --- examples/bundle-webpack/package.json | 24 +++++++++++++++-------- examples/bundle-webpack/src/App.js | 10 ++-------- examples/bundle-webpack/src/index.js | 3 ++- examples/bundle-webpack/webpack.config.js | 22 ++++++++++++++------- 5 files changed, 35 insertions(+), 27 deletions(-) delete mode 100644 examples/bundle-webpack/.babelrc diff --git a/examples/bundle-webpack/.babelrc b/examples/bundle-webpack/.babelrc deleted file mode 100644 index b0b9a96ef..000000000 --- a/examples/bundle-webpack/.babelrc +++ /dev/null @@ -1,3 +0,0 @@ -{ - "stage": 0 -} diff --git a/examples/bundle-webpack/package.json b/examples/bundle-webpack/package.json index bd72b6710..48ecb1ec5 100644 --- a/examples/bundle-webpack/package.json +++ b/examples/bundle-webpack/package.json @@ -9,13 +9,21 @@ "license": "MIT", "keywords": [], "devDependencies": { - "babel-core": "^5.4.7", - "babel-loader": "^5.1.2", + "@babel/core": "^7.2.2", + "@babel/preset-env": "^7.3.1", + "@babel/preset-react": "^7.0.0", + "babel-loader": "^8.0.5", "ipfs-http-client": "../../", - "json-loader": "~0.5.3", - "react": "~0.13.0", - "react-hot-loader": "^1.3.0", - "webpack": "^1.9.6", - "webpack-dev-server": "^1.8.2" - } + "react": "^16.8.1", + "react-dom": "^16.8.1", + "react-hot-loader": "^4.6.5", + "webpack": "^4.29.3", + "webpack-dev-server": "^3.1.14" + }, + "browserslist": [ + ">1%", + "not dead", + "not ie <= 11", + "not op_mini all" + ] } diff --git a/examples/bundle-webpack/src/App.js b/examples/bundle-webpack/src/App.js index 50889088c..155c6897e 100644 --- a/examples/bundle-webpack/src/App.js +++ b/examples/bundle-webpack/src/App.js @@ -29,15 +29,9 @@ class App extends React.Component { if (err) throw err const hash = res[0].hash this.setState({added_file_hash: hash}) - ipfs.cat(hash, (err, res) => { + ipfs.cat(hash, (err, data) => { if (err) throw err - let data = '' - res.on('data', (d) => { - data = data + d - }) - res.on('end', () => { - this.setState({added_file_contents: data}) - }) + this.setState({added_file_contents: data.toString()}) }) }) } diff --git a/examples/bundle-webpack/src/index.js b/examples/bundle-webpack/src/index.js index ec74d11ce..6d9d7badf 100644 --- a/examples/bundle-webpack/src/index.js +++ b/examples/bundle-webpack/src/index.js @@ -1,5 +1,6 @@ 'use strict' const React = require('react') +const ReactDOM = require('react-dom') const App = require('./App') -React.render(, document.getElementById('root')) +ReactDOM.render(, document.getElementById('root')) diff --git a/examples/bundle-webpack/webpack.config.js b/examples/bundle-webpack/webpack.config.js index ca6675c54..31e883e55 100644 --- a/examples/bundle-webpack/webpack.config.js +++ b/examples/bundle-webpack/webpack.config.js @@ -1,9 +1,10 @@ 'use strict' -var path = require('path') -var webpack = require('webpack') +const path = require('path') +const webpack = require('webpack') module.exports = { + mode: 'production', devtool: 'eval', entry: [ 'webpack-dev-server/client?http://localhost:3000', @@ -19,11 +20,18 @@ module.exports = { new webpack.HotModuleReplacementPlugin() ], module: { - loaders: [{ - test: /\.js$/, - loaders: ['react-hot', 'babel'], - include: path.join(__dirname, 'src') - }, { test: /\.json$/, loader: 'json-loader' }] + rules: [ + { + test: /\.js$/, + exclude: /node_modules/, + use: { + loader: 'babel-loader', + options: { + presets: ['@babel/preset-env', '@babel/preset-react'] + } + } + } + ] }, node: { fs: 'empty', From 52c72fdbfb3a22d463f30be3b62c4ec8702af145 Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Wed, 13 Feb 2019 09:26:42 +0000 Subject: [PATCH 010/233] chore: update contributors --- package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 4200d5b60..a16e7896e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ipfs-http-client", - "version": "29.1.0", + "version": "29.1.1", "description": "A client library for the IPFS HTTP API", "leadMaintainer": "Alan Shaw ", "main": "src/index.js", @@ -109,6 +109,7 @@ "Dmitry Nikulin ", "Donatas Stundys ", "Fil ", + "Filip Š ", "Francisco Baio Dias ", "Friedel Ziegelmayer ", "Gar ", From ec3eee2b025461cbc8d54877f584621b8e3c94bb Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Wed, 13 Feb 2019 09:26:42 +0000 Subject: [PATCH 011/233] chore: release version v29.1.1 --- CHANGELOG.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e7068feea..9e116539e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,13 @@ + +## [29.1.1](https://github.com/ipfs/js-ipfs-http-client/compare/v29.1.0...v29.1.1) (2019-02-13) + + +### Performance Improvements + +* use test profile ([#942](https://github.com/ipfs/js-ipfs-http-client/issues/942)) ([2c90620](https://github.com/ipfs/js-ipfs-http-client/commit/2c90620)) + + + # [29.1.0](https://github.com/ipfs/js-ipfs-http-client/compare/v29.0.1...v29.1.0) (2019-01-29) From 05f2f6cc38d21da37c94aaff6cd3b9ceea6fc45d Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Wed, 6 Mar 2019 13:21:19 +0000 Subject: [PATCH 012/233] fix: windows travis build (#952) Windows cannot have secrets (temporarily). License: MIT Signed-off-by: Alan Shaw --- .travis.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index fb59f0eeb..12b8e9494 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,13 +11,16 @@ node_js: os: - linux - osx - - windows script: npx nyc -s npm run test:node -- --bail after_success: npx nyc report --reporter=text-lcov > coverage.lcov && npx codecov jobs: include: + - os: windows + filter_secrets: false + cache: false + - stage: check script: - npx aegir commitlint --travis From d1e99e784184c6b9fabf03b423782656ef51e070 Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Wed, 6 Mar 2019 20:23:44 +0000 Subject: [PATCH 013/233] refactor: export types and utilities statically (#951) Allows users to access these additional types and utilities without having to create an instance of the client first. resolves #902 BREAKING CHANGE: `ipfs.util.isIPFS` has moved to a static export and should be accessed via `const { isIPFS } = require('ipfs-http-client')`. The modules available under `ipfs.types.*` have also become static exports. `ipfs.util.crypto` has been removed as it is not a dependency of `ipfs-http-client` so reduces the bundle size. If you need to use libp2p crypto primitives then please see the [js-libp2p-crypto](https://github.com/libp2p/js-libp2p-crypto) project for info on how to use it in your project. Finally `ipfs.util.getEndpointConfig` is now a direct instance method, `ipfs.getEndpointConfig` License: MIT Signed-off-by: Alan Shaw --- README.md | 47 ++++++++------------ examples/bundle-browserify/index.js | 4 +- examples/bundle-webpack/src/App.js | 6 +-- src/{util => }/get-endpoint-config.js | 0 src/index.js | 9 +++- src/utils/load-commands.js | 29 ++++-------- test/constructor.spec.js | 4 +- test/endpoint-config.spec.js | 46 +++++++++++++++++++ test/exports.spec.js | 29 ++++++++++++ test/interface.spec.js | 4 -- test/util.spec.js | 64 --------------------------- 11 files changed, 117 insertions(+), 125 deletions(-) rename src/{util => }/get-endpoint-config.js (100%) create mode 100644 test/endpoint-config.spec.js create mode 100644 test/exports.spec.js delete mode 100644 test/util.spec.js diff --git a/README.md b/README.md index f8bb44c80..f4982baa8 100644 --- a/README.md +++ b/README.md @@ -348,41 +348,32 @@ This means: - See https://github.com/ipfs/js-ipfs for details on pubsub in js-ipfs -#### Domain data types +#### Instance utils -A set of data types are exposed directly from the IPFS instance under `ipfs.types`. That way you're not required to import/require the following. +- `ipfs.getEndpointConfig()` -- [`ipfs.types.Buffer`](https://www.npmjs.com/package/buffer) -- [`ipfs.types.PeerId`](https://github.com/libp2p/js-peer-id) -- [`ipfs.types.PeerInfo`](https://github.com/libp2p/js-peer-info) -- [`ipfs.types.multiaddr`](https://github.com/multiformats/js-multiaddr) -- [`ipfs.types.multibase`](https://github.com/multiformats/multibase) -- [`ipfs.types.multihash`](https://github.com/multiformats/js-multihash) -- [`ipfs.types.CID`](https://github.com/ipld/js-cid) +Call this on your client instance to return an object containing the `host`, `port`, `protocol` and `api-path`. -#### Extra (util) functions +#### Static types and utils -Adding to the methods defined by [`interface-ipfs-core`](https://github.com/ipfs/interface-ipfs-core), `js-ipfs-http-client` exposes a set of extra utility methods. These utility functions are scoped behind the `ipfs.util`. +Aside from the default export, `ipfs-http-client` exports various types and utilities that are included in the bundle: -Complete documentation for these methods is coming with: https://github.com/ipfs/js-ipfs-http-client/pull/305 +- [`isIPFS`](https://www.npmjs.com/package/is-ipfs) +- [`Buffer`](https://www.npmjs.com/package/buffer) +- [`PeerId`](https://www.npmjs.com/package/peer-id) +- [`PeerInfo`](https://www.npmjs.com/package/peer-info) +- [`multiaddr`](https://www.npmjs.com/package/multiaddr) +- [`multibase`](https://www.npmjs.com/package/multibase) +- [`multihash`](https://www.npmjs.com/package/multihash) +- [`CID`](https://www.npmjs.com/package/cids) -##### Get endpoint configuration (host and port) +These can be accessed like this, for example: -> `ipfs.util.getEndpointConfig()` - -This returns an object containing the `host`, `port` and `protocol` - -##### Get libp2p crypto primitives - -> `ipfs.util.crypto` - -This contains an object with the crypto primitives - -##### Get is-ipfs utilities - -> `ipfs.util.isIPFS` - -This contains an object with the is-ipfs utilities to help identifying IPFS resources +```js +const { CID } = require('ipfs-http-client') +// ...or from an es-module: +import { CID } from 'ipfs-http-client' +``` ## Development diff --git a/examples/bundle-browserify/index.js b/examples/bundle-browserify/index.js index 1be85b9d9..b0bc9f15e 100644 --- a/examples/bundle-browserify/index.js +++ b/examples/bundle-browserify/index.js @@ -6,7 +6,7 @@ var ipfs = IPFS() function store () { var toStore = document.getElementById('source').value - ipfs.files.add(Buffer.from(toStore), function (err, res) { + ipfs.add(Buffer.from(toStore), function (err, res) { if (err || !res) { return console.error('ipfs add error', err, res) } @@ -21,7 +21,7 @@ function store () { } function display (hash) { - ipfs.files.cat(hash, function (err, res) { + ipfs.cat(hash, function (err, res) { if (err || !res) { return console.error('ipfs cat error', err, res) } diff --git a/examples/bundle-webpack/src/App.js b/examples/bundle-webpack/src/App.js index 155c6897e..06bf81991 100644 --- a/examples/bundle-webpack/src/App.js +++ b/examples/bundle-webpack/src/App.js @@ -28,15 +28,15 @@ class App extends React.Component { ipfs.add([Buffer.from(stringToUse)], (err, res) => { if (err) throw err const hash = res[0].hash - this.setState({added_file_hash: hash}) + this.setState({ added_file_hash: hash }) ipfs.cat(hash, (err, data) => { if (err) throw err - this.setState({added_file_contents: data.toString()}) + this.setState({ added_file_contents: data.toString() }) }) }) } render () { - return

+ return

Everything is working!

Your ID is {this.state.id}

Your IPFS version is {this.state.version}

diff --git a/src/util/get-endpoint-config.js b/src/get-endpoint-config.js similarity index 100% rename from src/util/get-endpoint-config.js rename to src/get-endpoint-config.js diff --git a/src/index.js b/src/index.js index 5be787427..2423091c2 100644 --- a/src/index.js +++ b/src/index.js @@ -1,7 +1,13 @@ 'use strict' /* global self */ +const isIPFS = require('is-ipfs') +const CID = require('cids') const multiaddr = require('multiaddr') +const multibase = require('multibase') +const multihash = require('multihashes') +const PeerId = require('peer-id') +const PeerInfo = require('peer-info') const loadCommands = require('./utils/load-commands') const getConfig = require('./utils/default-config') const sendRequest = require('./utils/send-request') @@ -39,7 +45,6 @@ function ipfsClient (hostOrMultiaddr, port, opts) { const requestAPI = sendRequest(config) const cmds = loadCommands(requestAPI, config) cmds.send = requestAPI - cmds.Buffer = Buffer // Added buffer in types (this should be removed once a breaking change is release) return cmds } @@ -54,3 +59,5 @@ function toHostAndPort (multiaddr) { } module.exports = ipfsClient + +Object.assign(module.exports, { isIPFS, Buffer, CID, multiaddr, multibase, multihash, PeerId, PeerInfo }) diff --git a/src/utils/load-commands.js b/src/utils/load-commands.js index 4d203defc..030aef5ab 100644 --- a/src/utils/load-commands.js +++ b/src/utils/load-commands.js @@ -1,7 +1,7 @@ 'use strict' function requireCommands () { - const cmds = { + return { // Files Regular (not MFS) add: require('../files-regular/add'), addReadableStream: require('../files-regular/add-readable-stream'), @@ -19,6 +19,9 @@ function requireCommands () { lsReadableStream: require('../files-regular/ls-readable-stream'), lsPullStream: require('../files-regular/ls-pull-stream'), + // Files MFS (Mutable Filesystem) + files: require('../files-mfs'), + // Block block: require('../block'), bitswap: require('../bitswap'), @@ -50,30 +53,14 @@ function requireCommands () { refs: require('../refs'), repo: require('../repo'), stop: require('../stop'), + shutdown: require('../stop'), stats: require('../stats'), update: require('../update'), version: require('../version'), - types: require('../types'), - resolve: require('../resolve') - } - - // shutdown is an alias for stop - cmds.shutdown = cmds.stop - - // Files MFS (Mutable Filesystem) - cmds.files = (send) => { - return require('../files-mfs')(send) + resolve: require('../resolve'), + // ipfs-http-client instance + getEndpointConfig: (send, config) => require('../get-endpoint-config')(config) } - - cmds.util = (send, config) => { - return { - getEndpointConfig: require('../util/get-endpoint-config')(config), - crypto: require('libp2p-crypto'), - isIPFS: require('is-ipfs') - } - } - - return cmds } function loadCommands (send, config) { diff --git a/test/constructor.spec.js b/test/constructor.spec.js index ab3ad26a2..68e1339c8 100644 --- a/test/constructor.spec.js +++ b/test/constructor.spec.js @@ -1,4 +1,4 @@ -/* eslint-env mocha */ +/* eslint-env mocha, browser */ 'use strict' const multiaddr = require('multiaddr') @@ -114,7 +114,7 @@ function clientWorks (client, done) { } function expectConfig (ipfs, { host, port, protocol, apiPath }) { - const conf = ipfs.util.getEndpointConfig() + const conf = ipfs.getEndpointConfig() expect(conf.host).to.equal(host || 'localhost') expect(conf.port).to.equal(port || '5001') expect(conf.protocol).to.equal(protocol || 'http') diff --git a/test/endpoint-config.spec.js b/test/endpoint-config.spec.js new file mode 100644 index 000000000..8ff6532c7 --- /dev/null +++ b/test/endpoint-config.spec.js @@ -0,0 +1,46 @@ +/* eslint-env mocha */ +/* eslint max-nested-callbacks: ["error", 8] */ +'use strict' + +const chai = require('chai') +const dirtyChai = require('dirty-chai') +const expect = chai.expect +chai.use(dirtyChai) +const isNode = require('detect-node') + +const ipfsClient = require('../src') +const f = require('./utils/factory') + +describe('.getEndpointConfig', () => { + if (!isNode) { return } + + let ipfsd + let ipfs + + before(function (done) { + this.timeout(20 * 1000) // slow CI + + f.spawn({ initOptions: { bits: 1024, profile: 'test' } }, (err, _ipfsd) => { + expect(err).to.not.exist() + ipfsd = _ipfsd + ipfs = ipfsClient(_ipfsd.apiAddr) + done() + }) + }) + + after(function (done) { + this.timeout(10 * 1000) + if (!ipfsd) return done() + ipfsd.stop(done) + }) + + it('should return the endpoint configuration', function () { + const endpoint = ipfs.getEndpointConfig() + + expect(endpoint.host).to.equal('127.0.0.1') + expect(endpoint.protocol).to.equal('http') + expect(endpoint['api-path']).to.equal('/api/v0/') + // changes per test run so we just assert it exists. + expect(endpoint).to.have.property('port') + }) +}) diff --git a/test/exports.spec.js b/test/exports.spec.js new file mode 100644 index 000000000..f1f813f69 --- /dev/null +++ b/test/exports.spec.js @@ -0,0 +1,29 @@ +/* eslint-env mocha, browser */ +'use strict' + +const isIPFS = require('is-ipfs') +const CID = require('cids') +const multiaddr = require('multiaddr') +const multibase = require('multibase') +const multihash = require('multihashes') +const PeerId = require('peer-id') +const PeerInfo = require('peer-info') +const chai = require('chai') +const dirtyChai = require('dirty-chai') +const expect = chai.expect +chai.use(dirtyChai) + +const IpfsHttpClient = require('../') + +describe('exports', () => { + it('should export the expected types and utilities', () => { + expect(IpfsHttpClient.isIPFS).to.equal(isIPFS) + expect(IpfsHttpClient.Buffer).to.equal(Buffer) + expect(IpfsHttpClient.CID).to.equal(CID) + expect(IpfsHttpClient.multiaddr).to.equal(multiaddr) + expect(IpfsHttpClient.multibase).to.equal(multibase) + expect(IpfsHttpClient.multihash).to.equal(multihash) + expect(IpfsHttpClient.PeerId).to.equal(PeerId) + expect(IpfsHttpClient.PeerInfo).to.equal(PeerInfo) + }) +}) diff --git a/test/interface.spec.js b/test/interface.spec.js index 5d87a2b91..3d7cb7970 100644 --- a/test/interface.spec.js +++ b/test/interface.spec.js @@ -282,8 +282,4 @@ describe('interface-ipfs-core tests', () => { } } })) - - tests.types(defaultCommonFactory) - - tests.util(defaultCommonFactory, { skip: { reason: 'FIXME currently failing' } }) }) diff --git a/test/util.spec.js b/test/util.spec.js deleted file mode 100644 index 9915c2940..000000000 --- a/test/util.spec.js +++ /dev/null @@ -1,64 +0,0 @@ -/* eslint-env mocha */ -/* eslint max-nested-callbacks: ["error", 8] */ -'use strict' - -const chai = require('chai') -const dirtyChai = require('dirty-chai') -const expect = chai.expect -chai.use(dirtyChai) -const isNode = require('detect-node') - -const ipfsClient = require('../src') -const f = require('./utils/factory') - -describe('.util', () => { - if (!isNode) { return } - - let ipfsd - let ipfs - - before(function (done) { - this.timeout(20 * 1000) // slow CI - - f.spawn({ initOptions: { bits: 1024, profile: 'test' } }, (err, _ipfsd) => { - expect(err).to.not.exist() - ipfsd = _ipfsd - ipfs = ipfsClient(_ipfsd.apiAddr) - done() - }) - }) - - after(function (done) { - this.timeout(10 * 1000) - if (!ipfsd) return done() - ipfsd.stop(done) - }) - - describe('.getEndpointConfig', () => { - it('should return the endpoint configuration', function () { - const endpoint = ipfs.util.getEndpointConfig() - - expect(endpoint.host).to.equal('127.0.0.1') - expect(endpoint.protocol).to.equal('http') - expect(endpoint['api-path']).to.equal('/api/v0/') - // changes per test run so we just assert it exists. - expect(endpoint).to.have.property('port') - }) - }) - - describe('.crypto', () => { - it('should contain the crypto primitives object', function () { - const cripto = ipfs.util.crypto - - expect(cripto).to.exist() - }) - }) - - describe('.isIPFS', () => { - it('should contain the isIPFS utilities object', function () { - const isIPFS = ipfs.util.isIPFS - - expect(isIPFS).to.exist() - }) - }) -}) From a57a4111adc0427c7ad49fb3d84bfc93de64bceb Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Wed, 13 Mar 2019 18:02:34 +0000 Subject: [PATCH 014/233] feat: pubsub unsubscribe all (#956) License: MIT Signed-off-by: Alan Shaw --- .aegir.js | 2 +- package.json | 6 +++--- src/pubsub.js | 6 +++++- test/get.spec.js | 2 +- test/interface.spec.js | 4 ++++ 5 files changed, 14 insertions(+), 6 deletions(-) diff --git a/.aegir.js b/.aegir.js index bbe8a75e9..51aedf024 100644 --- a/.aegir.js +++ b/.aegir.js @@ -12,7 +12,7 @@ module.exports = { }, karma: { files: [{ - pattern: 'node_modules/interface-ipfs-core/js/test/fixtures/**/*', + pattern: 'node_modules/interface-ipfs-core/test/fixtures/**/*', watched: false, served: true, included: false diff --git a/package.json b/package.json index a16e7896e..615c2417e 100644 --- a/package.json +++ b/package.json @@ -82,9 +82,9 @@ "cross-env": "^5.2.0", "dirty-chai": "^2.0.1", "eslint-plugin-react": "^7.11.1", - "go-ipfs-dep": "~0.4.18", - "interface-ipfs-core": "~0.96.0", - "ipfsd-ctl": "github:ipfs/js-ipfsd-ctl", + "go-ipfs-dep": "~0.4.19", + "interface-ipfs-core": "~0.99.0", + "ipfsd-ctl": "~0.42.0", "nock": "^10.0.2", "pull-stream": "^3.6.9", "stream-equal": "^1.1.1" diff --git a/src/pubsub.js b/src/pubsub.js index f539d0e3a..6b298351d 100644 --- a/src/pubsub.js +++ b/src/pubsub.js @@ -77,7 +77,11 @@ module.exports = (arg) => { return setImmediate(() => callback(err)) } - ps.removeListener(topic, handler) + if (!handler && !callback) { + ps.removeAllListeners(topic) + } else { + ps.removeListener(topic, handler) + } // Drop the request once we are actually done if (ps.listenerCount(topic) === 0) { diff --git a/test/get.spec.js b/test/get.spec.js index c789ce971..2c5adb6d9 100644 --- a/test/get.spec.js +++ b/test/get.spec.js @@ -23,7 +23,7 @@ describe('.get (specific go-ipfs features)', function () { const smallFile = { cid: 'Qma4hjFTnCasJ8PVp3mZbZK5g2vGDT4LByLJ7m8ciyRFZP', - data: fixture('js/test/fixtures/testfile.txt') + data: fixture('test/fixtures/testfile.txt') } let ipfsd diff --git a/test/interface.spec.js b/test/interface.spec.js index 3d7cb7970..a5eed428c 100644 --- a/test/interface.spec.js +++ b/test/interface.spec.js @@ -72,6 +72,10 @@ describe('interface-ipfs-core tests', () => { { name: 'should get by CID string + path', reason: 'FIXME vmx 2018-02-22: Currently not supported in go-ipfs, it might be possible once https://github.com/ipfs/go-ipfs/issues/4728 is done' + }, + { + name: 'should get only a CID, due to resolving locally only', + reason: 'FIXME: go-ipfs does not support localResolve option' } ] }) From 9a8b3ecea27a638b415b81a6dad7302fc2d28342 Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Wed, 13 Mar 2019 18:49:34 +0000 Subject: [PATCH 015/233] chore: update contributors --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 615c2417e..60123623d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ipfs-http-client", - "version": "29.1.1", + "version": "30.0.0", "description": "A client library for the IPFS HTTP API", "leadMaintainer": "Alan Shaw ", "main": "src/index.js", From 6b443f02c6f292f80712eaca862eb211903ffba1 Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Wed, 13 Mar 2019 18:49:35 +0000 Subject: [PATCH 016/233] chore: release version v30.0.0 --- CHANGELOG.md | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9e116539e..b29a45f24 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,37 @@ + +# [30.0.0](https://github.com/ipfs/js-ipfs-http-client/compare/v29.1.1...v30.0.0) (2019-03-13) + + +### Bug Fixes + +* windows travis build ([#952](https://github.com/ipfs/js-ipfs-http-client/issues/952)) ([05f2f6c](https://github.com/ipfs/js-ipfs-http-client/commit/05f2f6c)) + + +### Code Refactoring + +* export types and utilities statically ([#951](https://github.com/ipfs/js-ipfs-http-client/issues/951)) ([d1e99e7](https://github.com/ipfs/js-ipfs-http-client/commit/d1e99e7)), closes [#902](https://github.com/ipfs/js-ipfs-http-client/issues/902) + + +### Features + +* pubsub unsubscribe all ([#956](https://github.com/ipfs/js-ipfs-http-client/issues/956)) ([a57a411](https://github.com/ipfs/js-ipfs-http-client/commit/a57a411)) + + +### BREAKING CHANGES + +* `ipfs.util.isIPFS` has moved to a static export and should be accessed via `const { isIPFS } = require('ipfs-http-client')`. + +The modules available under `ipfs.types.*` have also become static exports. + +`ipfs.util.crypto` has been removed as it is not a dependency of `ipfs-http-client` so reduces the bundle size. If you need to use libp2p crypto primitives then please see the [js-libp2p-crypto](https://github.com/libp2p/js-libp2p-crypto) project for info on how to use it in your project. + +Finally `ipfs.util.getEndpointConfig` is now a direct instance method, `ipfs.getEndpointConfig` + +License: MIT +Signed-off-by: Alan Shaw + + + ## [29.1.1](https://github.com/ipfs/js-ipfs-http-client/compare/v29.1.0...v29.1.1) (2019-02-13) From 0c109ab5d260ad906704fd5e3175770700fe0923 Mon Sep 17 00:00:00 2001 From: Nitin Patel <31539366+niinpatel@users.noreply.github.com> Date: Thu, 14 Mar 2019 21:48:00 +0530 Subject: [PATCH 017/233] feat: provide access to multicodec (#954) License: MIT Signed-off by: Nitin Patel --- README.md | 1 + package.json | 3 ++- src/index.js | 3 ++- src/types.js | 18 ------------------ test/exports.spec.js | 2 ++ 5 files changed, 7 insertions(+), 20 deletions(-) delete mode 100644 src/types.js diff --git a/README.md b/README.md index f4982baa8..817ccdb78 100644 --- a/README.md +++ b/README.md @@ -364,6 +364,7 @@ Aside from the default export, `ipfs-http-client` exports various types and util - [`PeerInfo`](https://www.npmjs.com/package/peer-info) - [`multiaddr`](https://www.npmjs.com/package/multiaddr) - [`multibase`](https://www.npmjs.com/package/multibase) +- [`multicodec`](https://www.npmjs.com/package/multicodec) - [`multihash`](https://www.npmjs.com/package/multihash) - [`CID`](https://www.npmjs.com/package/cids) diff --git a/package.json b/package.json index 60123623d..0e58febec 100644 --- a/package.json +++ b/package.json @@ -49,6 +49,7 @@ "lru-cache": "^5.1.1", "multiaddr": "^6.0.0", "multibase": "~0.6.0", + "multicodec": "~0.5.0", "multihashes": "~0.4.14", "ndjson": "^1.5.0", "once": "^1.4.0", @@ -181,4 +182,4 @@ "url": "https://github.com/ipfs/js-ipfs-http-client/issues" }, "homepage": "https://github.com/ipfs/js-ipfs-http-client" -} +} \ No newline at end of file diff --git a/src/index.js b/src/index.js index 2423091c2..feb49e0bd 100644 --- a/src/index.js +++ b/src/index.js @@ -5,6 +5,7 @@ const isIPFS = require('is-ipfs') const CID = require('cids') const multiaddr = require('multiaddr') const multibase = require('multibase') +const multicodec = require('multicodec') const multihash = require('multihashes') const PeerId = require('peer-id') const PeerInfo = require('peer-info') @@ -60,4 +61,4 @@ function toHostAndPort (multiaddr) { module.exports = ipfsClient -Object.assign(module.exports, { isIPFS, Buffer, CID, multiaddr, multibase, multihash, PeerId, PeerInfo }) +Object.assign(module.exports, { isIPFS, Buffer, CID, multiaddr, multibase, multicodec, multihash, PeerId, PeerInfo }) diff --git a/src/types.js b/src/types.js deleted file mode 100644 index 39c80c50b..000000000 --- a/src/types.js +++ /dev/null @@ -1,18 +0,0 @@ -'use strict' - -const CID = require('cids') -const multiaddr = require('multiaddr') -const multibase = require('multibase') -const multihash = require('multihashes') -const PeerId = require('peer-id') -const PeerInfo = require('peer-info') - -module.exports = () => ({ - Buffer: Buffer, - CID: CID, - multiaddr: multiaddr, - multibase: multibase, - multihash: multihash, - PeerId: PeerId, - PeerInfo: PeerInfo -}) diff --git a/test/exports.spec.js b/test/exports.spec.js index f1f813f69..44730c5cc 100644 --- a/test/exports.spec.js +++ b/test/exports.spec.js @@ -5,6 +5,7 @@ const isIPFS = require('is-ipfs') const CID = require('cids') const multiaddr = require('multiaddr') const multibase = require('multibase') +const multicodec = require('multicodec') const multihash = require('multihashes') const PeerId = require('peer-id') const PeerInfo = require('peer-info') @@ -22,6 +23,7 @@ describe('exports', () => { expect(IpfsHttpClient.CID).to.equal(CID) expect(IpfsHttpClient.multiaddr).to.equal(multiaddr) expect(IpfsHttpClient.multibase).to.equal(multibase) + expect(IpfsHttpClient.multicodec).to.equal(multicodec) expect(IpfsHttpClient.multihash).to.equal(multihash) expect(IpfsHttpClient.PeerId).to.equal(PeerId) expect(IpfsHttpClient.PeerInfo).to.equal(PeerInfo) From c3cde768c4d411546fc1bbfe7791c3660a432eec Mon Sep 17 00:00:00 2001 From: Nitin Patel <31539366+niinpatel@users.noreply.github.com> Date: Fri, 15 Mar 2019 14:44:24 +0530 Subject: [PATCH 018/233] fix: dht.findProvs.js handle valid hash but no providers (#950) License: MIT Signed-off-by: Nitin Patel --- src/dht/findprovs.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/dht/findprovs.js b/src/dht/findprovs.js index 8585b054c..dd2d82f58 100644 --- a/src/dht/findprovs.js +++ b/src/dht/findprovs.js @@ -23,6 +23,12 @@ module.exports = (send) => { } const handleResult = (res, callback) => { + // callback with an empty array if no providers are found + if (!res) { + const responses = [] + return callback(null, responses) + } + // Inconsistent return values in the browser vs node if (Array.isArray(res)) { res = res[0] From 87dff04511605aa3d3b2379a627116f8f9d7eff2 Mon Sep 17 00:00:00 2001 From: Hugo Dias Date: Fri, 15 Mar 2019 09:57:35 +0000 Subject: [PATCH 019/233] perf: reduce bundle size (#915) --- .aegir.js | 1 + .travis.yml | 11 ++----- README.md | 7 ++-- package.json | 49 +++++++++++++--------------- src/config/replace.js | 13 ++++++-- src/files-mfs/ls-readable-stream.js | 2 +- src/files-mfs/stat.js | 4 +-- src/files-regular/add-from-url.js | 6 ++-- src/files-regular/add.js | 3 +- src/files-regular/get-pull-stream.js | 5 +-- src/files-regular/ls-pull-stream.js | 4 +-- src/pin/ls.js | 3 +- src/stats/bw-pull-stream.js | 5 +-- src/utils/multipart.js | 6 ++-- src/utils/request.js | 12 ------- src/utils/send-files-stream.js | 2 +- src/utils/send-request.js | 4 +-- test/files-mfs.spec.js | 14 ++++---- test/ping.spec.js | 2 +- 19 files changed, 72 insertions(+), 81 deletions(-) delete mode 100644 src/utils/request.js diff --git a/.aegir.js b/.aegir.js index 51aedf024..6effabad0 100644 --- a/.aegir.js +++ b/.aegir.js @@ -5,6 +5,7 @@ const createServer = require('ipfsd-ctl').createServer const server = createServer() module.exports = { + bundlesize: { maxSize: '231kB' }, webpack: { resolve: { mainFields: ['browser', 'main'] diff --git a/.travis.yml b/.travis.yml index 12b8e9494..912ef7ac7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -23,6 +23,7 @@ jobs: - stage: check script: + - npx aegir build --bundlesize - npx aegir commitlint --travis - npx aegir dep-check - npm run lint @@ -31,19 +32,13 @@ jobs: name: chrome addons: chrome: stable - script: npx aegir test -t browser + script: npx aegir test -t browser -t webworker - stage: test name: firefox addons: firefox: latest - script: npx aegir test -t browser -- --browsers FirefoxHeadless - - - stage: test - name: webworker - addons: - chrome: stable - script: npx aegir test -t webworker + script: npx aegir test -t browser -t webworker -- --browsers FirefoxHeadless notifications: email: false diff --git a/README.md b/README.md index 817ccdb78..a1ef73530 100644 --- a/README.md +++ b/README.md @@ -9,18 +9,19 @@ - +

- + +
- +

diff --git a/package.json b/package.json index 0e58febec..2a4449e0a 100644 --- a/package.json +++ b/package.json @@ -7,8 +7,7 @@ "browser": { "glob": false, "fs": false, - "stream": "readable-stream", - "http": "stream-http" + "stream": "readable-stream" }, "scripts": { "test": "aegir test", @@ -20,17 +19,15 @@ "release": "aegir release ", "release-minor": "aegir release --type minor ", "release-major": "aegir release --type major ", - "coverage": "aegir coverage --timeout 100000", - "coverage-publish": "aegir coverage --provider coveralls --timeout 100000", - "dep-check": "npx dependency-check package.json './test/**/*.js' './src/**/*.js'" + "coverage": "npx nyc -r html npm run test:node -- --bail" }, "dependencies": { "async": "^2.6.1", "bignumber.js": "^8.0.2", - "bl": "^2.1.2", + "bl": "^3.0.0", "bs58": "^4.0.1", "cids": "~0.5.5", - "concat-stream": "^2.0.0", + "concat-stream": "hugomrdias/concat-stream#feat/smaller", "debug": "^4.1.0", "detect-node": "^2.0.4", "end-of-stream": "^1.4.1", @@ -38,35 +35,34 @@ "flatmap": "0.0.3", "glob": "^7.1.3", "ipfs-block": "~0.8.0", - "ipfs-unixfs": "~0.1.16", - "ipld-dag-cbor": "~0.13.0", - "ipld-dag-pb": "~0.15.0", - "is-ipfs": "~0.4.7", + "ipld-dag-cbor": "~0.13.1", + "ipld-dag-pb": "~0.15.3", + "is-ipfs": "~0.6.0", "is-pull-stream": "0.0.0", "is-stream": "^1.1.0", - "libp2p-crypto": "~0.16.0", - "lodash": "^4.17.11", + "iso-stream-http": "~0.1.1", + "iso-url": "~0.4.6", + "just-kebab-case": "^1.1.0", + "just-map-keys": "^1.1.0", "lru-cache": "^5.1.1", - "multiaddr": "^6.0.0", + "multiaddr": "^6.0.6", "multibase": "~0.6.0", "multicodec": "~0.5.0", "multihashes": "~0.4.14", - "ndjson": "^1.5.0", + "ndjson": "hugomrdias/ndjson#feat/readable-stream3", "once": "^1.4.0", - "peer-id": "~0.12.1", - "peer-info": "~0.15.0", + "peer-id": "~0.12.2", + "peer-info": "~0.15.1", "promisify-es6": "^1.0.3", "pull-defer": "~0.2.3", - "pull-pushable": "^2.2.0", - "pull-stream-to-stream": "^1.3.4", + "pull-stream": "^3.6.9", + "pull-to-stream": "~0.1.0", "pump": "^3.0.0", "qs": "^6.5.2", - "readable-stream": "^3.0.6", - "stream-http": "^3.0.0", + "readable-stream": "^3.1.1", "stream-to-pull-stream": "^1.7.2", - "streamifier": "~0.1.1", - "tar-stream": "^1.6.2", - "through2": "^3.0.0" + "tar-stream": "^2.0.1", + "through2": "^3.0.1" }, "engines": { "node": ">=10.0.0", @@ -77,7 +73,7 @@ "url": "https://github.com/ipfs/js-ipfs-http-client" }, "devDependencies": { - "aegir": "^18.0.2", + "aegir": "^18.2.1", "browser-process-platform": "~0.1.1", "chai": "^4.2.0", "cross-env": "^5.2.0", @@ -87,7 +83,6 @@ "interface-ipfs-core": "~0.99.0", "ipfsd-ctl": "~0.42.0", "nock": "^10.0.2", - "pull-stream": "^3.6.9", "stream-equal": "^1.1.1" }, "keywords": [ @@ -182,4 +177,4 @@ "url": "https://github.com/ipfs/js-ipfs-http-client/issues" }, "homepage": "https://github.com/ipfs/js-ipfs-http-client" -} \ No newline at end of file +} diff --git a/src/config/replace.js b/src/config/replace.js index 24f9f0b00..971c61ee0 100644 --- a/src/config/replace.js +++ b/src/config/replace.js @@ -1,14 +1,23 @@ 'use strict' -const streamifier = require('streamifier') +const { Readable } = require('readable-stream') const promisify = require('promisify-es6') const SendOneFile = require('../utils/send-one-file') +function toStream (input) { + return new Readable({ + read () { + this.push(input) + this.push(null) + } + }) +} + module.exports = (send) => { const sendOneFile = SendOneFile(send, 'config/replace') return promisify((config, callback) => { if (typeof config === 'object') { - config = streamifier.createReadStream(Buffer.from(JSON.stringify(config))) + config = toStream(Buffer.from(JSON.stringify(config))) } sendOneFile(config, {}, callback) diff --git a/src/files-mfs/ls-readable-stream.js b/src/files-mfs/ls-readable-stream.js index 2e0ea1a50..404893e70 100644 --- a/src/files-mfs/ls-readable-stream.js +++ b/src/files-mfs/ls-readable-stream.js @@ -3,7 +3,7 @@ const { Transform, PassThrough -} = require('stream') +} = require('readable-stream') const pump = require('pump') const ndjson = require('ndjson') const isStream = require('is-stream') diff --git a/src/files-mfs/stat.js b/src/files-mfs/stat.js index a205fea8e..7274e32a1 100644 --- a/src/files-mfs/stat.js +++ b/src/files-mfs/stat.js @@ -1,8 +1,8 @@ 'use strict' const promisify = require('promisify-es6') -const mapKeys = require('lodash/mapKeys') -const kebabCase = require('lodash/kebabCase') +const mapKeys = require('just-map-keys') +const kebabCase = require('just-kebab-case') const transform = function (data, callback) { callback(null, { diff --git a/src/files-regular/add-from-url.js b/src/files-regular/add-from-url.js index e926a7c81..f1065f2de 100644 --- a/src/files-regular/add-from-url.js +++ b/src/files-regular/add-from-url.js @@ -1,8 +1,8 @@ 'use strict' const promisify = require('promisify-es6') -const { URL } = require('url') -const request = require('../utils/request') +const { URL } = require('iso-url') +const { getRequest } = require('iso-stream-http') const SendOneFile = require('../utils/send-one-file-multiple-results') const FileResultStreamConverter = require('../utils/file-result-stream-converter') @@ -37,7 +37,7 @@ const validUrl = (url) => typeof url === 'string' && url.startsWith('http') const requestWithRedirect = (url, opts, sendOneFile, callback) => { const parsedUrl = new URL(url) - const req = request(parsedUrl.protocol)(url, (res) => { + const req = getRequest(parsedUrl, (res) => { if (res.statusCode >= 400) { return callback(new Error(`Failed to download with ${res.statusCode}`)) } diff --git a/src/files-regular/add.js b/src/files-regular/add.js index 97fe3a5e5..c5506b48b 100644 --- a/src/files-regular/add.js +++ b/src/files-regular/add.js @@ -4,7 +4,6 @@ const promisify = require('promisify-es6') const ConcatStream = require('concat-stream') const once = require('once') const isStream = require('is-stream') -const isString = require('lodash/isString') const isSource = require('is-pull-stream').isSource const FileResultStreamConverter = require('../utils/file-result-stream-converter') const SendFilesStream = require('../utils/send-files-stream') @@ -33,7 +32,7 @@ module.exports = (send) => { // path is optional if content is present if (obj.content) return isBufferOrStream(obj.content) // path must be a non-empty string if no content - return Boolean(obj.path) && isString(obj.path) + return Boolean(obj.path) && typeof obj.path === 'string' } // An input atom: a buffer, stream or content object const isInput = obj => isBufferOrStream(obj) || isContentObject(obj) diff --git a/src/files-regular/get-pull-stream.js b/src/files-regular/get-pull-stream.js index c7d8aa7a4..4b2ede770 100644 --- a/src/files-regular/get-pull-stream.js +++ b/src/files-regular/get-pull-stream.js @@ -3,7 +3,8 @@ const cleanCID = require('../utils/clean-cid') const TarStreamToObjects = require('../utils/tar-stream-to-objects') const v = require('is-ipfs') -const pull = require('pull-stream') +const pull = require('pull-stream/pull') +const map = require('pull-stream/throughs/map') const toPull = require('stream-to-pull-stream') const deferred = require('pull-defer') @@ -30,7 +31,7 @@ module.exports = (send) => { p.resolve( pull( toPull.source(stream), - pull.map(file => { + map(file => { const { path, content } = file return content ? { path, content: toPull.source(content) } : file }) diff --git a/src/files-regular/ls-pull-stream.js b/src/files-regular/ls-pull-stream.js index c82d54f62..d1e238df0 100644 --- a/src/files-regular/ls-pull-stream.js +++ b/src/files-regular/ls-pull-stream.js @@ -1,7 +1,7 @@ 'use strict' const moduleConfig = require('../utils/module-config') -const pull = require('pull-stream') +const values = require('pull-stream/sources/values') const deferred = require('pull-defer') const IsIpfs = require('is-ipfs') const cleanCID = require('../utils/clean-cid') @@ -54,7 +54,7 @@ module.exports = (arg) => { type: typeOf(link) })) - p.resolve(pull.values(result)) + p.resolve(values(result)) }) return p diff --git a/src/pin/ls.js b/src/pin/ls.js index 6348dfe89..c8ad26a4b 100644 --- a/src/pin/ls.js +++ b/src/pin/ls.js @@ -1,7 +1,6 @@ 'use strict' const promisify = require('promisify-es6') -const keys = require('lodash/keys') module.exports = (send) => { return promisify((hash, opts, callback) => { @@ -26,7 +25,7 @@ module.exports = (send) => { if (err) { return callback(err) } - callback(null, keys(res.Keys).map(hash => ( + callback(null, Object.keys(res.Keys).map(hash => ( { hash, type: res.Keys[hash].Type } ))) }) diff --git a/src/stats/bw-pull-stream.js b/src/stats/bw-pull-stream.js index f302a3a5f..26a4eb311 100644 --- a/src/stats/bw-pull-stream.js +++ b/src/stats/bw-pull-stream.js @@ -1,7 +1,8 @@ 'use strict' const toPull = require('stream-to-pull-stream') -const pull = require('pull-stream') +const map = require('pull-stream/throughs/map') +const pull = require('pull-stream/pull') const transformChunk = require('./bw-util') const deferred = require('pull-defer') @@ -21,7 +22,7 @@ module.exports = (send) => { p.resolve(pull( toPull.source(stream), - pull.map(transformChunk) + map(transformChunk) )) }) diff --git a/src/utils/multipart.js b/src/utils/multipart.js index a7096eefd..22006c435 100644 --- a/src/utils/multipart.js +++ b/src/utils/multipart.js @@ -1,9 +1,9 @@ 'use strict' -const Transform = require('stream').Transform +const Transform = require('readable-stream').Transform const isNode = require('detect-node') const isSource = require('is-pull-stream').isSource -const toStream = require('pull-stream-to-stream') +const toStream = require('pull-to-stream') const PADDING = '--' const NEW_LINE = '\r\n' @@ -78,7 +78,7 @@ class Multipart extends Transform { } if (isSource(content)) { - content = toStream.source(content) + content = toStream.readable(content) } // From now on we assume content is a stream diff --git a/src/utils/request.js b/src/utils/request.js deleted file mode 100644 index d81edff7c..000000000 --- a/src/utils/request.js +++ /dev/null @@ -1,12 +0,0 @@ -'use strict' - -const http = require('http') -const https = require('https') - -module.exports = (protocol) => { - if (protocol.indexOf('https') === 0) { - return https.request - } - - return http.request -} diff --git a/src/utils/send-files-stream.js b/src/utils/send-files-stream.js index aff2cdcc9..c2450d39e 100644 --- a/src/utils/send-files-stream.js +++ b/src/utils/send-files-stream.js @@ -1,6 +1,6 @@ 'use strict' -const Duplex = require('stream').Duplex +const { Duplex } = require('readable-stream') const eachSeries = require('async/eachSeries') const isStream = require('is-stream') const once = require('once') diff --git a/src/utils/send-request.js b/src/utils/send-request.js index 16351bb39..219327adf 100644 --- a/src/utils/send-request.js +++ b/src/utils/send-request.js @@ -6,9 +6,9 @@ const isNode = require('detect-node') const ndjson = require('ndjson') const pump = require('pump') const once = require('once') +const { getRequest } = require('iso-stream-http') const streamToValue = require('./stream-to-value') const streamToJsonValue = require('./stream-to-json-value') -const request = require('./request') const log = require('debug')('ipfs-http-client:request') // -- Internal @@ -171,7 +171,7 @@ function requestAPI (config, options, callback) { protocol: `${config.protocol}:` } - const req = request(config.protocol)(reqOptions, onRes(options.buffer, callback)) + const req = getRequest(reqOptions, onRes(options.buffer, callback)) req.on('error', (err) => { callback(err) diff --git a/test/files-mfs.spec.js b/test/files-mfs.spec.js index b550105a6..f88e37ba9 100644 --- a/test/files-mfs.spec.js +++ b/test/files-mfs.spec.js @@ -9,7 +9,9 @@ chai.use(dirtyChai) const loadFixture = require('aegir/fixtures') const mh = require('multihashes') const CID = require('cids') -const pull = require('pull-stream') +const values = require('pull-stream/sources/values') +const pull = require('pull-stream/pull') +const collect = require('pull-stream/sinks/collect') const ipfsClient = require('../src') const f = require('./utils/factory') @@ -280,9 +282,9 @@ describe('.files (the MFS API part)', function () { const expectedCid = 'QmRf22bZar3WKmojipms22PkXH1MZGmvsqzQtuSvQE3uhm' pull( - pull.values([{ content: pull.values([Buffer.from('test')]) }]), + values([{ content: values([Buffer.from('test')]) }]), ipfs.addPullStream(), - pull.collect((err, res) => { + collect((err, res) => { expect(err).to.not.exist() expect(res).to.have.length(1) @@ -295,7 +297,7 @@ describe('.files (the MFS API part)', function () { it('.add with pull stream (callback)', (done) => { const expectedCid = 'QmRf22bZar3WKmojipms22PkXH1MZGmvsqzQtuSvQE3uhm' - ipfs.add(pull.values([Buffer.from('test')]), (err, res) => { + ipfs.add(values([Buffer.from('test')]), (err, res) => { expect(err).to.not.exist() expect(res).to.have.length(1) @@ -307,7 +309,7 @@ describe('.files (the MFS API part)', function () { it('.add with pull stream (promise)', () => { const expectedCid = 'QmRf22bZar3WKmojipms22PkXH1MZGmvsqzQtuSvQE3uhm' - return ipfs.add(pull.values([Buffer.from('test')])) + return ipfs.add(values([Buffer.from('test')])) .then((res) => { expect(res).to.have.length(1) expect(res[0]).to.deep.equal({ path: expectedCid, hash: expectedCid, size: 12 }) @@ -317,7 +319,7 @@ describe('.files (the MFS API part)', function () { it('.add with array of objects with pull stream content', () => { const expectedCid = 'QmRf22bZar3WKmojipms22PkXH1MZGmvsqzQtuSvQE3uhm' - return ipfs.add([{ content: pull.values([Buffer.from('test')]) }]) + return ipfs.add([{ content: values([Buffer.from('test')]) }]) .then((res) => { expect(res).to.have.length(1) expect(res[0]).to.eql({ path: expectedCid, hash: expectedCid, size: 12 }) diff --git a/test/ping.spec.js b/test/ping.spec.js index c8a856e13..5f6ecd3ea 100644 --- a/test/ping.spec.js +++ b/test/ping.spec.js @@ -3,7 +3,7 @@ const chai = require('chai') const dirtyChai = require('dirty-chai') -const pull = require('pull-stream') +const pull = require('pull-stream/pull') const collect = require('pull-stream/sinks/collect') const expect = chai.expect chai.use(dirtyChai) From e956348c4ee204213ec67b26299f37e576d977cf Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Fri, 15 Mar 2019 10:10:09 +0000 Subject: [PATCH 020/233] chore: update contributors --- package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 2a4449e0a..d1bd934d9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ipfs-http-client", - "version": "30.0.0", + "version": "30.1.0", "description": "A client library for the IPFS HTTP API", "leadMaintainer": "Alan Shaw ", "main": "src/index.js", @@ -138,6 +138,7 @@ "Mitar ", "Mithgol ", "Mohamed Abdulaziz ", + "Nitin Patel <31539366+niinpatel@users.noreply.github.com>", "Nuno Nogueira ", "Níckolas Goline ", "Oli Evans ", From bfed894f92aeb487a0de31b79a26093602970752 Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Fri, 15 Mar 2019 10:10:09 +0000 Subject: [PATCH 021/233] chore: release version v30.1.0 --- CHANGELOG.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b29a45f24..51a16de19 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,23 @@ + +# [30.1.0](https://github.com/ipfs/js-ipfs-http-client/compare/v30.0.0...v30.1.0) (2019-03-15) + + +### Bug Fixes + +* dht.findProvs.js handle valid hash but no providers ([#950](https://github.com/ipfs/js-ipfs-http-client/issues/950)) ([c3cde76](https://github.com/ipfs/js-ipfs-http-client/commit/c3cde76)) + + +### Features + +* provide access to multicodec ([#954](https://github.com/ipfs/js-ipfs-http-client/issues/954)) ([0c109ab](https://github.com/ipfs/js-ipfs-http-client/commit/0c109ab)) + + +### Performance Improvements + +* reduce bundle size ([#915](https://github.com/ipfs/js-ipfs-http-client/issues/915)) ([87dff04](https://github.com/ipfs/js-ipfs-http-client/commit/87dff04)) + + + # [30.0.0](https://github.com/ipfs/js-ipfs-http-client/compare/v29.1.1...v30.0.0) (2019-03-13) From 27bb9af61e549d19524de83c772d6669759413b7 Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Thu, 28 Mar 2019 08:50:36 +0000 Subject: [PATCH 022/233] chore: update contributors --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d1bd934d9..7fe2d6c0c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ipfs-http-client", - "version": "30.1.0", + "version": "30.1.1", "description": "A client library for the IPFS HTTP API", "leadMaintainer": "Alan Shaw ", "main": "src/index.js", From 21cdcc5100b32e3ac1e75ec70022b9b28b0aede1 Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Thu, 28 Mar 2019 08:50:37 +0000 Subject: [PATCH 023/233] chore: release version v30.1.1 --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 51a16de19..5a5ff2f3c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ + +## [30.1.1](https://github.com/ipfs/js-ipfs-http-client/compare/v30.1.0...v30.1.1) (2019-03-28) + + + # [30.1.0](https://github.com/ipfs/js-ipfs-http-client/compare/v30.0.0...v30.1.0) (2019-03-15) From 5da0bcd0dd15579c85c8f2d3ebd1bfef48a3b9f1 Mon Sep 17 00:00:00 2001 From: Marcin Rataj Date: Tue, 9 Apr 2019 17:38:01 +0200 Subject: [PATCH 024/233] fix: https multiaddr support in constructor (#965) Passing HTTPS multiaddr as a string to constructor did not work, protocol was ignored and unencrypted HTTP was used. This commit improves parsing of multiaddr constructor parameter and adds tests to ensure HTTPS is respected in all scenarios. It also updates iso-stream-http to v0.1.2 which includes fix for "https does not exist" License: MIT Signed-off-by: Marcin Rataj --- package.json | 2 +- src/index.js | 37 ++++++++++++++++++++++++------------- test/constructor.spec.js | 38 +++++++++++++++++++++++++++++++++----- 3 files changed, 58 insertions(+), 19 deletions(-) diff --git a/package.json b/package.json index 7fe2d6c0c..40bbcef66 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,7 @@ "is-ipfs": "~0.6.0", "is-pull-stream": "0.0.0", "is-stream": "^1.1.0", - "iso-stream-http": "~0.1.1", + "iso-stream-http": "~0.1.2", "iso-url": "~0.4.6", "just-kebab-case": "^1.1.0", "just-map-keys": "^1.1.0", diff --git a/src/index.js b/src/index.js index feb49e0bd..ddd0e3e37 100644 --- a/src/index.js +++ b/src/index.js @@ -13,28 +13,26 @@ const loadCommands = require('./utils/load-commands') const getConfig = require('./utils/default-config') const sendRequest = require('./utils/send-request') -function ipfsClient (hostOrMultiaddr, port, opts) { +function ipfsClient (hostOrMultiaddr, port, userOptions) { // convert all three params to objects that we can merge. - let hostAndPort = {} + let options = {} if (!hostOrMultiaddr) { // autoconfigure host and port in browser if (typeof self !== 'undefined') { - const split = self.location.host.split(':') - hostAndPort.host = split[0] - hostAndPort.port = split[1] + options = urlToOptions(self.location) } } else if (multiaddr.isMultiaddr(hostOrMultiaddr)) { - hostAndPort = toHostAndPort(hostOrMultiaddr) + options = maToOptions(hostOrMultiaddr) } else if (typeof hostOrMultiaddr === 'object') { - hostAndPort = hostOrMultiaddr + options = hostOrMultiaddr } else if (typeof hostOrMultiaddr === 'string') { if (hostOrMultiaddr[0] === '/') { // throws if multiaddr is malformed or can't be converted to a nodeAddress - hostAndPort = toHostAndPort(multiaddr(hostOrMultiaddr)) + options = maToOptions(multiaddr(hostOrMultiaddr)) } else { // hostOrMultiaddr is domain or ip address as a string - hostAndPort.host = hostOrMultiaddr + options.host = hostOrMultiaddr } } @@ -42,7 +40,7 @@ function ipfsClient (hostOrMultiaddr, port, opts) { port = { port: port } } - const config = Object.assign(getConfig(), hostAndPort, port, opts) + const config = Object.assign(getConfig(), options, port, userOptions) const requestAPI = sendRequest(config) const cmds = loadCommands(requestAPI, config) cmds.send = requestAPI @@ -50,12 +48,25 @@ function ipfsClient (hostOrMultiaddr, port, opts) { return cmds } -// throws if multiaddr can't be converted to a nodeAddress -function toHostAndPort (multiaddr) { +function maToOptions (multiaddr) { + // ma.nodeAddress() throws if multiaddr can't be converted to a nodeAddress const nodeAddr = multiaddr.nodeAddress() + const protos = multiaddr.protos() + // only http and https are allowed as protocol, + // anything else will be replaced with http + const exitProtocol = protos[protos.length - 1].name return { host: nodeAddr.address, - port: nodeAddr.port + port: nodeAddr.port, + protocol: exitProtocol.startsWith('http') ? exitProtocol : 'http' + } +} + +function urlToOptions (url) { + return { + host: url.hostname, + port: url.port || (url.protocol.startsWith('https') ? 443 : 80), + protocol: url.protocol.startsWith('http') ? url.protocol.split(':')[0] : 'http' } } diff --git a/test/constructor.spec.js b/test/constructor.spec.js index 68e1339c8..af77d18e1 100644 --- a/test/constructor.spec.js +++ b/test/constructor.spec.js @@ -30,7 +30,25 @@ describe('ipfs-http-client constructor tests', () => { expectConfig(ipfs, { host, port, protocol }) }) - it('mutliaddr dns4 string, opts', () => { + it('multiaddr dns4 string (implicit http)', () => { + const host = 'foo.com' + const port = '1001' + const protocol = 'http' // default to http if not specified in multiaddr + const addr = `/dns4/${host}/tcp/${port}` + const ipfs = ipfsClient(addr) + expectConfig(ipfs, { host, port, protocol }) + }) + + it('multiaddr dns4 string (explicit https)', () => { + const host = 'foo.com' + const port = '1001' + const protocol = 'https' + const addr = `/dns4/${host}/tcp/${port}/${protocol}` + const ipfs = ipfsClient(addr) + expectConfig(ipfs, { host, port, protocol }) + }) + + it('multiaddr dns4 string, explicit https in opts', () => { const host = 'foo.com' const port = '1001' const protocol = 'https' @@ -39,15 +57,25 @@ describe('ipfs-http-client constructor tests', () => { expectConfig(ipfs, { host, port, protocol }) }) - it('mutliaddr ipv4 string', () => { + it('multiaddr ipv4 string (implicit http)', () => { const host = '101.101.101.101' const port = '1001' + const protocol = 'http' const addr = `/ip4/${host}/tcp/${port}` const ipfs = ipfsClient(addr) - expectConfig(ipfs, { host, port }) + expectConfig(ipfs, { host, port, protocol }) + }) + + it('multiaddr ipv4 string (explicit https)', () => { + const host = '101.101.101.101' + const port = '1001' + const protocol = 'https' + const addr = `/ip4/${host}/tcp/${port}/${protocol}` + const ipfs = ipfsClient(addr) + expectConfig(ipfs, { host, port, protocol }) }) - it('mutliaddr instance', () => { + it('multiaddr instance', () => { const host = 'ace.place' const port = '1001' const addr = multiaddr(`/dns4/${host}/tcp/${port}`) @@ -70,7 +98,7 @@ describe('ipfs-http-client constructor tests', () => { expectConfig(ipfs, { host, port, apiPath }) }) - it('throws on invalid mutliaddr', () => { + it('throws on invalid multiaddr', () => { expect(() => ipfsClient('/dns4')).to.throw('invalid address') expect(() => ipfsClient('/hello')).to.throw('no protocol with name') expect(() => ipfsClient('/dns4/ipfs.io')).to.throw('multiaddr must have a valid format') From f2ab25de1035786fd73cbf782a84ad5e3d75959c Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Tue, 9 Apr 2019 16:49:13 +0100 Subject: [PATCH 025/233] chore: update contributors --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 40bbcef66..7bc2ebe73 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ipfs-http-client", - "version": "30.1.1", + "version": "30.1.2", "description": "A client library for the IPFS HTTP API", "leadMaintainer": "Alan Shaw ", "main": "src/index.js", From bf3dc789e8e1bded7c54937769c9278c32d9c9b5 Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Tue, 9 Apr 2019 16:49:13 +0100 Subject: [PATCH 026/233] chore: release version v30.1.2 --- CHANGELOG.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5a5ff2f3c..04ae6cefa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,13 @@ + +## [30.1.2](https://github.com/ipfs/js-ipfs-http-client/compare/v30.1.1...v30.1.2) (2019-04-09) + + +### Bug Fixes + +* https multiaddr support in constructor ([#965](https://github.com/ipfs/js-ipfs-http-client/issues/965)) ([5da0bcd](https://github.com/ipfs/js-ipfs-http-client/commit/5da0bcd)) + + + ## [30.1.1](https://github.com/ipfs/js-ipfs-http-client/compare/v30.1.0...v30.1.1) (2019-03-28) From 944a64b6f617409ed537b3640320e194d773fd55 Mon Sep 17 00:00:00 2001 From: Hugo Dias Date: Thu, 11 Apr 2019 15:03:48 +0100 Subject: [PATCH 027/233] fix: fix missing buffer bundling with browserify (#966) fixes #964 --- package.json | 1 + src/index.js | 1 + 2 files changed, 2 insertions(+) diff --git a/package.json b/package.json index 7bc2ebe73..b04473d2c 100644 --- a/package.json +++ b/package.json @@ -26,6 +26,7 @@ "bignumber.js": "^8.0.2", "bl": "^3.0.0", "bs58": "^4.0.1", + "buffer": "^5.2.1", "cids": "~0.5.5", "concat-stream": "hugomrdias/concat-stream#feat/smaller", "debug": "^4.1.0", diff --git a/src/index.js b/src/index.js index ddd0e3e37..bd58a66f1 100644 --- a/src/index.js +++ b/src/index.js @@ -2,6 +2,7 @@ /* global self */ const isIPFS = require('is-ipfs') +const { Buffer } = require('buffer') const CID = require('cids') const multiaddr = require('multiaddr') const multibase = require('multibase') From 55408eb91b1158a5647d084b801e65d550c93560 Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Thu, 11 Apr 2019 15:20:12 +0100 Subject: [PATCH 028/233] chore: update contributors --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b04473d2c..9964324bc 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ipfs-http-client", - "version": "30.1.2", + "version": "30.1.3", "description": "A client library for the IPFS HTTP API", "leadMaintainer": "Alan Shaw ", "main": "src/index.js", From ab77171be88b080565b8b1bceb974ba218dbd4df Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Thu, 11 Apr 2019 15:20:12 +0100 Subject: [PATCH 029/233] chore: release version v30.1.3 --- CHANGELOG.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 04ae6cefa..91f6b3ef5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,13 @@ + +## [30.1.3](https://github.com/ipfs/js-ipfs-http-client/compare/v30.1.2...v30.1.3) (2019-04-11) + + +### Bug Fixes + +* fix missing buffer bundling with browserify ([#966](https://github.com/ipfs/js-ipfs-http-client/issues/966)) ([944a64b](https://github.com/ipfs/js-ipfs-http-client/commit/944a64b)), closes [#964](https://github.com/ipfs/js-ipfs-http-client/issues/964) + + + ## [30.1.2](https://github.com/ipfs/js-ipfs-http-client/compare/v30.1.1...v30.1.2) (2019-04-09) From 17d49de29b634d0f485dd49a553adbb518194d37 Mon Sep 17 00:00:00 2001 From: Dietrich Ayala Date: Tue, 16 Apr 2019 07:09:33 -0700 Subject: [PATCH 030/233] fix: update Babel in upload-file-via-browser example (#968) (#970) --- examples/upload-file-via-browser/package.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/examples/upload-file-via-browser/package.json b/examples/upload-file-via-browser/package.json index 24130b384..2bb957036 100644 --- a/examples/upload-file-via-browser/package.json +++ b/examples/upload-file-via-browser/package.json @@ -11,8 +11,7 @@ ], "license": "MIT", "devDependencies": { - "babel-core": "~6.26.3", - "babel-loader": "~8.0.4", + "@babel/core": "^7.4.3", "ipfs-http-client": "../../", "pull-file-reader": "~1.0.2", "react": "~16.6.3", From d759f3c152058a37f8ce0c14b32ea18ad402b3c9 Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Mon, 29 Apr 2019 13:46:41 +0100 Subject: [PATCH 031/233] chore: update dependencies (#973) * chore: update dependencies License: MIT Signed-off-by: Alan Shaw * chore: pin to 0.4.19 temporarily --- package.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 9964324bc..c0f5f8dc9 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,7 @@ "bs58": "^4.0.1", "buffer": "^5.2.1", "cids": "~0.5.5", - "concat-stream": "hugomrdias/concat-stream#feat/smaller", + "concat-stream": "github:hugomrdias/concat-stream#feat/smaller", "debug": "^4.1.0", "detect-node": "^2.0.4", "end-of-stream": "^1.4.1", @@ -50,7 +50,7 @@ "multibase": "~0.6.0", "multicodec": "~0.5.0", "multihashes": "~0.4.14", - "ndjson": "hugomrdias/ndjson#feat/readable-stream3", + "ndjson": "github:hugomrdias/ndjson#feat/readable-stream3", "once": "^1.4.0", "peer-id": "~0.12.2", "peer-info": "~0.15.1", @@ -74,13 +74,13 @@ "url": "https://github.com/ipfs/js-ipfs-http-client" }, "devDependencies": { - "aegir": "^18.2.1", + "aegir": "^18.2.2", "browser-process-platform": "~0.1.1", "chai": "^4.2.0", "cross-env": "^5.2.0", "dirty-chai": "^2.0.1", "eslint-plugin-react": "^7.11.1", - "go-ipfs-dep": "~0.4.19", + "go-ipfs-dep": "0.4.19", "interface-ipfs-core": "~0.99.0", "ipfsd-ctl": "~0.42.0", "nock": "^10.0.2", From cc677f0d56619a291143c6c9ecea497005ef5493 Mon Sep 17 00:00:00 2001 From: Marcin Rataj Date: Mon, 29 Apr 2019 16:09:44 +0200 Subject: [PATCH 032/233] fix: uncaught error: stream.push() after EOF (#980) This switches pull-to-stream to v0.1.1 which includes a fix for #967 License: MIT Signed-off-by: Marcin Rataj --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c0f5f8dc9..3be53d65a 100644 --- a/package.json +++ b/package.json @@ -57,7 +57,7 @@ "promisify-es6": "^1.0.3", "pull-defer": "~0.2.3", "pull-stream": "^3.6.9", - "pull-to-stream": "~0.1.0", + "pull-to-stream": "~0.1.1", "pump": "^3.0.0", "qs": "^6.5.2", "readable-stream": "^3.1.1", From 2a810b2cd2d5ac516e160e6a31f7494cabc64cff Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Mon, 29 Apr 2019 16:27:20 +0100 Subject: [PATCH 033/233] chore: update contributors --- package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 3be53d65a..8d1091994 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ipfs-http-client", - "version": "30.1.3", + "version": "30.1.4", "description": "A client library for the IPFS HTTP API", "leadMaintainer": "Alan Shaw ", "main": "src/index.js", @@ -101,6 +101,7 @@ "Danny ", "David Braun ", "David Dias ", + "Dietrich Ayala ", "Diogo Silva ", "Dmitriy Ryajov ", "Dmitry Nikulin ", From ab3b6ef6ad1052e98b4bb5f57fb80235d61631fd Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Mon, 29 Apr 2019 16:27:21 +0100 Subject: [PATCH 034/233] chore: release version v30.1.4 --- CHANGELOG.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 91f6b3ef5..4719549bc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,14 @@ + +## [30.1.4](https://github.com/ipfs/js-ipfs-http-client/compare/v30.1.3...v30.1.4) (2019-04-29) + + +### Bug Fixes + +* uncaught error: stream.push() after EOF ([#980](https://github.com/ipfs/js-ipfs-http-client/issues/980)) ([cc677f0](https://github.com/ipfs/js-ipfs-http-client/commit/cc677f0)), closes [#967](https://github.com/ipfs/js-ipfs-http-client/issues/967) +* update Babel in upload-file-via-browser example ([#968](https://github.com/ipfs/js-ipfs-http-client/issues/968)) ([#970](https://github.com/ipfs/js-ipfs-http-client/issues/970)) ([17d49de](https://github.com/ipfs/js-ipfs-http-client/commit/17d49de)) + + + ## [30.1.3](https://github.com/ipfs/js-ipfs-http-client/compare/v30.1.2...v30.1.3) (2019-04-11) From bf9c595c7af3e59f69e6ef37b5a9c599ed2d0857 Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Wed, 1 May 2019 16:04:34 +0100 Subject: [PATCH 035/233] docs: add maintainer.json (#939) In preparation for https://github.com/ipfs/team-mgmt/pull/822 License: MIT Signed-off-by: Alan Shaw --- maintainer.json | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 maintainer.json diff --git a/maintainer.json b/maintainer.json new file mode 100644 index 000000000..7fc0aa142 --- /dev/null +++ b/maintainer.json @@ -0,0 +1,11 @@ +{ + "repoLeadMaintainer": { + "name": "Alan Shaw", + "email": "alan.shaw@protocol.ai", + "username": "alanshaw" + }, + "workingGroup": { + "name": "JS IPFS", + "entryPoint": "https://github.com/ipfs/js-core" + } +} From 11c4d16b293143a9a4ca44a0b1b2a86bdf7fed25 Mon Sep 17 00:00:00 2001 From: Hugo Dias Date: Wed, 8 May 2019 09:58:05 +0100 Subject: [PATCH 036/233] chore: remove two files and update deps (#975) --- .eslintignore | 1 - .npmignore | 5 ----- package.json | 6 +++++- 3 files changed, 5 insertions(+), 7 deletions(-) delete mode 100644 .eslintignore delete mode 100644 .npmignore diff --git a/.eslintignore b/.eslintignore deleted file mode 100644 index 499b34048..000000000 --- a/.eslintignore +++ /dev/null @@ -1 +0,0 @@ -test/test-folder/ipfs-add.js \ No newline at end of file diff --git a/.npmignore b/.npmignore deleted file mode 100644 index e20403d47..000000000 --- a/.npmignore +++ /dev/null @@ -1,5 +0,0 @@ -node_modules -*.log -coverage -.nyc_output -test diff --git a/package.json b/package.json index 8d1091994..86cbc9b4c 100644 --- a/package.json +++ b/package.json @@ -9,6 +9,10 @@ "fs": false, "stream": "readable-stream" }, + "files": [ + "src", + "dist" + ], "scripts": { "test": "aegir test", "test:node": "aegir test -t node", @@ -40,7 +44,7 @@ "ipld-dag-pb": "~0.15.3", "is-ipfs": "~0.6.0", "is-pull-stream": "0.0.0", - "is-stream": "^1.1.0", + "is-stream": "^2.0.0", "iso-stream-http": "~0.1.2", "iso-url": "~0.4.6", "just-kebab-case": "^1.1.0", From 775ce803b0d7f96691ce64b5747d9ea40ed6c956 Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" Date: Thu, 9 May 2019 16:08:29 +0100 Subject: [PATCH 037/233] =?UTF-8?q?chore:=20update=20dependencies=20to=20e?= =?UTF-8?q?nable=20Greenkeeper=20=F0=9F=8C=B4=20(#989)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit License: MIT Signed-off-by: Alan Shaw --- examples/bundle-browserify/package.json | 4 ++-- examples/bundle-webpack/package.json | 10 +++++----- examples/name-api/package.json | 2 +- examples/sub-module/package.json | 4 ++-- examples/upload-file-via-browser/package.json | 10 +++++----- greenkeeper.json | 18 ++++++++++++++++++ package.json | 2 +- 7 files changed, 34 insertions(+), 16 deletions(-) create mode 100644 greenkeeper.json diff --git a/examples/bundle-browserify/package.json b/examples/bundle-browserify/package.json index 4e64ef8a5..7245b9c3a 100644 --- a/examples/bundle-browserify/package.json +++ b/examples/bundle-browserify/package.json @@ -10,9 +10,9 @@ "author": "Friedel Ziegelmayer", "license": "MIT", "devDependencies": { - "browserify": "^13.1.1", + "browserify": "^16.2.3", "ipfs-http-client": "../../", - "http-server": "~0.9.0" + "http-server": "~0.11.1" }, "dependencies": {} } diff --git a/examples/bundle-webpack/package.json b/examples/bundle-webpack/package.json index 48ecb1ec5..bfa0b9428 100644 --- a/examples/bundle-webpack/package.json +++ b/examples/bundle-webpack/package.json @@ -14,11 +14,11 @@ "@babel/preset-react": "^7.0.0", "babel-loader": "^8.0.5", "ipfs-http-client": "../../", - "react": "^16.8.1", - "react-dom": "^16.8.1", - "react-hot-loader": "^4.6.5", - "webpack": "^4.29.3", - "webpack-dev-server": "^3.1.14" + "react": "~16.8.6", + "react-dom": "~16.8.6", + "react-hot-loader": "~4.8.4", + "webpack": "~4.31.0", + "webpack-dev-server": "~3.3.1" }, "browserslist": [ ">1%", diff --git a/examples/name-api/package.json b/examples/name-api/package.json index 697ffb68a..daab7ee99 100644 --- a/examples/name-api/package.json +++ b/examples/name-api/package.json @@ -10,6 +10,6 @@ "license": "MIT", "devDependencies": { "browserify": "^16.2.3", - "http-server": "^0.11.1" + "http-server": "~0.11.1" } } diff --git a/examples/sub-module/package.json b/examples/sub-module/package.json index 74d650390..1eb2bbf18 100644 --- a/examples/sub-module/package.json +++ b/examples/sub-module/package.json @@ -9,9 +9,9 @@ "license": "MIT", "devDependencies": { "babel-core": "^6.25.0", - "babel-loader": "^7.1.0", + "babel-loader": "^8.0.5", "babel-preset-env": "^1.5.2", "babili": "~0.1.4", - "webpack": "^3.0.0" + "webpack": "~4.31.0" } } diff --git a/examples/upload-file-via-browser/package.json b/examples/upload-file-via-browser/package.json index 2bb957036..d5e1fad68 100644 --- a/examples/upload-file-via-browser/package.json +++ b/examples/upload-file-via-browser/package.json @@ -14,10 +14,10 @@ "@babel/core": "^7.4.3", "ipfs-http-client": "../../", "pull-file-reader": "~1.0.2", - "react": "~16.6.3", - "react-dom": "~16.6.3", - "react-hot-loader": "~4.3.12", - "webpack": "~4.25.1", - "webpack-dev-server": "~3.1.10" + "react": "~16.8.6", + "react-dom": "~16.8.6", + "react-hot-loader": "~4.8.4", + "webpack": "~4.31.0", + "webpack-dev-server": "~3.3.1" } } diff --git a/greenkeeper.json b/greenkeeper.json new file mode 100644 index 000000000..ae2649cc9 --- /dev/null +++ b/greenkeeper.json @@ -0,0 +1,18 @@ +{ + "groups": { + "default": { + "packages": [ + "package.json" + ] + }, + "examples": { + "packages": [ + "examples/bundle-browserify/package.json", + "examples/bundle-webpack/package.json", + "examples/name-api/package.json", + "examples/sub-module/package.json", + "examples/upload-file-via-browser/package.json" + ] + } + } +} diff --git a/package.json b/package.json index 86cbc9b4c..d17d7302d 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,7 @@ "bl": "^3.0.0", "bs58": "^4.0.1", "buffer": "^5.2.1", - "cids": "~0.5.5", + "cids": "~0.5.8", "concat-stream": "github:hugomrdias/concat-stream#feat/smaller", "debug": "^4.1.0", "detect-node": "^2.0.4", From a741e100d170dcc5f26a8c3ccbc5ad0d4c572ff0 Mon Sep 17 00:00:00 2001 From: dirkmc Date: Sat, 11 May 2019 07:49:30 -0400 Subject: [PATCH 038/233] feat: refs endpoint (#978) BREAKING CHANGE: ipfs.refs now returns objects with camelCase properties not PascalCase properties. i.e. `{ ref, err }` not `{ Ref, Err }` --- README.md | 8 ++ src/files-regular/index.js | 5 +- src/files-regular/refs-local-pull-stream.js | 27 +++++ .../refs-local-readable-stream.js | 23 ++++ src/files-regular/refs-local.js | 32 ++++++ src/files-regular/refs-pull-stream.js | 34 ++++++ src/files-regular/refs-readable-stream.js | 30 ++++++ src/files-regular/refs.js | 75 +++++++++++++ src/refs.js | 40 ------- src/utils/load-commands.js | 4 +- test/refs.spec.js | 100 ------------------ test/sub-modules.spec.js | 13 ++- 12 files changed, 242 insertions(+), 149 deletions(-) create mode 100644 src/files-regular/refs-local-pull-stream.js create mode 100644 src/files-regular/refs-local-readable-stream.js create mode 100644 src/files-regular/refs-local.js create mode 100644 src/files-regular/refs-pull-stream.js create mode 100644 src/files-regular/refs-readable-stream.js create mode 100644 src/files-regular/refs.js delete mode 100644 src/refs.js delete mode 100644 test/refs.spec.js diff --git a/README.md b/README.md index a1ef73530..c4544e791 100644 --- a/README.md +++ b/README.md @@ -220,6 +220,14 @@ const ipfs = ipfsClient({ - [`ipfs.block.put(block, [options], [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/BLOCK.md#blockput) - [`ipfs.block.stat(cid, [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/BLOCK.md#blockstat) +- [refs](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/REFS.md) + - [`ipfs.refs(ipfsPath, [options], [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/REFS.md#refs) + - [`ipfs.refsReadableStream(ipfsPath, [options], [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/REFS.md#refsreadablestream) + - [`ipfs.refsPullStream(ipfsPath, [options], [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/REFS.md#refspullstream) + - [`ipfs.refs.local([callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/REFS.md#refslocal) + - [`ipfs.refs.localReadableStream([callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/REFS.md#refslocalreadablestream) + - [`ipfs.refs.localPullStream([callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/REFS.md#refslocalpullstream) + #### Graph - [dag](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/DAG.md) diff --git a/src/files-regular/index.js b/src/files-regular/index.js index a52e7505a..059d7ea1c 100644 --- a/src/files-regular/index.js +++ b/src/files-regular/index.js @@ -20,6 +20,9 @@ module.exports = (arg) => { getPullStream: require('../files-regular/get-pull-stream')(send), ls: require('../files-regular/ls')(send), lsReadableStream: require('../files-regular/ls-readable-stream')(send), - lsPullStream: require('../files-regular/ls-pull-stream')(send) + lsPullStream: require('../files-regular/ls-pull-stream')(send), + refs: require('../files-regular/refs')(send), + refsReadableStream: require('../files-regular/refs-readable-stream')(send), + refsPullStream: require('../files-regular/refs-pull-stream')(send) } } diff --git a/src/files-regular/refs-local-pull-stream.js b/src/files-regular/refs-local-pull-stream.js new file mode 100644 index 000000000..c4452b116 --- /dev/null +++ b/src/files-regular/refs-local-pull-stream.js @@ -0,0 +1,27 @@ +'use strict' + +const pull = require('pull-stream') +const toPull = require('stream-to-pull-stream') +const deferred = require('pull-defer') +const moduleConfig = require('../utils/module-config') + +module.exports = (send) => { + send = moduleConfig(send) + + return (opts) => { + opts = opts || {} + + const p = deferred.source() + + send({ path: 'refs/local', qs: opts }, (err, stream) => { + if (err) { return p.resolve(pull.error(err)) } + + p.resolve(pull( + toPull.source(stream), + pull.map(r => ({ ref: r.Ref, err: r.Err })) + )) + }) + + return p + } +} diff --git a/src/files-regular/refs-local-readable-stream.js b/src/files-regular/refs-local-readable-stream.js new file mode 100644 index 000000000..0d8bc15bf --- /dev/null +++ b/src/files-regular/refs-local-readable-stream.js @@ -0,0 +1,23 @@ +'use strict' + +const Stream = require('readable-stream') +const pump = require('pump') +const through = require('through2') + +module.exports = (send) => { + return (opts) => { + opts = opts || {} + + const pt = new Stream.PassThrough({ objectMode: true }) + + send({ path: 'refs/local', qs: opts }, (err, stream) => { + if (err) { return pt.destroy(err) } + + pump(stream, through.obj(function (r, enc, cb) { + cb(null, { ref: r.Ref, err: r.Err }) + }), pt) + }) + + return pt + } +} diff --git a/src/files-regular/refs-local.js b/src/files-regular/refs-local.js new file mode 100644 index 000000000..680e51000 --- /dev/null +++ b/src/files-regular/refs-local.js @@ -0,0 +1,32 @@ +'use strict' + +const promisify = require('promisify-es6') +const streamToValueWithTransformer = require('../utils/stream-to-value-with-transformer') +const moduleConfig = require('../utils/module-config') + +module.exports = (arg) => { + const send = moduleConfig(arg) + + return promisify((opts, callback) => { + if (typeof (opts) === 'function') { + callback = opts + opts = {} + } + + const transform = (res, cb) => { + cb(null, res.map(r => ({ ref: r.Ref, err: r.Err }))) + } + + const request = { + path: 'refs/local', + qs: opts + } + send(request, (err, result) => { + if (err) { + return callback(err) + } + + streamToValueWithTransformer(result, transform, callback) + }) + }) +} diff --git a/src/files-regular/refs-pull-stream.js b/src/files-regular/refs-pull-stream.js new file mode 100644 index 000000000..e3c1b113a --- /dev/null +++ b/src/files-regular/refs-pull-stream.js @@ -0,0 +1,34 @@ +'use strict' + +const pull = require('pull-stream') +const toPull = require('stream-to-pull-stream') +const deferred = require('pull-defer') +const moduleConfig = require('../utils/module-config') +const { checkArgs, normalizeOpts } = require('./refs') + +module.exports = (send) => { + send = moduleConfig(send) + + return (args, opts) => { + opts = normalizeOpts(opts) + + const p = deferred.source() + + try { + args = checkArgs(args) + } catch (err) { + return p.end(err) + } + + send({ path: 'refs', args, qs: opts }, (err, stream) => { + if (err) { return p.resolve(pull.error(err)) } + + p.resolve(pull( + toPull.source(stream), + pull.map(r => ({ ref: r.Ref, err: r.Err })) + )) + }) + + return p + } +} diff --git a/src/files-regular/refs-readable-stream.js b/src/files-regular/refs-readable-stream.js new file mode 100644 index 000000000..4c9ae2d1f --- /dev/null +++ b/src/files-regular/refs-readable-stream.js @@ -0,0 +1,30 @@ +'use strict' + +const Stream = require('readable-stream') +const pump = require('pump') +const through = require('through2') +const { checkArgs, normalizeOpts } = require('./refs') + +module.exports = (send) => { + return (args, opts) => { + opts = normalizeOpts(opts) + + const pt = new Stream.PassThrough({ objectMode: true }) + + try { + args = checkArgs(args) + } catch (err) { + return pt.destroy(err) + } + + send({ path: 'refs', args, qs: opts }, (err, stream) => { + if (err) { return pt.destroy(err) } + + pump(stream, through.obj(function (r, enc, cb) { + cb(null, { ref: r.Ref, err: r.Err }) + }), pt) + }) + + return pt + } +} diff --git a/src/files-regular/refs.js b/src/files-regular/refs.js new file mode 100644 index 000000000..986a6f6cc --- /dev/null +++ b/src/files-regular/refs.js @@ -0,0 +1,75 @@ +'use strict' + +const IsIpfs = require('is-ipfs') +const promisify = require('promisify-es6') +const streamToValueWithTransformer = require('../utils/stream-to-value-with-transformer') +const moduleConfig = require('../utils/module-config') +const cleanCID = require('../utils/clean-cid') + +module.exports = (arg) => { + const send = moduleConfig(arg) + + const refs = promisify((args, opts, callback) => { + if (typeof (opts) === 'function') { + callback = opts + opts = {} + } + opts = module.exports.normalizeOpts(opts) + + try { + args = module.exports.checkArgs(args) + } catch (err) { + return callback(err) + } + + const transform = (res, cb) => { + cb(null, res.map(r => ({ ref: r.Ref, err: r.Err }))) + } + + const request = { + args, + path: 'refs', + qs: opts + } + send(request, (err, result) => { + if (err) { + return callback(err) + } + + streamToValueWithTransformer(result, transform, callback) + }) + }) + + refs.local = require('./refs-local')(arg) + refs.localReadableStream = require('./refs-local-readable-stream')(arg) + refs.localPullStream = require('./refs-local-pull-stream')(arg) + + return refs +} + +module.exports.checkArgs = (args) => { + const isArray = Array.isArray(args) + args = isArray ? args : [args] + + const res = [] + for (let arg of args) { + try { + arg = cleanCID(arg) + } catch (err) { + if (!IsIpfs.ipfsPath(arg)) { + throw err + } + } + res.push(arg) + } + + return isArray ? res : res[0] +} + +module.exports.normalizeOpts = (opts) => { + opts = opts || {} + if (typeof opts.maxDepth === 'number') { + opts['max-depth'] = opts.maxDepth + } + return opts +} diff --git a/src/refs.js b/src/refs.js deleted file mode 100644 index 97d204124..000000000 --- a/src/refs.js +++ /dev/null @@ -1,40 +0,0 @@ -'use strict' - -const promisify = require('promisify-es6') -const streamToValue = require('./utils/stream-to-value') -const moduleConfig = require('./utils/module-config') - -module.exports = (arg) => { - const send = moduleConfig(arg) - - const refs = promisify((args, opts, callback) => { - if (typeof (opts) === 'function') { - callback = opts - opts = {} - } - - const request = { - path: 'refs', - args: args, - qs: opts - } - - send.andTransform(request, streamToValue, callback) - }) - - refs.local = promisify((opts, callback) => { - if (typeof (opts) === 'function') { - callback = opts - opts = {} - } - - const request = { - path: 'refs/local', - qs: opts - } - - send.andTransform(request, streamToValue, callback) - }) - - return refs -} diff --git a/src/utils/load-commands.js b/src/utils/load-commands.js index 030aef5ab..e4a914dd0 100644 --- a/src/utils/load-commands.js +++ b/src/utils/load-commands.js @@ -18,6 +18,9 @@ function requireCommands () { ls: require('../files-regular/ls'), lsReadableStream: require('../files-regular/ls-readable-stream'), lsPullStream: require('../files-regular/ls-pull-stream'), + refs: require('../files-regular/refs'), + refsReadableStream: require('../files-regular/refs-readable-stream'), + refsPullStream: require('../files-regular/refs-pull-stream'), // Files MFS (Mutable Filesystem) files: require('../files-mfs'), @@ -50,7 +53,6 @@ function requireCommands () { key: require('../key'), log: require('../log'), mount: require('../mount'), - refs: require('../refs'), repo: require('../repo'), stop: require('../stop'), shutdown: require('../stop'), diff --git a/test/refs.spec.js b/test/refs.spec.js deleted file mode 100644 index 9ffcf4ebe..000000000 --- a/test/refs.spec.js +++ /dev/null @@ -1,100 +0,0 @@ -/* eslint-env mocha */ -'use strict' - -const chai = require('chai') -const dirtyChai = require('dirty-chai') -const expect = chai.expect -chai.use(dirtyChai) -const isNode = require('detect-node') -const waterfall = require('async/waterfall') -const path = require('path') -const fs = require('fs') - -const ipfsClient = require('../src') -const f = require('./utils/factory') - -describe('.refs', function () { - this.timeout(80 * 1000) - - if (!isNode) { return } - - let ipfs - let ipfsd - let folder - - before((done) => { - const filesPath = path.join(__dirname, '/fixtures/test-folder') - - // Symlinks in a repo don't always clone well, especially on Windows. - // So if the 'hello-link' is not a symlink, then make it one. - const symlinkPath = filesPath + '/hello-link' - const symlinkTarget = 'files/hello.txt' - if (!fs.lstatSync(symlinkPath).isSymbolicLink()) { - fs.unlinkSync(symlinkPath) - fs.symlinkSync(symlinkTarget, symlinkPath) - } - - waterfall([ - (cb) => f.spawn({ initOptions: { bits: 1024, profile: 'test' } }, cb), - (_ipfsd, cb) => { - ipfsd = _ipfsd - ipfs = ipfsClient(_ipfsd.apiAddr) - ipfs.addFromFs(filesPath, { recursive: true }, cb) - }, - (hashes, cb) => { - folder = hashes[hashes.length - 1].hash - expect(folder).to.be.eql('QmQao3KNcpCsdXaLGpjieFGMfXzsSXgsf6Rnc5dJJA3QMh') - cb() - } - ], done) - }) - - after((done) => { - if (!ipfsd) return done() - ipfsd.stop(done) - }) - - const result = [ - { - Ref: 'QmQao3KNcpCsdXaLGpjieFGMfXzsSXgsf6Rnc5dJJA3QMh QmcUYKmQxmTcFom4R4UZP7FWeQzgJkwcFn51XrvsMy7PE9 add', - Err: '' - }, { - Ref: 'QmQao3KNcpCsdXaLGpjieFGMfXzsSXgsf6Rnc5dJJA3QMh QmNeHxDfQfjVFyYj2iruvysLH9zpp78v3cu1s3BZq1j5hY cat', - Err: '' - }, { - Ref: 'QmQao3KNcpCsdXaLGpjieFGMfXzsSXgsf6Rnc5dJJA3QMh QmTYFLz5vsdMpq4XXw1a1pSxujJc9Z5V3Aw1Qg64d849Zy files', - Err: '' - }, { - Ref: 'QmQao3KNcpCsdXaLGpjieFGMfXzsSXgsf6Rnc5dJJA3QMh QmY9cxiHqTFoWamkQVkpmmqzBrY3hCBEL2XNu3NtX74Fuu hello-link', - Err: '' - }, { - Ref: 'QmQao3KNcpCsdXaLGpjieFGMfXzsSXgsf6Rnc5dJJA3QMh QmU7wetVaAqc3Meurif9hcYBHGvQmL5QdpPJYBoZizyTNL ipfs-add', - Err: '' - }, { - Ref: 'QmQao3KNcpCsdXaLGpjieFGMfXzsSXgsf6Rnc5dJJA3QMh QmctZfSuegbi2TMFY2y3VQjxsH5JbRBu7XmiLfHNvshhio ls', - Err: '' - }, { - Ref: 'QmQao3KNcpCsdXaLGpjieFGMfXzsSXgsf6Rnc5dJJA3QMh QmbkMNB6rwfYAxRvnG9CWJ6cKKHEdq2ZKTozyF5FQ7H8Rs version', - Err: '' - } - ] - - describe('Callback API', () => { - it('refs', (done) => { - ipfs.refs(folder, { format: ' ' }, (err, objs) => { - expect(err).to.not.exist() - expect(objs).to.eql(result) - done() - }) - }) - }) - - describe('Promise API', () => { - it('refs', () => { - return ipfs.refs(folder, { format: ' ' }) - .then((objs) => { - expect(objs).to.eql(result) - }) - }) - }) -}) diff --git a/test/sub-modules.spec.js b/test/sub-modules.spec.js index 333407ea4..cabd09b55 100644 --- a/test/sub-modules.spec.js +++ b/test/sub-modules.spec.js @@ -183,6 +183,12 @@ describe('submodules', () => { expect(filesRegular.ls).to.be.a('function') expect(filesRegular.lsReadableStream).to.be.a('function') expect(filesRegular.lsPullStream).to.be.a('function') + expect(filesRegular.refs).to.be.a('function') + expect(filesRegular.refsReadableStream).to.be.a('function') + expect(filesRegular.refsPullStream).to.be.a('function') + expect(filesRegular.refs.local).to.be.a('function') + expect(filesRegular.refs.localReadableStream).to.be.a('function') + expect(filesRegular.refs.localPullStream).to.be.a('function') }) it('files MFS API', () => { @@ -209,11 +215,4 @@ describe('submodules', () => { expect(mount).to.be.a('function') }) - - it('refs', () => { - const refs = require('../src/refs')(config) - - expect(refs).to.be.a('function') - expect(refs.local).to.be.a('function') - }) }) From 83a8094d42bf4035605347781149a8c2e071c31a Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" Date: Mon, 13 May 2019 13:01:20 +0100 Subject: [PATCH 039/233] chore(package): update interface-ipfs-core to version 0.100.1 (#994) --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d17d7302d..cfa588398 100644 --- a/package.json +++ b/package.json @@ -85,7 +85,7 @@ "dirty-chai": "^2.0.1", "eslint-plugin-react": "^7.11.1", "go-ipfs-dep": "0.4.19", - "interface-ipfs-core": "~0.99.0", + "interface-ipfs-core": "~0.100.1", "ipfsd-ctl": "~0.42.0", "nock": "^10.0.2", "stream-equal": "^1.1.1" From dcbbdd95b896c82a8fcf6eb3e02011a0ef0b7212 Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Mon, 13 May 2019 13:21:00 +0100 Subject: [PATCH 040/233] chore: update contributors --- package.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index cfa588398..de974ca9a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ipfs-http-client", - "version": "30.1.4", + "version": "31.0.0", "description": "A client library for the IPFS HTTP API", "leadMaintainer": "Alan Shaw ", "main": "src/index.js", @@ -122,6 +122,7 @@ "Harlan T Wood ", "Henrique Dias ", "Holodisc ", + "Hugo Dias ", "Hugo Dias ", "JGAntunes ", "Jacob Heun ", @@ -164,9 +165,11 @@ "Victor Bjelkholm ", "Volker Mische ", "Zhiyuan Lin ", + "dirkmc ", "dmitriy ryajov ", "elsehow ", "ethers ", + "greenkeeper[bot] ", "haad ", "kumavis ", "leekt216 ", From f4b89edcd9894acb68e05a8a811fdccea635d935 Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Mon, 13 May 2019 13:21:01 +0100 Subject: [PATCH 041/233] chore: release version v31.0.0 --- CHANGELOG.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4719549bc..d95f1253c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,18 @@ + +# [31.0.0](https://github.com/ipfs/js-ipfs-http-client/compare/v30.1.4...v31.0.0) (2019-05-13) + + +### Features + +* refs endpoint ([#978](https://github.com/ipfs/js-ipfs-http-client/issues/978)) ([a741e10](https://github.com/ipfs/js-ipfs-http-client/commit/a741e10)) + + +### BREAKING CHANGES + +* ipfs.refs now returns objects with camelCase properties not PascalCase properties. i.e. `{ ref, err }` not `{ Ref, Err }` + + + ## [30.1.4](https://github.com/ipfs/js-ipfs-http-client/compare/v30.1.3...v30.1.4) (2019-04-29) From 7a47e3b910b0c7ac68b70b2aaf7eba36e7c02731 Mon Sep 17 00:00:00 2001 From: Michael Bradley Date: Wed, 15 May 2019 10:21:48 -0500 Subject: [PATCH 042/233] build: change min node version to 8.3.0 (#996) Also adjust Travis CI config to perform builds and tests with node 8. `npm install`, `npm run build`, and `npm run test` all succeeded locally with node version `8.3.0`. The reason for version `8.3.0` instead of `8.0.0` is that `8.3.0` introduced support for object rest/spread, which is used by at least one of this package's devDependencies (`go-ipfs-dep`). It may be the case that at runtime older versions of node would work correctly with the built package, but it seems simpler to settle on the minimum supported version being a version that can build, test, and use the package. Closes #983. --- .travis.yml | 1 + package.json | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 912ef7ac7..7428d50be 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,6 +7,7 @@ stages: node_js: - '10' + - '8' os: - linux diff --git a/package.json b/package.json index de974ca9a..608b51511 100644 --- a/package.json +++ b/package.json @@ -70,7 +70,7 @@ "through2": "^3.0.1" }, "engines": { - "node": ">=10.0.0", + "node": ">=8.3.0", "npm": ">=3.0.0" }, "repository": { From 4f21befdc89d2d6e51eaa1b6d0309decce1b4fc3 Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Wed, 15 May 2019 16:47:04 +0100 Subject: [PATCH 043/233] fix: config set with number (#998) Anything that isn't a string needs to be passed with `--json`. fixes #881 Depends on: * [x] https://github.com/ipfs/interface-js-ipfs-core/pull/470 License: MIT Signed-off-by: Alan Shaw --- package.json | 2 +- src/config/set.js | 8 +++----- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 608b51511..eb876d139 100644 --- a/package.json +++ b/package.json @@ -85,7 +85,7 @@ "dirty-chai": "^2.0.1", "eslint-plugin-react": "^7.11.1", "go-ipfs-dep": "0.4.19", - "interface-ipfs-core": "~0.100.1", + "interface-ipfs-core": "~0.101.0", "ipfsd-ctl": "~0.42.0", "nock": "^10.0.2", "stream-equal": "^1.1.1" diff --git a/src/config/set.js b/src/config/set.js index ae36a75b5..0fa933565 100644 --- a/src/config/set.js +++ b/src/config/set.js @@ -16,14 +16,12 @@ module.exports = (send) => { return callback(new Error('Invalid value type')) } - if (typeof value === 'object') { - value = JSON.stringify(value) - opts = { json: true } - } - if (typeof value === 'boolean') { value = value.toString() opts = { bool: true } + } else if (typeof value !== 'string') { + value = JSON.stringify(value) + opts = { json: true } } send({ From b1a5a94ccdbe941fe54e2f782840ed0565ab46fb Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Wed, 15 May 2019 16:50:19 +0100 Subject: [PATCH 044/233] chore: update contributors --- package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index eb876d139..deeef433d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ipfs-http-client", - "version": "31.0.0", + "version": "31.0.1", "description": "A client library for the IPFS HTTP API", "leadMaintainer": "Alan Shaw ", "main": "src/index.js", @@ -140,6 +140,7 @@ "Marcin Rataj ", "Matt Bell ", "Maxime Lathuilière ", + "Michael Bradley ", "Michael Muré ", "Mikeal Rogers ", "Mitar ", From 84117a136d05d9eb6a43e42e2a7e3dc52635efb9 Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Wed, 15 May 2019 16:50:19 +0100 Subject: [PATCH 045/233] chore: release version v31.0.1 --- CHANGELOG.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d95f1253c..f54d248f8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,13 @@ + +## [31.0.1](https://github.com/ipfs/js-ipfs-http-client/compare/v31.0.0...v31.0.1) (2019-05-15) + + +### Bug Fixes + +* config set with number ([#998](https://github.com/ipfs/js-ipfs-http-client/issues/998)) ([4f21bef](https://github.com/ipfs/js-ipfs-http-client/commit/4f21bef)), closes [#881](https://github.com/ipfs/js-ipfs-http-client/issues/881) + + + # [31.0.0](https://github.com/ipfs/js-ipfs-http-client/compare/v30.1.4...v31.0.0) (2019-05-13) From 391351d406384b164c6e58daaa3f73bc1adb3dc8 Mon Sep 17 00:00:00 2001 From: dirkmc Date: Thu, 16 May 2019 09:41:11 -0600 Subject: [PATCH 046/233] fix: error handling for refs/refs local (#997) * fix: error handling for refs/refs local * fix: ensure errors are passed back from stream-to-value * chore: update interface-ipfs-core --- package.json | 2 +- src/files-regular/refs-local-readable-stream.js | 2 ++ src/files-regular/refs-readable-stream.js | 2 ++ src/utils/stream-to-value.js | 10 ++++------ 4 files changed, 9 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index deeef433d..c5f2e5bad 100644 --- a/package.json +++ b/package.json @@ -85,7 +85,7 @@ "dirty-chai": "^2.0.1", "eslint-plugin-react": "^7.11.1", "go-ipfs-dep": "0.4.19", - "interface-ipfs-core": "~0.101.0", + "interface-ipfs-core": "~0.101.1", "ipfsd-ctl": "~0.42.0", "nock": "^10.0.2", "stream-equal": "^1.1.1" diff --git a/src/files-regular/refs-local-readable-stream.js b/src/files-regular/refs-local-readable-stream.js index 0d8bc15bf..09fddde1d 100644 --- a/src/files-regular/refs-local-readable-stream.js +++ b/src/files-regular/refs-local-readable-stream.js @@ -13,6 +13,8 @@ module.exports = (send) => { send({ path: 'refs/local', qs: opts }, (err, stream) => { if (err) { return pt.destroy(err) } + stream.once('error', (err) => pt.destroy(err)) + pump(stream, through.obj(function (r, enc, cb) { cb(null, { ref: r.Ref, err: r.Err }) }), pt) diff --git a/src/files-regular/refs-readable-stream.js b/src/files-regular/refs-readable-stream.js index 4c9ae2d1f..b5cf69c48 100644 --- a/src/files-regular/refs-readable-stream.js +++ b/src/files-regular/refs-readable-stream.js @@ -20,6 +20,8 @@ module.exports = (send) => { send({ path: 'refs', args, qs: opts }, (err, stream) => { if (err) { return pt.destroy(err) } + stream.once('error', (err) => pt.destroy(err)) + pump(stream, through.obj(function (r, enc, cb) { cb(null, { ref: r.Ref, err: r.Err }) }), pt) diff --git a/src/utils/stream-to-value.js b/src/utils/stream-to-value.js index fa7068d46..d28fd6130 100644 --- a/src/utils/stream-to-value.js +++ b/src/utils/stream-to-value.js @@ -7,14 +7,12 @@ const concat = require('concat-stream') Concatenate a stream to a single value. */ function streamToValue (response, callback) { + let data pump( response, - concat((data) => callback(null, data)), - (err) => { - if (err) { - callback(err) - } - }) + concat((d) => { data = d }), + (err) => callback(err, data) + ) } module.exports = streamToValue From 6d4ab3eef93c30824973f9672800945daacb5f5f Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Thu, 16 May 2019 16:50:21 +0100 Subject: [PATCH 047/233] chore: update contributors --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c5f2e5bad..43879e244 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ipfs-http-client", - "version": "31.0.1", + "version": "31.0.2", "description": "A client library for the IPFS HTTP API", "leadMaintainer": "Alan Shaw ", "main": "src/index.js", From 8a4062a41abe4b08c19fe4b941f9b8d5796be931 Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Thu, 16 May 2019 16:50:21 +0100 Subject: [PATCH 048/233] chore: release version v31.0.2 --- CHANGELOG.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f54d248f8..a2288fe6b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,13 @@ + +## [31.0.2](https://github.com/ipfs/js-ipfs-http-client/compare/v31.0.1...v31.0.2) (2019-05-16) + + +### Bug Fixes + +* error handling for refs/refs local ([#997](https://github.com/ipfs/js-ipfs-http-client/issues/997)) ([391351d](https://github.com/ipfs/js-ipfs-http-client/commit/391351d)) + + + ## [31.0.1](https://github.com/ipfs/js-ipfs-http-client/compare/v31.0.0...v31.0.1) (2019-05-15) From 7b49f7e4650f7fbd1dd7f85723fd64dfbcfd99b2 Mon Sep 17 00:00:00 2001 From: Hugo Dias Date: Thu, 16 May 2019 23:36:16 +0200 Subject: [PATCH 049/233] feat: add support for File DOM API to files-regular (#986) * feat: add file dom api support to files api * feat: add support for File DOM API to files-regular * chore: fix package declaration cause npm is dumb * chore: fix lint * chore: add ipfs-utils * fix: change the requires to ipfs-utils * chore: increase max bundle size --- .aegir.js | 2 +- examples/upload-file-via-browser/.eslintrc | 11 ---- examples/upload-file-via-browser/.gitignore | 1 + examples/upload-file-via-browser/package.json | 26 +++++--- examples/upload-file-via-browser/server.js | 13 ---- examples/upload-file-via-browser/src/App.js | 27 ++++---- .../upload-file-via-browser/webpack.config.js | 9 +-- package.json | 5 +- src/files-regular/add.js | 26 ++------ src/utils/multipart.js | 7 --- src/utils/prepare-file.js | 61 ++++++++++++++++--- 11 files changed, 96 insertions(+), 92 deletions(-) delete mode 100644 examples/upload-file-via-browser/.eslintrc delete mode 100644 examples/upload-file-via-browser/server.js diff --git a/.aegir.js b/.aegir.js index 6effabad0..fe08c25af 100644 --- a/.aegir.js +++ b/.aegir.js @@ -5,7 +5,7 @@ const createServer = require('ipfsd-ctl').createServer const server = createServer() module.exports = { - bundlesize: { maxSize: '231kB' }, + bundlesize: { maxSize: '232kB' }, webpack: { resolve: { mainFields: ['browser', 'main'] diff --git a/examples/upload-file-via-browser/.eslintrc b/examples/upload-file-via-browser/.eslintrc deleted file mode 100644 index 676feeeb1..000000000 --- a/examples/upload-file-via-browser/.eslintrc +++ /dev/null @@ -1,11 +0,0 @@ -{ - "extends": "standard", - "rules": { - "react/jsx-uses-react": 2, - "react/jsx-uses-vars": 2, - "react/react-in-jsx-scope": 2 - }, - "plugins": [ - "react" - ] -} diff --git a/examples/upload-file-via-browser/.gitignore b/examples/upload-file-via-browser/.gitignore index 44b50488c..c089921a3 100644 --- a/examples/upload-file-via-browser/.gitignore +++ b/examples/upload-file-via-browser/.gitignore @@ -2,3 +2,4 @@ node_modules npm-debug.log .DS_Store dist +yarn.lock \ No newline at end of file diff --git a/examples/upload-file-via-browser/package.json b/examples/upload-file-via-browser/package.json index d5e1fad68..8827052ca 100644 --- a/examples/upload-file-via-browser/package.json +++ b/examples/upload-file-via-browser/package.json @@ -3,7 +3,7 @@ "version": "1.0.0", "description": "Upload file to IPFS via browser using js-ipfs-http-client with Webpack", "scripts": { - "start": "node server.js" + "start": "webpack-dev-server" }, "author": "Harlan T Wood ", "contributors": [ @@ -12,12 +12,24 @@ "license": "MIT", "devDependencies": { "@babel/core": "^7.4.3", - "ipfs-http-client": "../../", - "pull-file-reader": "~1.0.2", - "react": "~16.8.6", - "react-dom": "~16.8.6", - "react-hot-loader": "~4.8.4", - "webpack": "~4.31.0", + "@babel/preset-env": "^7.3.1", + "@babel/preset-react": "^7.0.0", + "eslint": "^5.16.0", + "eslint-plugin-react": "^7.11.1", + "react": "~16.6.3", + "react-dom": "~16.6.3", + "webpack": "~4.30.0", "webpack-dev-server": "~3.3.1" + }, + "eslintConfig" : { + "extends": "standard", + "rules": { + "react/jsx-uses-react": 2, + "react/jsx-uses-vars": 2, + "react/react-in-jsx-scope": 2 + }, + "plugins": [ + "react" + ] } } diff --git a/examples/upload-file-via-browser/server.js b/examples/upload-file-via-browser/server.js deleted file mode 100644 index 6b476dcb0..000000000 --- a/examples/upload-file-via-browser/server.js +++ /dev/null @@ -1,13 +0,0 @@ -'use strict' -let webpack = require('webpack') -let WebpackDevServer = require('webpack-dev-server') -let config = require('./webpack.config') - -new WebpackDevServer(webpack(config), { - publicPath: config.output.publicPath, - hot: true, - historyApiFallback: true -}).listen(3000, 'localhost', function (err) { - if (err) throw new Error(err) - console.log('Listening at localhost:3000') -}) diff --git a/examples/upload-file-via-browser/src/App.js b/examples/upload-file-via-browser/src/App.js index 77f5b43d2..258dc53ed 100644 --- a/examples/upload-file-via-browser/src/App.js +++ b/examples/upload-file-via-browser/src/App.js @@ -1,9 +1,6 @@ 'use strict' const React = require('react') -const ipfsClient = require('ipfs-http-client') - -// create a stream from a file, which enables uploads of big files without allocating memory twice -const fileReaderPullStream = require('pull-file-reader') +const ipfsClient = require('../../../src') class App extends React.Component { constructor () { @@ -11,7 +8,7 @@ class App extends React.Component { this.state = { added_file_hash: null } - this.ipfs = ipfsClient('localhost', '5001') + this.ipfs = ipfsClient('localhost', '58041') // bind methods this.captureFile = this.captureFile.bind(this) @@ -22,25 +19,23 @@ class App extends React.Component { captureFile (event) { event.stopPropagation() event.preventDefault() - const file = event.target.files[0] if (document.getElementById('keepFilename').checked) { - this.saveToIpfsWithFilename(file) + this.saveToIpfsWithFilename(event.target.files) } else { - this.saveToIpfs(file) + this.saveToIpfs(event.target.files) } } // Example #1 // Add file to IPFS and return a CID - saveToIpfs (file) { + saveToIpfs (files) { let ipfsId - const fileStream = fileReaderPullStream(file) - this.ipfs.add(fileStream, { progress: (prog) => console.log(`received: ${prog}`) }) + this.ipfs.add([...files], { progress: (prog) => console.log(`received: ${prog}`) }) .then((response) => { console.log(response) ipfsId = response[0].hash console.log(ipfsId) - this.setState({added_file_hash: ipfsId}) + this.setState({ added_file_hash: ipfsId }) }).catch((err) => { console.error(err) }) @@ -48,12 +43,12 @@ class App extends React.Component { // Example #2 // Add file to IPFS and wrap it in a directory to keep the original filename - saveToIpfsWithFilename (file) { + saveToIpfsWithFilename (files) { + const file = [...files][0] let ipfsId - const fileStream = fileReaderPullStream(file) const fileDetails = { path: file.name, - content: fileStream + content: file } const options = { wrapWithDirectory: true, @@ -65,7 +60,7 @@ class App extends React.Component { // CID of wrapping directory is returned last ipfsId = response[response.length - 1].hash console.log(ipfsId) - this.setState({added_file_hash: ipfsId}) + this.setState({ added_file_hash: ipfsId }) }).catch((err) => { console.error(err) }) diff --git a/examples/upload-file-via-browser/webpack.config.js b/examples/upload-file-via-browser/webpack.config.js index 6dfc86d24..c28ec1168 100644 --- a/examples/upload-file-via-browser/webpack.config.js +++ b/examples/upload-file-via-browser/webpack.config.js @@ -1,14 +1,11 @@ 'use strict' const path = require('path') -const webpack = require('webpack') module.exports = { mode: 'development', devtool: 'eval', entry: [ - 'webpack-dev-server/client?http://localhost:3000', - 'webpack/hot/only-dev-server', './src/index' ], output: { @@ -16,9 +13,6 @@ module.exports = { filename: 'bundle.js', publicPath: '/static/' }, - plugins: [ - new webpack.HotModuleReplacementPlugin() - ], module: { rules: [ { @@ -28,8 +22,7 @@ module.exports = { { loader: 'babel-loader', options: { - presets: ['@babel/preset-env', '@babel/preset-react'], - plugins: ['react-hot-loader/babel'] + presets: ['@babel/preset-env', '@babel/preset-react'] } } ] diff --git a/package.json b/package.json index 43879e244..5296c01ea 100644 --- a/package.json +++ b/package.json @@ -47,8 +47,10 @@ "is-stream": "^2.0.0", "iso-stream-http": "~0.1.2", "iso-url": "~0.4.6", + "ipfs-utils": "~0.0.3", "just-kebab-case": "^1.1.0", "just-map-keys": "^1.1.0", + "kind-of": "^6.0.2", "lru-cache": "^5.1.1", "multiaddr": "^6.0.6", "multibase": "~0.6.0", @@ -83,9 +85,8 @@ "chai": "^4.2.0", "cross-env": "^5.2.0", "dirty-chai": "^2.0.1", - "eslint-plugin-react": "^7.11.1", "go-ipfs-dep": "0.4.19", - "interface-ipfs-core": "~0.101.1", + "interface-ipfs-core": "~0.102.0", "ipfsd-ctl": "~0.42.0", "nock": "^10.0.2", "stream-equal": "^1.1.1" diff --git a/src/files-regular/add.js b/src/files-regular/add.js index c5506b48b..cb5898265 100644 --- a/src/files-regular/add.js +++ b/src/files-regular/add.js @@ -3,10 +3,10 @@ const promisify = require('promisify-es6') const ConcatStream = require('concat-stream') const once = require('once') -const isStream = require('is-stream') -const isSource = require('is-pull-stream').isSource +const { isSource } = require('is-pull-stream') const FileResultStreamConverter = require('../utils/file-result-stream-converter') const SendFilesStream = require('../utils/send-files-stream') +const validateAddInput = require('ipfs-utils/src/files/add-input-validation') module.exports = (send) => { const createAddStream = SendFilesStream(send, 'add') @@ -16,7 +16,6 @@ module.exports = (send) => { _callback = options options = null } - const callback = once(_callback) if (!options) { @@ -24,23 +23,10 @@ module.exports = (send) => { } options.converter = FileResultStreamConverter - // Buffer, pull stream or Node.js stream - const isBufferOrStream = obj => Buffer.isBuffer(obj) || isStream.readable(obj) || isSource(obj) - // An object like { content?, path? }, where content isBufferOrStream and path isString - const isContentObject = obj => { - if (typeof obj !== 'object') return false - // path is optional if content is present - if (obj.content) return isBufferOrStream(obj.content) - // path must be a non-empty string if no content - return Boolean(obj.path) && typeof obj.path === 'string' - } - // An input atom: a buffer, stream or content object - const isInput = obj => isBufferOrStream(obj) || isContentObject(obj) - // All is ok if data isInput or data is an array of isInput - const ok = isInput(_files) || (Array.isArray(_files) && _files.every(isInput)) - - if (!ok) { - return callback(new Error('invalid input: expected buffer, readable stream, pull stream, object or array of objects')) + try { + validateAddInput(_files) + } catch (err) { + return callback(err) } const files = [].concat(_files) diff --git a/src/utils/multipart.js b/src/utils/multipart.js index 22006c435..a6df61fd4 100644 --- a/src/utils/multipart.js +++ b/src/utils/multipart.js @@ -2,8 +2,6 @@ const Transform = require('readable-stream').Transform const isNode = require('detect-node') -const isSource = require('is-pull-stream').isSource -const toStream = require('pull-to-stream') const PADDING = '--' const NEW_LINE = '\r\n' @@ -77,12 +75,7 @@ class Multipart extends Transform { return callback() // early } - if (isSource(content)) { - content = toStream.readable(content) - } - // From now on we assume content is a stream - content.once('error', this.emit.bind(this, 'error')) content.once('end', () => { diff --git a/src/utils/prepare-file.js b/src/utils/prepare-file.js index 738c4a4c0..1ffe3f31c 100644 --- a/src/utils/prepare-file.js +++ b/src/utils/prepare-file.js @@ -2,6 +2,13 @@ const isNode = require('detect-node') const flatmap = require('flatmap') +const { Readable } = require('readable-stream') +const kindOf = require('kind-of') +const { isSource } = require('is-pull-stream') +const isStream = require('is-stream') +const pullToStream = require('pull-to-stream') +const { supportsFileReader } = require('ipfs-utils/src/supports') +const streamFromFileReader = require('ipfs-utils/src/streams/stream-from-filereader') function loadPaths (opts, file) { const path = require('path') @@ -73,10 +80,36 @@ function loadPaths (opts, file) { } } +function contentToStream (content) { + if (supportsFileReader && kindOf(content) === 'file') { + return streamFromFileReader(content) + } + + if (kindOf(content) === 'buffer') { + return new Readable({ + read () { + this.push(content) + this.push(null) + } + }) + } + + if (isSource(content)) { + return pullToStream.readable(content) + } + + if (isStream.readable(content)) { + return content + } + + throw new Error(`Input not supported. Expected Buffer|ReadableStream|PullStream|File got ${kindOf(content)}. Check the documentation for more info https://github.com/ipfs/interface-js-ipfs-core/blob/master/SPEC/FILES.md#add`) +} + function prepareFile (file, opts) { let files = [].concat(file) return flatmap(files, (file) => { + // add from fs with file path if (typeof file === 'string') { if (!isNode) { throw new Error('Can only add file paths in node') @@ -85,20 +118,34 @@ function prepareFile (file, opts) { return loadPaths(opts, file) } - if (file.path && !file.content) { - file.dir = true - return file - } + // add with object syntax { path : , content: Date: Thu, 16 May 2019 22:43:44 +0100 Subject: [PATCH 050/233] chore: update contributors --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5296c01ea..01cbaeefe 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ipfs-http-client", - "version": "31.0.2", + "version": "31.1.0", "description": "A client library for the IPFS HTTP API", "leadMaintainer": "Alan Shaw ", "main": "src/index.js", From c39206da371890c0773b2f4f68446cc5ef2a5073 Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Thu, 16 May 2019 22:43:45 +0100 Subject: [PATCH 051/233] chore: release version v31.1.0 --- CHANGELOG.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a2288fe6b..99d3a523e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,13 @@ + +# [31.1.0](https://github.com/ipfs/js-ipfs-http-client/compare/v31.0.2...v31.1.0) (2019-05-16) + + +### Features + +* add support for File DOM API to files-regular ([#986](https://github.com/ipfs/js-ipfs-http-client/issues/986)) ([7b49f7e](https://github.com/ipfs/js-ipfs-http-client/commit/7b49f7e)) + + + ## [31.0.2](https://github.com/ipfs/js-ipfs-http-client/compare/v31.0.1...v31.0.2) (2019-05-16) From 15ab7c5002c44c5ff1e16998b6597d1f7687f3cd Mon Sep 17 00:00:00 2001 From: Gopalakrishna Palem Date: Fri, 17 May 2019 17:50:04 +0530 Subject: [PATCH 052/233] fix: handle empty array return value in dht.findProvs (#1003) Correcting the array check to happen before the individual element checks. fixes https://github.com/ipfs/js-ipfs-http-client/issues/928 --- src/dht/findprovs.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/dht/findprovs.js b/src/dht/findprovs.js index dd2d82f58..acfd1329f 100644 --- a/src/dht/findprovs.js +++ b/src/dht/findprovs.js @@ -23,17 +23,17 @@ module.exports = (send) => { } const handleResult = (res, callback) => { + // Inconsistent return values in the browser vs node + if (Array.isArray(res)) { + res = res[0] + } + // callback with an empty array if no providers are found if (!res) { const responses = [] return callback(null, responses) } - // Inconsistent return values in the browser vs node - if (Array.isArray(res)) { - res = res[0] - } - // Type 4 keys if (res.Type !== 4) { const errMsg = `key was not found (type 4)` From 961fc4a53c15e600f18d3625dc2a698fed959499 Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Sun, 19 May 2019 13:35:50 +0100 Subject: [PATCH 053/233] chore: appease linter License: MIT Signed-off-by: Alan Shaw --- src/dht/findprovs.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dht/findprovs.js b/src/dht/findprovs.js index acfd1329f..183adfa93 100644 --- a/src/dht/findprovs.js +++ b/src/dht/findprovs.js @@ -27,7 +27,7 @@ module.exports = (send) => { if (Array.isArray(res)) { res = res[0] } - + // callback with an empty array if no providers are found if (!res) { const responses = [] From a423d7f4d8aef0a39e297dfb114b09b7e7e56f05 Mon Sep 17 00:00:00 2001 From: Alex Potsides Date: Tue, 21 May 2019 10:06:44 +0100 Subject: [PATCH 054/233] chore: update ipld formats (#1010) BREAKING CHANGE: The default string encoding for version 1 CIDs has changed to `base32`. IPLD formats have been updated to the latest versions. IPLD nodes returned by `ipfs.dag` and `ipfs.object` commands have significant breaking changes. If you are using these commands in your application you are likely to encounter the following changes to `dag-pb` nodes (the default node type that IPFS creates): * `DAGNode` properties have been renamed as follows: * `data` => `Data` * `links` => `Links` * `size` => `size` (Note: no change) * `DAGLink` properties have been renamed as follows: * `cid` => `Hash` * `name` => `Name` * `size` => `Tsize` See CHANGELOGs for each IPLD format for it's respective changes, you can read more about the [`dag-pb` changes in the CHANGELOG](https://github.com/ipld/js-ipld-dag-pb/blob/master) License: MIT Signed-off-by: Alan Shaw --- package.json | 14 +++++------ src/dag/get.js | 13 +++++++--- src/dag/put.js | 54 +++++++++++++++++++++++------------------- src/object/addLink.js | 15 ++++++------ src/object/get.js | 20 ++++------------ src/object/links.js | 7 +++--- src/object/put.js | 12 +++++----- src/object/rmLink.js | 2 +- test/dag.spec.js | 26 ++++++++++---------- test/interface.spec.js | 5 ++++ 10 files changed, 86 insertions(+), 82 deletions(-) diff --git a/package.json b/package.json index 01cbaeefe..52a4a4ed6 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,7 @@ "bl": "^3.0.0", "bs58": "^4.0.1", "buffer": "^5.2.1", - "cids": "~0.5.8", + "cids": "~0.7.1", "concat-stream": "github:hugomrdias/concat-stream#feat/smaller", "debug": "^4.1.0", "detect-node": "^2.0.4", @@ -39,10 +39,10 @@ "err-code": "^1.1.2", "flatmap": "0.0.3", "glob": "^7.1.3", - "ipfs-block": "~0.8.0", - "ipld-dag-cbor": "~0.13.1", - "ipld-dag-pb": "~0.15.3", - "is-ipfs": "~0.6.0", + "ipfs-block": "~0.8.1", + "ipld-dag-cbor": "~0.15.0", + "ipld-dag-pb": "~0.17.3", + "is-ipfs": "~0.6.1", "is-pull-stream": "0.0.0", "is-stream": "^2.0.0", "iso-stream-http": "~0.1.2", @@ -54,7 +54,7 @@ "lru-cache": "^5.1.1", "multiaddr": "^6.0.6", "multibase": "~0.6.0", - "multicodec": "~0.5.0", + "multicodec": "~0.5.1", "multihashes": "~0.4.14", "ndjson": "github:hugomrdias/ndjson#feat/readable-stream3", "once": "^1.4.0", @@ -86,7 +86,7 @@ "cross-env": "^5.2.0", "dirty-chai": "^2.0.1", "go-ipfs-dep": "0.4.19", - "interface-ipfs-core": "~0.102.0", + "interface-ipfs-core": "~0.103.0", "ipfsd-ctl": "~0.42.0", "nock": "^10.0.2", "stream-equal": "^1.1.1" diff --git a/src/dag/get.js b/src/dag/get.js index dc4e46b4a..c46ada33c 100644 --- a/src/dag/get.js +++ b/src/dag/get.js @@ -46,13 +46,20 @@ module.exports = (send) => { }, (ipfsBlock, path, cb) => { const dagResolver = resolvers[ipfsBlock.cid.codec] + if (!dagResolver) { const error = new Error('ipfs-http-client is missing DAG resolver for "' + ipfsBlock.cid.codec + '" multicodec') error.missingMulticodec = ipfsBlock.cid.codec - cb(error) - return + return cb(error) + } + + let res + try { + res = dagResolver.resolve(ipfsBlock.data, path) + } catch (err) { + return cb(err) } - dagResolver.resolve(ipfsBlock.data, path, cb) + cb(null, res) } ], callback) }) diff --git a/src/dag/put.js b/src/dag/put.js index 636d39ae4..42d92b285 100644 --- a/src/dag/put.js +++ b/src/dag/put.js @@ -50,34 +50,38 @@ module.exports = (send) => { options = Object.assign(optionDefaults, options) - if (options.format === 'dag-cbor') { - dagCBOR.util.serialize(dagNode, finalize) - } else if (options.format === 'dag-pb') { - dagPB.util.serialize(dagNode, finalize) - } else { - // FIXME Hopefully already serialized...can we use IPLD to serialise instead? - finalize(null, dagNode) + let serialized + + try { + if (options.format === 'dag-cbor') { + serialized = dagCBOR.util.serialize(dagNode) + } else if (options.format === 'dag-pb') { + serialized = dagPB.util.serialize(dagNode) + } else { + // FIXME Hopefully already serialized...can we use IPLD to serialise instead? + serialized = dagNode + } + } catch (err) { + return callback(err) } - function finalize (err, serialized) { - if (err) { return callback(err) } - const sendOptions = { - qs: { - hash: options.hashAlg, - format: options.format, - 'input-enc': options.inputEnc - } + const sendOptions = { + qs: { + hash: options.hashAlg, + format: options.format, + 'input-enc': options.inputEnc } - sendOneFile(serialized, sendOptions, (err, result) => { - if (err) { - return callback(err) - } - if (result['Cid']) { - return callback(null, new CID(result['Cid']['/'])) - } else { - return callback(result) - } - }) } + + sendOneFile(serialized, sendOptions, (err, result) => { + if (err) { + return callback(err) + } + if (result['Cid']) { + return callback(null, new CID(result['Cid']['/'])) + } else { + return callback(result) + } + }) }) } diff --git a/src/object/addLink.js b/src/object/addLink.js index 75087578b..bda202bce 100644 --- a/src/object/addLink.js +++ b/src/object/addLink.js @@ -19,14 +19,13 @@ module.exports = (send) => { return callback(err) } - send({ - path: 'object/patch/add-link', - args: [ - cid.toString(), - dLink.name, - dLink.cid.toString() - ] - }, (err, result) => { + const args = [ + cid.toString(), + dLink.Name || dLink.name || null, + (dLink.Hash || dLink.cid || '').toString() || null + ] + + send({ path: 'object/patch/add-link', args }, (err, result) => { if (err) { return callback(err) } diff --git a/src/object/get.js b/src/object/get.js index a8d44db92..1450c3792 100644 --- a/src/object/get.js +++ b/src/object/get.js @@ -1,9 +1,7 @@ 'use strict' const promisify = require('promisify-es6') -const dagPB = require('ipld-dag-pb') -const DAGNode = dagPB.DAGNode -const DAGLink = dagPB.DAGLink +const { DAGNode, DAGLink } = require('ipld-dag-pb') const CID = require('cids') const LRU = require('lru-cache') const lruOptions = { @@ -49,19 +47,11 @@ module.exports = (send) => { return callback(err) } - result.Data = Buffer.from(result.Data, 'base64') + const links = result.Links.map(l => new DAGLink(l.Name, l.Size, l.Hash)) + const node = DAGNode.create(Buffer.from(result.Data, 'base64'), links) - const links = result.Links.map((l) => { - return new DAGLink(l.Name, l.Size, l.Hash) - }) - - DAGNode.create(result.Data, links, (err, node) => { - if (err) { - return callback(err) - } - cache.set(cidB58Str, node) - callback(null, node) - }) + cache.set(cidB58Str, node) + callback(null, node) }) }) } diff --git a/src/object/links.js b/src/object/links.js index 41527d998..0b0366c81 100644 --- a/src/object/links.js +++ b/src/object/links.js @@ -1,8 +1,7 @@ 'use strict' const promisify = require('promisify-es6') -const dagPB = require('ipld-dag-pb') -const DAGLink = dagPB.DAGLink +const { DAGLink } = require('ipld-dag-pb') const CID = require('cids') const LRU = require('lru-cache') const lruOptions = { @@ -44,7 +43,9 @@ module.exports = (send) => { let links = [] if (result.Links) { - links = result.Links.map((l) => new DAGLink(l.Name, l.Size, l.Hash)) + links = result.Links.map((l) => { + return new DAGLink(l.Name, l.Size, l.Hash) + }) } callback(null, links) }) diff --git a/src/object/put.js b/src/object/put.js index 0b624f7f9..40b9ffac4 100644 --- a/src/object/put.js +++ b/src/object/put.js @@ -36,12 +36,12 @@ module.exports = (send) => { } } else if (DAGNode.isDAGNode(obj)) { tmpObj = { - Data: obj.data.toString(), - Links: obj.links.map((l) => { - const link = l.toJSON() - link.hash = link.cid - return link - }) + Data: obj.Data.toString(), + Links: obj.Links.map(l => ({ + Name: l.Name, + Hash: l.Hash.toString(), + Size: l.Tsize + })) } } else if (typeof obj === 'object') { tmpObj.Data = obj.Data.toString() diff --git a/src/object/rmLink.js b/src/object/rmLink.js index 4726bb216..db699feeb 100644 --- a/src/object/rmLink.js +++ b/src/object/rmLink.js @@ -23,7 +23,7 @@ module.exports = (send) => { path: 'object/patch/rm-link', args: [ cid.toString(), - dLink.name + dLink.Name || dLink.name || null ] }, (err, result) => { if (err) { diff --git a/test/dag.spec.js b/test/dag.spec.js index 0b1a2f314..1b0cfc683 100644 --- a/test/dag.spec.js +++ b/test/dag.spec.js @@ -8,8 +8,7 @@ const dirtyChai = require('dirty-chai') const expect = chai.expect chai.use(dirtyChai) const series = require('async/series') -const dagPB = require('ipld-dag-pb') -const DAGNode = dagPB.DAGNode +const { DAGNode } = require('ipld-dag-pb') const CID = require('cids') const ipfsClient = require('../src') const f = require('./utils/factory') @@ -37,20 +36,19 @@ describe('.dag', function () { it('should be able to put and get a DAG node with format dag-pb', (done) => { const data = Buffer.from('some data') - DAGNode.create(data, (err, node) => { + const node = DAGNode.create(data) + + ipfs.dag.put(node, { format: 'dag-pb', hashAlg: 'sha2-256' }, (err, cid) => { expect(err).to.not.exist() - ipfs.dag.put(node, { format: 'dag-pb', hashAlg: 'sha2-256' }, (err, cid) => { + cid = cid.toV0() + expect(cid.codec).to.equal('dag-pb') + cid = cid.toBaseEncodedString('base58btc') + // expect(cid).to.equal('bafybeig3t3eugdchignsgkou3ly2mmy4ic4gtfor7inftnqn3yq4ws3a5u') + expect(cid).to.equal('Qmd7xRhW5f29QuBFtqu3oSD27iVy35NRB91XFjmKFhtgMr') + ipfs.dag.get(cid, (err, result) => { expect(err).to.not.exist() - cid = cid.toV0() - expect(cid.codec).to.equal('dag-pb') - cid = cid.toBaseEncodedString('base58btc') - // expect(cid).to.equal('bafybeig3t3eugdchignsgkou3ly2mmy4ic4gtfor7inftnqn3yq4ws3a5u') - expect(cid).to.equal('Qmd7xRhW5f29QuBFtqu3oSD27iVy35NRB91XFjmKFhtgMr') - ipfs.dag.get(cid, (err, result) => { - expect(err).to.not.exist() - expect(result.value.data).to.deep.equal(data) - done() - }) + expect(result.value.Data).to.deep.equal(data) + done() }) }) }) diff --git a/test/interface.spec.js b/test/interface.spec.js index a5eed428c..f960238d7 100644 --- a/test/interface.spec.js +++ b/test/interface.spec.js @@ -173,6 +173,11 @@ describe('interface-ipfs-core tests', () => { isNode ? null : { name: 'should readable stream ls with a base58 encoded CID', reason: 'FIXME https://github.com/ipfs/js-ipfs-http-client/issues/339' + }, + // .refs + { + name: 'dag refs test', + reason: 'FIXME unskip when 0.4.21 is released' } ] }) From e22afea118a9ae24e9145090f7707c2ffda81669 Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Tue, 21 May 2019 10:25:11 +0100 Subject: [PATCH 055/233] chore: update contributors --- package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 52a4a4ed6..409c0c7ec 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ipfs-http-client", - "version": "31.1.0", + "version": "32.0.0", "description": "A client library for the IPFS HTTP API", "leadMaintainer": "Alan Shaw ", "main": "src/index.js", @@ -117,6 +117,7 @@ "Friedel Ziegelmayer ", "Gar ", "Gavin McDermott ", + "Gopalakrishna Palem ", "Greenkeeper ", "Haad ", "Harlan T Wood ", From 6ce77f7ecf2123cf59cdcd2698bb6c28eee0ec4d Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Tue, 21 May 2019 10:25:12 +0100 Subject: [PATCH 056/233] chore: release version v32.0.0 --- CHANGELOG.md | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 99d3a523e..850618174 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,39 @@ + +# [32.0.0](https://github.com/ipfs/js-ipfs-http-client/compare/v31.1.0...v32.0.0) (2019-05-21) + + +### Bug Fixes + +* handle empty array return value in dht.findProvs ([#1003](https://github.com/ipfs/js-ipfs-http-client/issues/1003)) ([15ab7c5](https://github.com/ipfs/js-ipfs-http-client/commit/15ab7c5)) + + +### Chores + +* update ipld formats ([#1010](https://github.com/ipfs/js-ipfs-http-client/issues/1010)) ([a423d7f](https://github.com/ipfs/js-ipfs-http-client/commit/a423d7f)) + + +### BREAKING CHANGES + +* The default string encoding for version 1 CIDs has changed to `base32`. + +IPLD formats have been updated to the latest versions. IPLD nodes returned by `ipfs.dag` and `ipfs.object` commands have significant breaking changes. If you are using these commands in your application you are likely to encounter the following changes to `dag-pb` nodes (the default node type that IPFS creates): + +* `DAGNode` properties have been renamed as follows: + * `data` => `Data` + * `links` => `Links` + * `size` => `size` (Note: no change) +* `DAGLink` properties have been renamed as follows: + * `cid` => `Hash` + * `name` => `Name` + * `size` => `Tsize` + +See CHANGELOGs for each IPLD format for it's respective changes, you can read more about the [`dag-pb` changes in the CHANGELOG](https://github.com/ipld/js-ipld-dag-pb/blob/master) + +License: MIT +Signed-off-by: Alan Shaw + + + # [31.1.0](https://github.com/ipfs/js-ipfs-http-client/compare/v31.0.2...v31.1.0) (2019-05-16) From a28b009cdf470d84059c438b73beb20bf32be830 Mon Sep 17 00:00:00 2001 From: Alex Potsides Date: Tue, 21 May 2019 20:44:25 +0100 Subject: [PATCH 057/233] fix: send trickle param to trigger trickle dag builder (#1015) --- src/utils/send-files-stream.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/utils/send-files-stream.js b/src/utils/send-files-stream.js index c2450d39e..4c91798fc 100644 --- a/src/utils/send-files-stream.js +++ b/src/utils/send-files-stream.js @@ -81,6 +81,10 @@ module.exports = (send, path) => { qs['wrap-with-directory'] = propOrProp(options, 'wrap-with-directory', 'wrapWithDirectory') qs.hash = propOrProp(options, 'hash', 'hashAlg') + if (options.strategy === 'trickle' || options.trickle) { + qs['trickle'] = 'true' + } + const args = { path: path, qs: qs, From 4251c88c28dc35a0463a907867649eeff4404746 Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Tue, 21 May 2019 22:00:26 +0100 Subject: [PATCH 058/233] fix: error reporting for non-JSON responses (#1016) Better error reporting by detecting `Content-Type` of the response and not attempting to parse JSON for non-`application/json` responses. resolves #912 resolves #1000 closes #1001 License: MIT Signed-off-by: Alan Shaw --- src/utils/send-request.js | 21 ++++++++- src/utils/stream-to-json-value.js | 2 +- test/request-api.spec.js | 74 +++++++++++++++++++++++++++++++ 3 files changed, 94 insertions(+), 3 deletions(-) diff --git a/src/utils/send-request.js b/src/utils/send-request.js index 219327adf..1645969f2 100644 --- a/src/utils/send-request.js +++ b/src/utils/send-request.js @@ -13,8 +13,26 @@ const log = require('debug')('ipfs-http-client:request') // -- Internal +function hasJSONHeaders (res) { + return res.headers['content-type'] && + res.headers['content-type'].indexOf('application/json') === 0 +} + function parseError (res, cb) { const error = new Error(`Server responded with ${res.statusCode}`) + error.statusCode = res.statusCode + + if (!hasJSONHeaders(res)) { + return streamToValue(res, (err, data) => { // eslint-disable-line handle-callback-err + // the `err` here refers to errors in stream processing, which + // we ignore here, since we already have a valid `error` response + // from the server above that we have to report to the caller. + if (data && data.length) { + error.message = data.toString() + } + cb(error) + }) + } streamToJsonValue(res, (err, payload) => { if (err) { @@ -34,8 +52,7 @@ function onRes (buffer, cb) { return (res) => { const stream = Boolean(res.headers['x-stream-output']) const chunkedObjects = Boolean(res.headers['x-chunked-output']) - const isJson = res.headers['content-type'] && - res.headers['content-type'].indexOf('application/json') === 0 + const isJson = hasJSONHeaders(res) if (res.req) { log(res.req.method, `${res.req.getHeaders().host}${res.req.path}`, res.statusCode, res.statusMessage) diff --git a/src/utils/stream-to-json-value.js b/src/utils/stream-to-json-value.js index e42de2fc6..2ae83e50d 100644 --- a/src/utils/stream-to-json-value.js +++ b/src/utils/stream-to-json-value.js @@ -24,7 +24,7 @@ function streamToJsonValue (res, cb) { try { res = JSON.parse(data) } catch (err) { - return cb(err) + return cb(new Error(`Invalid JSON: ${data}`)) } cb(null, res) diff --git a/test/request-api.spec.js b/test/request-api.spec.js index 02f342e53..a9b2fcf2e 100644 --- a/test/request-api.spec.js +++ b/test/request-api.spec.js @@ -65,3 +65,77 @@ describe('trailer headers', () => { }) }) }) + +describe('error handling', () => { + it('should handle plain text error response', function (done) { + if (!isNode) return this.skip() + + const server = require('http').createServer((req, res) => { + // Consume the entire request, before responding. + req.on('data', () => {}) + req.on('end', () => { + // Write a text/plain response with a 403 (forbidden) status + res.writeHead(403, { 'Content-Type': 'text/plain' }) + res.write('ipfs method not allowed') + res.end() + }) + }) + + server.listen(6001, () => { + ipfsClient('/ip4/127.0.0.1/tcp/6001').config.replace('test/fixtures/r-config.json', (err) => { + expect(err).to.exist() + expect(err.statusCode).to.equal(403) + expect(err.message).to.equal('ipfs method not allowed') + server.close(done) + }) + }) + }) + + it('should handle JSON error response', function (done) { + if (!isNode) return this.skip() + + const server = require('http').createServer((req, res) => { + // Consume the entire request, before responding. + req.on('data', () => {}) + req.on('end', () => { + // Write a application/json response with a 400 (bad request) header + res.writeHead(400, { 'Content-Type': 'application/json' }) + res.write(JSON.stringify({ Message: 'client error', Code: 1 })) + res.end() + }) + }) + + server.listen(6001, () => { + ipfsClient('/ip4/127.0.0.1/tcp/6001').config.replace('test/fixtures/r-config.json', (err) => { + expect(err).to.exist() + expect(err.statusCode).to.equal(400) + expect(err.message).to.equal('client error') + expect(err.code).to.equal(1) + server.close(done) + }) + }) + }) + + it('should handle JSON error response with invalid JSON', function (done) { + if (!isNode) return this.skip() + + const server = require('http').createServer((req, res) => { + // Consume the entire request, before responding. + req.on('data', () => {}) + req.on('end', () => { + // Write a application/json response with a 400 (bad request) header + res.writeHead(400, { 'Content-Type': 'application/json' }) + res.write('{ Message: ') + res.end() + }) + }) + + server.listen(6001, () => { + ipfsClient('/ip4/127.0.0.1/tcp/6001').config.replace('test/fixtures/r-config.json', (err) => { + expect(err).to.exist() + expect(err.message).to.include('Invalid JSON') + server.close(done) + }) + }) + }) +}) From 5dbf3f3b69840450a83a8b24cd05424402ae6b89 Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Tue, 21 May 2019 22:13:43 +0100 Subject: [PATCH 059/233] chore: update contributors --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 409c0c7ec..50f63ae52 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ipfs-http-client", - "version": "32.0.0", + "version": "32.0.1", "description": "A client library for the IPFS HTTP API", "leadMaintainer": "Alan Shaw ", "main": "src/index.js", From 57af61611736a27551008774c030a6486f74a47b Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Tue, 21 May 2019 22:13:44 +0100 Subject: [PATCH 060/233] chore: release version v32.0.1 --- CHANGELOG.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 850618174..1ed4603c5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,14 @@ + +## [32.0.1](https://github.com/ipfs/js-ipfs-http-client/compare/v32.0.0...v32.0.1) (2019-05-21) + + +### Bug Fixes + +* error reporting for non-JSON responses ([#1016](https://github.com/ipfs/js-ipfs-http-client/issues/1016)) ([4251c88](https://github.com/ipfs/js-ipfs-http-client/commit/4251c88)), closes [#912](https://github.com/ipfs/js-ipfs-http-client/issues/912) [#1000](https://github.com/ipfs/js-ipfs-http-client/issues/1000) [#1001](https://github.com/ipfs/js-ipfs-http-client/issues/1001) +* send trickle param to trigger trickle dag builder ([#1015](https://github.com/ipfs/js-ipfs-http-client/issues/1015)) ([a28b009](https://github.com/ipfs/js-ipfs-http-client/commit/a28b009)) + + + # [32.0.0](https://github.com/ipfs/js-ipfs-http-client/compare/v31.1.0...v32.0.0) (2019-05-21) From 6c528766b2dd0e2ec8c890ffb37ad3ccc33d0dd4 Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Thu, 23 May 2019 13:32:51 +0100 Subject: [PATCH 061/233] chore: update min bundlesize (#1019) We added some functionality and made it a tiny bit bigger, sorry. This will hopefully come down again when we switch to async await and async iterators. --- .aegir.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.aegir.js b/.aegir.js index fe08c25af..1deee7d74 100644 --- a/.aegir.js +++ b/.aegir.js @@ -5,7 +5,7 @@ const createServer = require('ipfsd-ctl').createServer const server = createServer() module.exports = { - bundlesize: { maxSize: '232kB' }, + bundlesize: { maxSize: '236kB' }, webpack: { resolve: { mainFields: ['browser', 'main'] From b16e62c94941d7675d989972c1cb4af8605d6fb5 Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Thu, 23 May 2019 13:33:09 +0100 Subject: [PATCH 062/233] chore: remove commitlint from check stage in CI (#1018) See https://github.com/ipfs/aegir/issues/345 --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 7428d50be..0be5b0ef5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -25,7 +25,6 @@ jobs: - stage: check script: - npx aegir build --bundlesize - - npx aegir commitlint --travis - npx aegir dep-check - npm run lint From a04edaca59b2aba654329aa4ecfa11ffb5ec7692 Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" Date: Tue, 28 May 2019 08:55:15 +0100 Subject: [PATCH 063/233] fix(package): update bignumber.js to version 9.0.0 (#1024) --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 50f63ae52..4147effca 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,7 @@ }, "dependencies": { "async": "^2.6.1", - "bignumber.js": "^8.0.2", + "bignumber.js": "^9.0.0", "bl": "^3.0.0", "bs58": "^4.0.1", "buffer": "^5.2.1", From 806b206e5b494001ee5578916fb3d0a875978498 Mon Sep 17 00:00:00 2001 From: Hugo Dias Date: Sun, 9 Jun 2019 13:02:36 +0100 Subject: [PATCH 064/233] fix: prepare for aegir release (#1021) * fix: prepare for aegir release * chore: tweak node version in ci * chore: test electron * chore: test electron 2 * chore: upgrade aegir * chore: fix electron ci test * chore: fix ci tests * chore: allow fail electron-renderer * chore: test allow failure * chore: test allow failure 2 --- .travis.yml | 18 +++++++++++++++++- package.json | 41 ++++++++++++++++++---------------------- test/constructor.spec.js | 4 ++-- 3 files changed, 37 insertions(+), 26 deletions(-) diff --git a/.travis.yml b/.travis.yml index 0be5b0ef5..1368eb6eb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,7 +7,7 @@ stages: node_js: - '10' - - '8' + - '12' os: - linux @@ -17,10 +17,16 @@ script: npx nyc -s npm run test:node -- --bail after_success: npx nyc report --reporter=text-lcov > coverage.lcov && npx codecov jobs: + allow_failures: + - name: electron-renderer + + fast_finish: true + include: - os: windows filter_secrets: false cache: false + - stage: check script: @@ -39,6 +45,16 @@ jobs: addons: firefox: latest script: npx aegir test -t browser -t webworker -- --browsers FirefoxHeadless + + - stage: test + name: electron-main + script: + - xvfb-run npx aegir test -t electron-main -- --bail + + - stage: test + name: electron-renderer + script: + - xvfb-run npx aegir test -t electron-renderer -- --bail notifications: email: false diff --git a/package.json b/package.json index 4147effca..24ef30c8c 100644 --- a/package.json +++ b/package.json @@ -2,17 +2,24 @@ "name": "ipfs-http-client", "version": "32.0.1", "description": "A client library for the IPFS HTTP API", + "keywords": [ + "ipfs" + ], + "homepage": "https://github.com/ipfs/js-ipfs-http-client", + "bugs": "https://github.com/ipfs/js-ipfs-http-client/issues", + "license": "MIT", "leadMaintainer": "Alan Shaw ", + "files": [ + "src", + "dist" + ], "main": "src/index.js", "browser": { "glob": false, "fs": false, "stream": "readable-stream" }, - "files": [ - "src", - "dist" - ], + "repository": "github:ipfs/js-ipfs-http-client", "scripts": { "test": "aegir test", "test:node": "aegir test -t node", @@ -40,6 +47,7 @@ "flatmap": "0.0.3", "glob": "^7.1.3", "ipfs-block": "~0.8.1", + "ipfs-utils": "~0.0.3", "ipld-dag-cbor": "~0.15.0", "ipld-dag-pb": "~0.17.3", "is-ipfs": "~0.6.1", @@ -47,7 +55,6 @@ "is-stream": "^2.0.0", "iso-stream-http": "~0.1.2", "iso-url": "~0.4.6", - "ipfs-utils": "~0.0.3", "just-kebab-case": "^1.1.0", "just-map-keys": "^1.1.0", "kind-of": "^6.0.2", @@ -71,16 +78,8 @@ "tar-stream": "^2.0.1", "through2": "^3.0.1" }, - "engines": { - "node": ">=8.3.0", - "npm": ">=3.0.0" - }, - "repository": { - "type": "git", - "url": "https://github.com/ipfs/js-ipfs-http-client" - }, "devDependencies": { - "aegir": "^18.2.2", + "aegir": "^19.0.3", "browser-process-platform": "~0.1.1", "chai": "^4.2.0", "cross-env": "^5.2.0", @@ -91,9 +90,10 @@ "nock": "^10.0.2", "stream-equal": "^1.1.1" }, - "keywords": [ - "ipfs" - ], + "engines": { + "node": ">=8.3.0", + "npm": ">=3.0.0" + }, "contributors": [ "Alan Shaw ", "Alan Shaw ", @@ -184,10 +184,5 @@ "victorbjelkholm ", "Łukasz Magiera ", "Łukasz Magiera " - ], - "license": "MIT", - "bugs": { - "url": "https://github.com/ipfs/js-ipfs-http-client/issues" - }, - "homepage": "https://github.com/ipfs/js-ipfs-http-client" + ] } diff --git a/test/constructor.spec.js b/test/constructor.spec.js index af77d18e1..c138b7fb0 100644 --- a/test/constructor.spec.js +++ b/test/constructor.spec.js @@ -143,8 +143,8 @@ function clientWorks (client, done) { function expectConfig (ipfs, { host, port, protocol, apiPath }) { const conf = ipfs.getEndpointConfig() - expect(conf.host).to.equal(host || 'localhost') - expect(conf.port).to.equal(port || '5001') + expect(conf.host).to.be.oneOf([host, 'localhost', '']) + expect(conf.port).to.be.oneOf([port, '5001', 80]) expect(conf.protocol).to.equal(protocol || 'http') expect(conf['api-path']).to.equal(apiPath || '/api/v0/') } From fdbfb39c077fa9bfe1ea9ad2847a20bc77d4d4ec Mon Sep 17 00:00:00 2001 From: Hugo Dias Date: Thu, 20 Jun 2019 11:45:40 +0100 Subject: [PATCH 065/233] test: adds tests for `ipfs name` (#974) * fix: adds tests to `ipfs name` * fix: add correct interface-core * fix: fix tests and update deps * fix: remove local name tests * fix: fix mfs timeout * fix: skip ping tests that fail with latest go-ipfs * chore: update interface-ipfs-core dep * chore: update ctl --- package.json | 6 +-- test/files-mfs.spec.js | 9 ++-- test/interface.spec.js | 23 +++++++++- test/name.spec.js | 101 ----------------------------------------- 4 files changed, 29 insertions(+), 110 deletions(-) delete mode 100644 test/name.spec.js diff --git a/package.json b/package.json index 24ef30c8c..d9b58aa83 100644 --- a/package.json +++ b/package.json @@ -84,9 +84,9 @@ "chai": "^4.2.0", "cross-env": "^5.2.0", "dirty-chai": "^2.0.1", - "go-ipfs-dep": "0.4.19", - "interface-ipfs-core": "~0.103.0", - "ipfsd-ctl": "~0.42.0", + "go-ipfs-dep": "~0.4.21", + "interface-ipfs-core": "~0.105.0", + "ipfsd-ctl": "~0.43.0", "nock": "^10.0.2", "stream-equal": "^1.1.1" }, diff --git a/test/files-mfs.spec.js b/test/files-mfs.spec.js index f88e37ba9..f9b46cdd7 100644 --- a/test/files-mfs.spec.js +++ b/test/files-mfs.spec.js @@ -25,14 +25,14 @@ const HASH_ALGS = [ 'sha1', 'sha2-256', 'sha2-512', - 'keccak-224', + // 'keccak-224', // go throws 'keccak-256', - 'keccak-384', + // 'keccak-384', // go throws 'keccak-512' ] describe('.files (the MFS API part)', function () { - this.timeout(120 * 1000) + this.timeout(20 * 1000) let ipfsd let ipfs @@ -95,7 +95,7 @@ describe('.files (the MFS API part)', function () { }) it('.add with cid-version=1 and raw-leaves=false', (done) => { - const expectedCid = 'zdj7Wh9x6gXdg4UAqhRYnjBTw9eJF7hvzUU4HjpnZXHYQz9jK' + const expectedCid = 'bafybeifogzovjqrcxvgt7g36y7g63hvwvoakledwk4b2fr2dl4wzawpnny' const options = { 'cid-version': 1, 'raw-leaves': false } ipfs.add(testfile, options, (err, res) => { @@ -109,7 +109,6 @@ describe('.files (the MFS API part)', function () { }) it('.add with only-hash=true', function () { - this.slow(10 * 1000) const content = String(Math.random() + Date.now()) return ipfs.add(Buffer.from(content), { onlyHash: true }) diff --git a/test/interface.spec.js b/test/interface.spec.js index f960238d7..127fbe4fa 100644 --- a/test/interface.spec.js +++ b/test/interface.spec.js @@ -209,6 +209,12 @@ describe('interface-ipfs-core tests', () => { ] }) + tests.name(CommonFactory.create({ + spawnOptions: { + args: ['--offline'] + } + })) + // TODO: uncomment after https://github.com/ipfs/interface-ipfs-core/pull/361 being merged and a new release tests.namePubsub(CommonFactory.create({ spawnOptions: { @@ -234,7 +240,22 @@ describe('interface-ipfs-core tests', () => { tests.pin(defaultCommonFactory) - tests.ping(defaultCommonFactory) + tests.ping(defaultCommonFactory, { + skip: [ + { + name: 'should fail when pinging an unknown peer over pull stream', + reason: 'FIXME go-ipfs return success with text: Looking up peer ' + }, + { + name: 'should fail when pinging peer that is not available over readable stream', + reason: 'FIXME go-ipfs return success with text: Looking up peer ' + }, + { + name: 'should fail when pinging a peer that is not available', + reason: 'FIXME go-ipfs return success with text: Looking up peer ' + } + ] + }) tests.pubsub(CommonFactory.create({ spawnOptions: { diff --git a/test/name.spec.js b/test/name.spec.js deleted file mode 100644 index 67c19f94a..000000000 --- a/test/name.spec.js +++ /dev/null @@ -1,101 +0,0 @@ -/* eslint-env mocha */ -'use strict' - -const chai = require('chai') -const dirtyChai = require('dirty-chai') -const expect = chai.expect -chai.use(dirtyChai) - -const parallel = require('async/parallel') -const series = require('async/series') -const loadFixture = require('aegir/fixtures') - -const ipfsClient = require('../src') -const f = require('./utils/factory') - -const testfile = loadFixture('test/fixtures/testfile.txt') - -describe('.name', () => { - let ipfs - let ipfsd - let other - let otherd - let name - let testFileCid - - before(function (done) { - this.timeout(30 * 1000) - - series([ - (cb) => { - f.spawn({ initOptions: { bits: 1024, profile: 'test' } }, (err, _ipfsd) => { - expect(err).to.not.exist() - ipfsd = _ipfsd - ipfs = ipfsClient(_ipfsd.apiAddr) - cb() - }) - }, - (cb) => { - f.spawn({ initOptions: { bits: 1024, profile: 'test' } }, (err, node) => { - expect(err).to.not.exist() - other = node.api - otherd = node - cb() - }) - }, - (cb) => { - parallel([ - (cb) => { - ipfs.id((err, id) => { - expect(err).to.not.exist() - const ma = id.addresses[0] - other.swarm.connect(ma, cb) - }) - }, - (cb) => { - ipfs.add(testfile, (err, res) => { - expect(err).to.not.exist() - testFileCid = res[0].hash - cb() - }) - } - ], cb) - } - ], done) - }) - - after(function (done) { - this.timeout(10 * 1000) - - parallel([ - (cb) => { - if (!ipfsd) return cb() - ipfsd.stop(cb) - }, - (cb) => { - if (!otherd) return cb() - otherd.stop(cb) - } - ], done) - }) - - it('.name.publish', function (done) { - this.timeout(5 * 60 * 1000) - - ipfs.name.publish(testFileCid, (err, res) => { - expect(err).to.not.exist() - name = res - expect(name).to.exist() - done() - }) - }) - - it('.name.resolve', (done) => { - ipfs.name.resolve(name.name, (err, res) => { - expect(err).to.not.exist() - expect(res).to.exist() - expect(res).to.be.eql(name.value) - done() - }) - }) -}) From 70cdf257d6609e32fb664fe682b05b7212fc2b5d Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Wed, 3 Jul 2019 08:48:54 +0100 Subject: [PATCH 066/233] fix: link to ipfs.io --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c4544e791..23e800092 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@

- IPFS http client lib logo + IPFS http client lib logo

The JavaScript HTTP client library for IPFS implementations.

From a74b8f77eb926dc32162c413f61fe9b4f10f513e Mon Sep 17 00:00:00 2001 From: Alex Potsides Date: Wed, 10 Jul 2019 09:18:00 +0100 Subject: [PATCH 067/233] fix: sometimes no Addrs element is present in the response (#1037) --- src/dht/findprovs.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/dht/findprovs.js b/src/dht/findprovs.js index 183adfa93..84c1df8f9 100644 --- a/src/dht/findprovs.js +++ b/src/dht/findprovs.js @@ -44,11 +44,13 @@ module.exports = (send) => { const responses = res.Responses.map((r) => { const peerInfo = new PeerInfo(PeerId.createFromB58String(r.ID)) - r.Addrs.forEach((addr) => { - const ma = multiaddr(addr) + if (r.Addrs) { + r.Addrs.forEach((addr) => { + const ma = multiaddr(addr) - peerInfo.multiaddrs.add(ma) - }) + peerInfo.multiaddrs.add(ma) + }) + } return peerInfo }) From 63d21250f9d6dc08d40f615e5cd341c08d5e3b50 Mon Sep 17 00:00:00 2001 From: dirkmc Date: Wed, 10 Jul 2019 04:59:17 -0400 Subject: [PATCH 068/233] GC endpoint (#992) * feat: gc * fix: better repo.gc() response handling * fix: repo.gc() cid handling * chore: update interface-ipfs-core --- package.json | 2 +- src/repo/gc.js | 21 +++++++++++++++++++-- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index d9b58aa83..cdd0ff456 100644 --- a/package.json +++ b/package.json @@ -85,7 +85,7 @@ "cross-env": "^5.2.0", "dirty-chai": "^2.0.1", "go-ipfs-dep": "~0.4.21", - "interface-ipfs-core": "~0.105.0", + "interface-ipfs-core": "~0.106.0", "ipfsd-ctl": "~0.43.0", "nock": "^10.0.2", "stream-equal": "^1.1.1" diff --git a/src/repo/gc.js b/src/repo/gc.js index 27a9d3ca8..35d4288b0 100644 --- a/src/repo/gc.js +++ b/src/repo/gc.js @@ -1,6 +1,15 @@ 'use strict' const promisify = require('promisify-es6') +const streamToValueWithTransformer = require('../utils/stream-to-value-with-transformer') +const CID = require('cids') + +const transform = function (res, callback) { + callback(null, res.map(r => ({ + err: r.Err ? new Error(r.Err) : null, + cid: (r.Key || {})['/'] ? new CID(r.Key['/']) : null + }))) +} module.exports = (send) => { return promisify((opts, callback) => { @@ -8,9 +17,17 @@ module.exports = (send) => { callback = opts opts = {} } - send({ + + const request = { path: 'repo/gc', qs: opts - }, callback) + } + send(request, (err, result) => { + if (err) { + return callback(err) + } + + streamToValueWithTransformer(result, transform, callback) + }) }) } From 303a610aaa6408fc2fce548a0d539ad9e901122a Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Wed, 10 Jul 2019 10:19:15 +0100 Subject: [PATCH 069/233] chore: update contributors --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index cdd0ff456..1ace9bdd5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ipfs-http-client", - "version": "32.0.1", + "version": "33.0.0", "description": "A client library for the IPFS HTTP API", "keywords": [ "ipfs" From 689a5a17a6b99f83d314ee5a09fd73fca795033e Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Wed, 10 Jul 2019 10:19:16 +0100 Subject: [PATCH 070/233] chore: release version v33.0.0 --- CHANGELOG.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1ed4603c5..38b6715f9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,16 @@ + +# [33.0.0](https://github.com/ipfs/js-ipfs-http-client/compare/v32.0.1...v33.0.0) (2019-07-10) + + +### Bug Fixes + +* link to ipfs.io ([70cdf25](https://github.com/ipfs/js-ipfs-http-client/commit/70cdf25)) +* prepare for aegir release ([#1021](https://github.com/ipfs/js-ipfs-http-client/issues/1021)) ([806b206](https://github.com/ipfs/js-ipfs-http-client/commit/806b206)) +* sometimes no Addrs element is present in the response ([#1037](https://github.com/ipfs/js-ipfs-http-client/issues/1037)) ([a74b8f7](https://github.com/ipfs/js-ipfs-http-client/commit/a74b8f7)) +* **package:** update bignumber.js to version 9.0.0 ([#1024](https://github.com/ipfs/js-ipfs-http-client/issues/1024)) ([a04edac](https://github.com/ipfs/js-ipfs-http-client/commit/a04edac)) + + + ## [32.0.1](https://github.com/ipfs/js-ipfs-http-client/compare/v32.0.0...v32.0.1) (2019-05-21) From 1a8bcdd7d18b59398d6bba5a4173059f1e3785e6 Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Wed, 10 Jul 2019 12:56:18 +0100 Subject: [PATCH 071/233] chore: use test profile for swarm tests (#1038) Saves 1 minute running them locally. License: MIT Signed-off-by: Alan Shaw --- test/interface.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/interface.spec.js b/test/interface.spec.js index 127fbe4fa..abc57e962 100644 --- a/test/interface.spec.js +++ b/test/interface.spec.js @@ -297,7 +297,7 @@ describe('interface-ipfs-core tests', () => { config = undefined } - const spawnOptions = { repoPath, config, initOptions: { bits: 1024 } } + const spawnOptions = { repoPath, config, initOptions: { bits: 1024, profile: 'test' } } ipfsFactory.spawn(spawnOptions, (err, _ipfsd) => { if (err) { From 5252f506ff405891c6c8619fd046cbde6490e56c Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Wed, 10 Jul 2019 13:52:32 +0100 Subject: [PATCH 072/233] fix: response for findpeer and findprovs (#1039) * fix: response for findpeer and findprovs Pick out the correct item from the response, do not assume the first is the one we want. License: MIT Signed-off-by: Alan Shaw * fix: allow CID instance to be passed License: MIT Signed-off-by: Alan Shaw * docs: add comments for magic Type numbers License: MIT Signed-off-by: Alan Shaw * fix: reinstate not found error License: MIT Signed-off-by: Alan Shaw * fix: module name * fix: add skip for dht.findprovs timeout test Go IPFS does not implement this option and the error that was being checked for was a false positive - it was an error to report no providers were found, which is not an error just a fact and this PR fixes this by removing that error and thus causing this test to now fail. License: MIT Signed-off-by: Alan Shaw --- src/dht/findpeer.js | 13 +++++++------ src/dht/findprovs.js | 19 ++++++------------- test/interface.spec.js | 4 ++++ 3 files changed, 17 insertions(+), 19 deletions(-) diff --git a/src/dht/findpeer.js b/src/dht/findpeer.js index 98611468c..046664bda 100644 --- a/src/dht/findpeer.js +++ b/src/dht/findpeer.js @@ -25,14 +25,15 @@ module.exports = (send) => { const handleResult = (res, callback) => { // Inconsistent return values in the browser if (Array.isArray(res)) { - res = res[0] + res = res.find(r => r.Type === 2) } // Type 2 keys - if (res.Type !== 2) { - const errMsg = `key was not found (type 2)` - - return callback(errcode(new Error(errMsg), 'ERR_KEY_TYPE_2_NOT_FOUND')) + // 2 = FinalPeer + // https://github.com/libp2p/go-libp2p-core/blob/6e566d10f4a5447317a66d64c7459954b969bdab/routing/query.go#L18 + if (!res || res.Type !== 2) { + const errMsg = `key was not found (type 4)` + return callback(errcode(new Error(errMsg), 'ERR_KEY_TYPE_4_NOT_FOUND')) } const responseReceived = res.Responses[0] @@ -49,7 +50,7 @@ module.exports = (send) => { send({ path: 'dht/findpeer', - args: peerId, + args: peerId.toString(), qs: opts }, (err, result) => { if (err) { diff --git a/src/dht/findprovs.js b/src/dht/findprovs.js index 84c1df8f9..23be84068 100644 --- a/src/dht/findprovs.js +++ b/src/dht/findprovs.js @@ -6,7 +6,6 @@ const streamToValueWithTransformer = require('../utils/stream-to-value-with-tran const multiaddr = require('multiaddr') const PeerId = require('peer-id') const PeerInfo = require('peer-info') -const errcode = require('err-code') module.exports = (send) => { return promisify((cid, opts, callback) => { @@ -25,20 +24,14 @@ module.exports = (send) => { const handleResult = (res, callback) => { // Inconsistent return values in the browser vs node if (Array.isArray(res)) { - res = res[0] + res = res.find(r => r.Type === 4) } // callback with an empty array if no providers are found - if (!res) { - const responses = [] - return callback(null, responses) - } - - // Type 4 keys - if (res.Type !== 4) { - const errMsg = `key was not found (type 4)` - - return callback(errcode(new Error(errMsg), 'ERR_KEY_TYPE_4_NOT_FOUND')) + // 4 = Provider + // https://github.com/libp2p/go-libp2p-core/blob/6e566d10f4a5447317a66d64c7459954b969bdab/routing/query.go#L20 + if (!res || res.Type !== 4) { + return callback(null, []) } const responses = res.Responses.map((r) => { @@ -60,7 +53,7 @@ module.exports = (send) => { send({ path: 'dht/findprovs', - args: cid, + args: cid.toString(), qs: opts }, (err, result) => { if (err) { diff --git a/test/interface.spec.js b/test/interface.spec.js index abc57e962..adc928289 100644 --- a/test/interface.spec.js +++ b/test/interface.spec.js @@ -92,6 +92,10 @@ describe('interface-ipfs-core tests', () => { name: 'should provide from one node and find it through another node', reason: 'FIXME go-ipfs endpoint doesn\'t conform with the others https://github.com/ipfs/go-ipfs/issues/5047' }, + { + name: 'should take options to override timeout config', + reason: 'FIXME go-ipfs does not support a timeout option' + }, // dht.get { name: 'should get a value after it was put on another node', From f6ff746827e3dba3d72d50242bf07f3c0eae985d Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Wed, 10 Jul 2019 14:31:16 +0100 Subject: [PATCH 073/233] chore: update contributors --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1ace9bdd5..c417ffed7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ipfs-http-client", - "version": "33.0.0", + "version": "33.0.1", "description": "A client library for the IPFS HTTP API", "keywords": [ "ipfs" From d83d2830ee932cc8a9bbbf9924b04f95a33ed7c1 Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Wed, 10 Jul 2019 14:31:16 +0100 Subject: [PATCH 074/233] chore: release version v33.0.1 --- CHANGELOG.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 38b6715f9..e920d5ef1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,13 @@ + +## [33.0.1](https://github.com/ipfs/js-ipfs-http-client/compare/v33.0.0...v33.0.1) (2019-07-10) + + +### Bug Fixes + +* response for findpeer and findprovs ([#1039](https://github.com/ipfs/js-ipfs-http-client/issues/1039)) ([5252f50](https://github.com/ipfs/js-ipfs-http-client/commit/5252f50)) + + + # [33.0.0](https://github.com/ipfs/js-ipfs-http-client/compare/v32.0.1...v33.0.0) (2019-07-10) From e056ee2793c772829e0ce5eca89399d2c09927c0 Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Wed, 10 Jul 2019 15:39:20 +0100 Subject: [PATCH 075/233] docs: fix ecstatic security vulnerability in name-api example (#1040) Switch to using `extatic` (a maintained fork of `ecstatic`) instead of http-server (which uses `ecstatic`) License: MIT Signed-off-by: Alan Shaw --- examples/name-api/package-lock.json | 364 ++++++++++------------------ examples/name-api/package.json | 4 +- 2 files changed, 135 insertions(+), 233 deletions(-) diff --git a/examples/name-api/package-lock.json b/examples/name-api/package-lock.json index aed871bd3..e30d976fb 100644 --- a/examples/name-api/package-lock.json +++ b/examples/name-api/package-lock.json @@ -15,9 +15,9 @@ } }, "acorn": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.1.0.tgz", - "integrity": "sha512-MW/FjM+IvU9CgBzjO3UIPCE2pyEwUsoFl+VGdczOPEdxfGFjuKny/gN54mOuX7Qxmb9Rg9MCn2oKiSUeW+pjrw==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.2.0.tgz", + "integrity": "sha512-8oe72N3WPMjA+2zVG71Ia0nXZ8DpQH+QyyHO+p06jT8eg8FGG3FbcUIi8KziHlAfheJQZeoqbvq1mQSQHXKYLw==", "dev": true }, "acorn-dynamic-import": { @@ -27,21 +27,21 @@ "dev": true }, "acorn-node": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.6.2.tgz", - "integrity": "sha512-rIhNEZuNI8ibQcL7ANm/mGyPukIaZsRNX9psFNQURyJW0nu6k8wjSDld20z6v2mDBWqX13pIEnk9gGZJHIlEXg==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.7.0.tgz", + "integrity": "sha512-XhahLSsCB6X6CJbe+uNu3Mn9sJBNFxtBN9NLgAOQovfS6Kh0lDUtmlclhjn9CvEK7A7YyRU13PXlNcpSiLI9Yw==", "dev": true, "requires": { - "acorn": "^6.0.2", + "acorn": "^6.1.1", "acorn-dynamic-import": "^4.0.0", - "acorn-walk": "^6.1.0", + "acorn-walk": "^6.1.1", "xtend": "^4.0.1" } }, "acorn-walk": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.1.1.tgz", - "integrity": "sha512-OtUw6JUTgxA2QoqqmrmQ7F2NYqiBPi/L2jqHyFtllhOUvXYQXf0Z1CYUinIfyT4bTCGmrA7gX9FvHA81uzCoVw==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.2.0.tgz", + "integrity": "sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA==", "dev": true }, "array-filter": { @@ -74,11 +74,12 @@ } }, "assert": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/assert/-/assert-1.4.1.tgz", - "integrity": "sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE=", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/assert/-/assert-1.5.0.tgz", + "integrity": "sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA==", "dev": true, "requires": { + "object-assign": "^4.1.1", "util": "0.10.3" }, "dependencies": { @@ -99,12 +100,6 @@ } } }, - "async": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", - "dev": true - }, "balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", @@ -171,9 +166,9 @@ } }, "browserify": { - "version": "16.2.3", - "resolved": "https://registry.npmjs.org/browserify/-/browserify-16.2.3.tgz", - "integrity": "sha512-zQt/Gd1+W+IY+h/xX2NYMW4orQWhqSwyV+xsblycTtpOuB27h1fZhhNQuipJ4t79ohw4P4mMem0jp/ZkISQtjQ==", + "version": "16.3.0", + "resolved": "https://registry.npmjs.org/browserify/-/browserify-16.3.0.tgz", + "integrity": "sha512-BWaaD7alyGZVEBBwSTYx4iJF5DswIGzK17o8ai9w4iKRbYpk3EOiprRHMRRA8DCZFmFeOdx7A385w2XdFvxWmg==", "dev": true, "requires": { "JSONStream": "^1.0.3", @@ -331,6 +326,12 @@ "integrity": "sha512-5r2GqsoEb4qMTTN9J+WzXfjov+hjxT+j3u5K+kIVNIwAd99DLCJE9pBIMP1qVeybV6JiijL385Oz0DcYxfbOIg==", "dev": true }, + "charset": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/charset/-/charset-1.0.1.tgz", + "integrity": "sha512-6dVyOOYjpfFcL1Y4qChrAoQLRHvj2ziyhcm0QJlhOcAhykL/k1kTUPbeo+87MNRTRdk2OIIsIXbuF3x2wi5EXg==", + "dev": true + }, "cipher-base": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", @@ -341,12 +342,6 @@ "safe-buffer": "^5.0.1" } }, - "colors": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", - "integrity": "sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=", - "dev": true - }, "combine-source-map": { "version": "0.8.0", "resolved": "https://registry.npmjs.org/combine-source-map/-/combine-source-map-0.8.0.tgz", @@ -404,12 +399,6 @@ "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", "dev": true }, - "corser": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/corser/-/corser-2.0.1.tgz", - "integrity": "sha1-jtolLsqrWEDc2XXOuQ2TcMgZ/4c=", - "dev": true - }, "create-ecdh": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz", @@ -466,21 +455,18 @@ "randomfill": "^1.0.3" } }, + "dash-ast": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/dash-ast/-/dash-ast-1.0.0.tgz", + "integrity": "sha512-Vy4dx7gquTeMcQR/hDkYLGUnwVil6vk4FOOct+djUnHOUWt+zJPJAaRIXaAFkPXtJjvlY7o3rfRu0/3hpnwoUA==", + "dev": true + }, "date-now": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=", "dev": true }, - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, "defined": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", @@ -546,22 +532,16 @@ "readable-stream": "^2.0.2" } }, - "ecstatic": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/ecstatic/-/ecstatic-3.3.1.tgz", - "integrity": "sha512-/rrctvxZ78HMI/tPIsqdvFKHHscxR3IJuKrZI2ZoUgkt2SiufyLFBmcco+aqQBIu6P1qBsUNG3drAAGLx80vTQ==", - "dev": true, - "requires": { - "he": "^1.1.1", - "mime": "^1.6.0", - "minimist": "^1.1.0", - "url-join": "^2.0.5" - } + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", + "dev": true }, "elliptic": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.1.tgz", - "integrity": "sha512-BsXLz5sqX8OHcsh7CqBMztyXARmGQ3LWPtGjJi6DiJHq5C/qvi9P3OqgswKSDftbu8+IoI/QDTAm2fFnQ9SZSQ==", + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.0.tgz", + "integrity": "sha512-eFOJTMyCYb7xtE/caJ6JJu+bhi67WCYNbkGSknu20pmM8Ke/bqOfdnZWxyoGN26JgfxTbXrsCkEw4KheCT/KGg==", "dev": true, "requires": { "bn.js": "^4.4.0", @@ -573,12 +553,6 @@ "minimalistic-crypto-utils": "^1.0.0" } }, - "eventemitter3": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.0.tgz", - "integrity": "sha512-ivIvhpq/Y0uSjcHDcOIccjmYjGLcP09MFGE7ysAwkAvkXfpZlC985pH2/ui64DKazbTW/4kN3yqozUxlXzI6cA==", - "dev": true - }, "events": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/events/-/events-2.1.0.tgz", @@ -595,13 +569,18 @@ "safe-buffer": "^5.1.1" } }, - "follow-redirects": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.6.1.tgz", - "integrity": "sha512-t2JCjbzxQpWvbhts3l6SH1DKzSrx8a+SsaVf4h6bG4kOXUuPYS/kg2Lr4gQSb7eemaHqJkOThF1BGyjlUkO1GQ==", + "extatic": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/extatic/-/extatic-4.1.3.tgz", + "integrity": "sha512-ZOzJowsUKufkUKDoRe8WTltm+/mUJRLQzWEgr0FgC0+lMv9yrtXU4OnYQSN++AEKK5LXPe2oyird+xrkDvoogA==", "dev": true, "requires": { - "debug": "=3.1.0" + "charset": "^1.0.1", + "he": "^1.1.1", + "mime": "^2.4.1", + "minimist": "^1.1.0", + "on-finished": "^2.3.0", + "url-join": "^4.0.0" } }, "fs.realpath": { @@ -623,9 +602,9 @@ "dev": true }, "glob": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", - "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", + "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", "dev": true, "requires": { "fs.realpath": "^1.0.0", @@ -688,33 +667,6 @@ "integrity": "sha1-OgPtwiFLyjtmQko+eVk0lQnLA1E=", "dev": true }, - "http-proxy": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.17.0.tgz", - "integrity": "sha512-Taqn+3nNvYRfJ3bGvKfBSRwy1v6eePlm3oc/aWVxZp57DQr5Eq3xhKJi7Z4hZpS8PC3H4qI+Yly5EmFacGuA/g==", - "dev": true, - "requires": { - "eventemitter3": "^3.0.0", - "follow-redirects": "^1.0.0", - "requires-port": "^1.0.0" - } - }, - "http-server": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/http-server/-/http-server-0.11.1.tgz", - "integrity": "sha512-6JeGDGoujJLmhjiRGlt8yK8Z9Kl0vnl/dQoQZlc4oeqaUoAKQg94NILLfrY3oWzSyFaQCVNTcKE5PZ3cH8VP9w==", - "dev": true, - "requires": { - "colors": "1.0.3", - "corser": "~2.0.0", - "ecstatic": "^3.0.0", - "http-proxy": "^1.8.1", - "opener": "~1.4.0", - "optimist": "0.6.x", - "portfinder": "^1.0.13", - "union": "~0.4.3" - } - }, "https-browserify": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", @@ -722,9 +674,9 @@ "dev": true }, "ieee754": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.12.tgz", - "integrity": "sha512-GguP+DRY+pJ3soyIiGPTvdiVXjZ+DbXOxGpXn3eMvNW4x4irjqXm4wHKscC+TfxSJ0yw/S1F24tqdMNsMZTiLA==", + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==", "dev": true }, "inflight": { @@ -738,9 +690,9 @@ } }, "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true }, "inline-source-map": { @@ -804,22 +756,13 @@ "dev": true }, "labeled-stream-splicer": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/labeled-stream-splicer/-/labeled-stream-splicer-2.0.1.tgz", - "integrity": "sha512-MC94mHZRvJ3LfykJlTUipBqenZz1pacOZEMhhQ8dMGcDHs0SBE5GbsavUXV7YtP3icBW17W0Zy1I0lfASmo9Pg==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/labeled-stream-splicer/-/labeled-stream-splicer-2.0.2.tgz", + "integrity": "sha512-Ca4LSXFFZUjPScRaqOcFxneA0VpKZr4MMYCljyQr4LIewTLb3Y0IUTIsnBBsVubIeEfxeSZpSjSsRM8APEQaAw==", "dev": true, "requires": { "inherits": "^2.0.1", - "isarray": "^2.0.4", "stream-splicer": "^2.0.0" - }, - "dependencies": { - "isarray": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.4.tgz", - "integrity": "sha512-GMxXOiUirWg1xTKRipM0Ek07rX+ubx4nNVElTJdNLYmNO/2YrDkgJGw9CljXn+r4EWiDQg/8lsRdHyg2PJuUaA==", - "dev": true - } } }, "lodash.memoize": { @@ -850,9 +793,9 @@ } }, "mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.4.tgz", + "integrity": "sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA==", "dev": true }, "minimalistic-assert": { @@ -900,14 +843,14 @@ } }, "module-deps": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/module-deps/-/module-deps-6.2.0.tgz", - "integrity": "sha512-hKPmO06so6bL/ZvqVNVqdTVO8UAYsi3tQWlCa+z9KuWhoN4KDQtb5hcqQQv58qYiDE21wIvnttZEPiDgEbpwbA==", + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/module-deps/-/module-deps-6.2.1.tgz", + "integrity": "sha512-UnEn6Ah36Tu4jFiBbJVUtt0h+iXqxpLqDvPS8nllbw5RZFmNJ1+Mz5BjYnM9ieH80zyxHkARGLnMIHlPK5bu6A==", "dev": true, "requires": { "JSONStream": "^1.0.3", "browser-resolve": "^1.7.0", - "cached-path-relative": "^1.0.0", + "cached-path-relative": "^1.0.2", "concat-stream": "~1.6.0", "defined": "^1.0.0", "detective": "^5.0.2", @@ -922,12 +865,21 @@ "xtend": "^4.0.0" } }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", "dev": true }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "dev": true, + "requires": { + "ee-first": "1.1.1" + } + }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -937,30 +889,6 @@ "wrappy": "1" } }, - "opener": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/opener/-/opener-1.4.3.tgz", - "integrity": "sha1-XG2ixdflgx6P+jlklQ+NZnSskLg=", - "dev": true - }, - "optimist": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", - "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", - "dev": true, - "requires": { - "minimist": "~0.0.1", - "wordwrap": "~0.0.2" - }, - "dependencies": { - "minimist": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", - "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=", - "dev": true - } - } - }, "os-browserify": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", @@ -968,9 +896,9 @@ "dev": true }, "pako": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.8.tgz", - "integrity": "sha512-6i0HVbUfcKaTv+EG8ZTr75az7GFXcLYk9UyLEg7Notv/Ma+z/UG3TCoz6GiNeOrn1E/e63I0X/Hpw18jHOTUnA==", + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.10.tgz", + "integrity": "sha512-0DTvPVU3ed8+HNXOu5Bs+o//Mbdj9VNQMUOe9oKCwh8l0GNwpTDMKCWbRjgtD291AWnkAgkqA/LOnQS8AmS1tw==", "dev": true }, "parents": { @@ -983,9 +911,9 @@ } }, "parse-asn1": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.3.tgz", - "integrity": "sha512-VrPoetlz7B/FqjBLD2f5wBVZvsZVLnRUrxVLfRYhGXCODa/NWE4p3Wp+6+aV3ZPL3KM7/OZmxDIwwijD7yuucg==", + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.4.tgz", + "integrity": "sha512-Qs5duJcuvNExRfFZ99HDD3z4mAi3r9Wl/FOjEOijlxwCZs7E7mW2vjTpgQ4J8LpTF8x5v+1Vn5UQFejmWT11aw==", "dev": true, "requires": { "asn1.js": "^4.0.0", @@ -1033,28 +961,6 @@ "sha.js": "^2.4.8" } }, - "portfinder": { - "version": "1.0.20", - "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.20.tgz", - "integrity": "sha512-Yxe4mTyDzTd59PZJY4ojZR8F+E5e97iq2ZOHPz3HDgSvYC5siNad2tLooQ5y5QHyQhc3xVqvyk/eNA3wuoa7Sw==", - "dev": true, - "requires": { - "async": "^1.5.2", - "debug": "^2.2.0", - "mkdirp": "0.5.x" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - } - } - }, "process": { "version": "0.11.10", "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", @@ -1062,9 +968,9 @@ "dev": true }, "process-nextick-args": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", - "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", "dev": true }, "public-encrypt": { @@ -1087,12 +993,6 @@ "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", "dev": true }, - "qs": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/qs/-/qs-2.3.3.tgz", - "integrity": "sha1-6eha2+ddoLvkyOBHaghikPhjtAQ=", - "dev": true - }, "querystring": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", @@ -1106,9 +1006,9 @@ "dev": true }, "randombytes": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.6.tgz", - "integrity": "sha512-CIQ5OFxf4Jou6uOKe9t1AOgqpeU5fd70A8NPdHSGeYXqXsPe6peOwI0cUl88RWZ6sP1vPMV3avd/R6cZ5/sP1A==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", "dev": true, "requires": { "safe-buffer": "^5.1.0" @@ -1148,6 +1048,12 @@ "util-deprecate": "~1.0.1" }, "dependencies": { + "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==", + "dev": true + }, "string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", @@ -1159,16 +1065,10 @@ } } }, - "requires-port": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", - "dev": true - }, "resolve": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.10.0.tgz", - "integrity": "sha512-3sUr9aq5OfSg2S9pNtPA9hL1FVEAjvfOC4leW0SNf/mpnaakz2a9femSd6LqAww2RaFctwyf1lCqnTHuF1rxDg==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.11.1.tgz", + "integrity": "sha512-vIpgF6wfuJOZI7KKKSP+HmiKggadPQAdsp5HiC1mvqnfp0gF1vdwgBWZIdrVft9pgqoMFQN+R7BSWZiBxx+BBw==", "dev": true, "requires": { "path-parse": "^1.0.6" @@ -1185,9 +1085,9 @@ } }, "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==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz", + "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==", "dev": true }, "sha.js": { @@ -1268,9 +1168,9 @@ } }, "stream-splicer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/stream-splicer/-/stream-splicer-2.0.0.tgz", - "integrity": "sha1-G2O+Q4oTPktnHMGTUZdgAXWRDYM=", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/stream-splicer/-/stream-splicer-2.0.1.tgz", + "integrity": "sha512-Xizh4/NPuYSyAXyT7g8IvdJ9HJpxIGL9PjyhtywCZvvP0OPIdqyrr4dMikeuvY8xahpdKEBlBTySe583totajg==", "dev": true, "requires": { "inherits": "^2.0.1", @@ -1284,6 +1184,14 @@ "dev": true, "requires": { "safe-buffer": "~5.1.0" + }, + "dependencies": { + "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==", + "dev": true + } } }, "subarg": { @@ -1354,26 +1262,18 @@ "dev": true }, "undeclared-identifiers": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/undeclared-identifiers/-/undeclared-identifiers-1.1.2.tgz", - "integrity": "sha512-13EaeocO4edF/3JKime9rD7oB6QI8llAGhgn5fKOPyfkJbRb6NFv9pYV6dFEmpa4uRjKeBqLZP8GpuzqHlKDMQ==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/undeclared-identifiers/-/undeclared-identifiers-1.1.3.tgz", + "integrity": "sha512-pJOW4nxjlmfwKApE4zvxLScM/njmwj/DiUBv7EabwE4O8kRUy+HIwxQtZLBPll/jx1LJyBcqNfB3/cpv9EZwOw==", "dev": true, "requires": { "acorn-node": "^1.3.0", + "dash-ast": "^1.0.0", "get-assigned-identifiers": "^1.2.0", "simple-concat": "^1.0.0", "xtend": "^4.0.1" } }, - "union": { - "version": "0.4.6", - "resolved": "https://registry.npmjs.org/union/-/union-0.4.6.tgz", - "integrity": "sha1-GY+9rrolTniLDvy2MLwR8kopWeA=", - "dev": true, - "requires": { - "qs": "~2.3.3" - } - }, "url": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", @@ -1393,9 +1293,9 @@ } }, "url-join": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/url-join/-/url-join-2.0.5.tgz", - "integrity": "sha1-WvIvGMBSoACkjXuCxenC4v7tpyg=", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz", + "integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==", "dev": true }, "util": { @@ -1405,6 +1305,14 @@ "dev": true, "requires": { "inherits": "2.0.3" + }, + "dependencies": { + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + } } }, "util-deprecate": { @@ -1419,12 +1327,6 @@ "integrity": "sha512-iq+S7vZJE60yejDYM0ek6zg308+UZsdtPExWP9VZoCFCz1zkJoXFnAX7aZfd/ZwrkidzdUZL0C/ryW+JwAiIGw==", "dev": true }, - "wordwrap": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", - "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", - "dev": true - }, "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", @@ -1432,9 +1334,9 @@ "dev": true }, "xtend": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", - "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", "dev": true } } diff --git a/examples/name-api/package.json b/examples/name-api/package.json index daab7ee99..143e733d2 100644 --- a/examples/name-api/package.json +++ b/examples/name-api/package.json @@ -4,12 +4,12 @@ "description": "", "main": "index.js", "scripts": { - "start": "browserify index.js > bundle.js && http-server -a 127.0.0.1 -p 8888" + "start": "browserify index.js > bundle.js && extatic --host 127.0.0.1 -p 8888" }, "author": "Tara Vancil ", "license": "MIT", "devDependencies": { "browserify": "^16.2.3", - "http-server": "~0.11.1" + "extatic": "^4.1.3" } } From 25e5209e913a9fcb3f0f0e4a68f27fe8ebe4653e Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Thu, 11 Jul 2019 10:25:11 +0100 Subject: [PATCH 076/233] chore: bump bundle size restriction temporarily MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This will come down again when we switch to the new version of Peer ID with async/await (since it will use the same `multihashing-async` as the included IPLD formats): ```js ipfs-http-client@33.0.1 /Users/alan/Code/protocol-labs/js-ipfs-http-client ├─┬ ipld-dag-cbor@0.15.0 │ └── multihashing-async@0.7.0 ├─┬ ipld-dag-pb@0.17.4 │ └── multihashing-async@0.7.0 deduped └─┬ peer-id@0.12.2 └─┬ libp2p-crypto@0.16.1 ├─┬ libp2p-crypto-secp256k1@0.3.1 │ └── multihashing-async@0.6.0 └── multihashing-async@0.5.2 ``` --- .aegir.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.aegir.js b/.aegir.js index 1deee7d74..65a309618 100644 --- a/.aegir.js +++ b/.aegir.js @@ -5,7 +5,7 @@ const createServer = require('ipfsd-ctl').createServer const server = createServer() module.exports = { - bundlesize: { maxSize: '236kB' }, + bundlesize: { maxSize: '237kB' }, webpack: { resolve: { mainFields: ['browser', 'main'] From 63103bd7c34c9bcf89ccb243e96af03dda503b29 Mon Sep 17 00:00:00 2001 From: Jacob Heun Date: Thu, 11 Jul 2019 10:27:07 +0100 Subject: [PATCH 077/233] fix: make findprovs return all responses (#1041) * fix: make findprovs return all responses * test: add test for many providers from interface-ipfs-core * chore: update interface-ipfs-core dep --- package.json | 2 +- src/dht/findprovs.js | 39 ++++++++++++++++++--------------------- test/interface.spec.js | 4 ---- 3 files changed, 19 insertions(+), 26 deletions(-) diff --git a/package.json b/package.json index c417ffed7..c4ba1493e 100644 --- a/package.json +++ b/package.json @@ -85,7 +85,7 @@ "cross-env": "^5.2.0", "dirty-chai": "^2.0.1", "go-ipfs-dep": "~0.4.21", - "interface-ipfs-core": "~0.106.0", + "interface-ipfs-core": "~0.107.0", "ipfsd-ctl": "~0.43.0", "nock": "^10.0.2", "stream-equal": "^1.1.1" diff --git a/src/dht/findprovs.js b/src/dht/findprovs.js index 23be84068..41ef4aaeb 100644 --- a/src/dht/findprovs.js +++ b/src/dht/findprovs.js @@ -23,29 +23,26 @@ module.exports = (send) => { const handleResult = (res, callback) => { // Inconsistent return values in the browser vs node - if (Array.isArray(res)) { - res = res.find(r => r.Type === 4) + if (!Array.isArray(res)) { + res = [res] } - // callback with an empty array if no providers are found - // 4 = Provider - // https://github.com/libp2p/go-libp2p-core/blob/6e566d10f4a5447317a66d64c7459954b969bdab/routing/query.go#L20 - if (!res || res.Type !== 4) { - return callback(null, []) - } - - const responses = res.Responses.map((r) => { - const peerInfo = new PeerInfo(PeerId.createFromB58String(r.ID)) - - if (r.Addrs) { - r.Addrs.forEach((addr) => { - const ma = multiaddr(addr) - - peerInfo.multiaddrs.add(ma) - }) - } - - return peerInfo + let responses = [] + res.forEach(result => { + // 4 = Provider + if (result.Type !== 4) return + result.Responses.forEach(response => { + const peerInfo = new PeerInfo(PeerId.createFromB58String(response.ID)) + + if (response.Addrs) { + response.Addrs.forEach((addr) => { + const ma = multiaddr(addr) + peerInfo.multiaddrs.add(ma) + }) + } + + responses.push(peerInfo) + }) }) callback(null, responses) diff --git a/test/interface.spec.js b/test/interface.spec.js index adc928289..1c7ed2b7d 100644 --- a/test/interface.spec.js +++ b/test/interface.spec.js @@ -88,10 +88,6 @@ describe('interface-ipfs-core tests', () => { reason: 'FIXME checking what is exactly go-ipfs returning https://github.com/ipfs/go-ipfs/issues/3862#issuecomment-294168090' }, // dht.findprovs - { - name: 'should provide from one node and find it through another node', - reason: 'FIXME go-ipfs endpoint doesn\'t conform with the others https://github.com/ipfs/go-ipfs/issues/5047' - }, { name: 'should take options to override timeout config', reason: 'FIXME go-ipfs does not support a timeout option' From 351c011b8dbf672f84098c7843f539d2311f376f Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Thu, 11 Jul 2019 11:53:19 +0100 Subject: [PATCH 078/233] chore: update contributors --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c4ba1493e..96f647d95 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ipfs-http-client", - "version": "33.0.1", + "version": "33.0.2", "description": "A client library for the IPFS HTTP API", "keywords": [ "ipfs" From a30f69269ba4c6b8794136b6f4019a069e1cc753 Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Thu, 11 Jul 2019 11:53:20 +0100 Subject: [PATCH 079/233] chore: release version v33.0.2 --- CHANGELOG.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e920d5ef1..b00d86333 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,13 @@ + +## [33.0.2](https://github.com/ipfs/js-ipfs-http-client/compare/v33.0.1...v33.0.2) (2019-07-11) + + +### Bug Fixes + +* make findprovs return all responses ([#1041](https://github.com/ipfs/js-ipfs-http-client/issues/1041)) ([63103bd](https://github.com/ipfs/js-ipfs-http-client/commit/63103bd)) + + + ## [33.0.1](https://github.com/ipfs/js-ipfs-http-client/compare/v33.0.0...v33.0.1) (2019-07-10) From cd41a1687b145403de3a63e6e229a13d245c1824 Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Thu, 11 Jul 2019 13:11:50 +0100 Subject: [PATCH 080/233] fix: changelog for 33.x does not include breaking change --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b00d86333..043fe2c7b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,6 +29,10 @@ * sometimes no Addrs element is present in the response ([#1037](https://github.com/ipfs/js-ipfs-http-client/issues/1037)) ([a74b8f7](https://github.com/ipfs/js-ipfs-http-client/commit/a74b8f7)) * **package:** update bignumber.js to version 9.0.0 ([#1024](https://github.com/ipfs/js-ipfs-http-client/issues/1024)) ([a04edac](https://github.com/ipfs/js-ipfs-http-client/commit/a04edac)) +### BREAKING CHANGES + +`repo.gc` response objects have changed to `{ err, cid }`, where `err` is an `Error` instance and `cid` is a [`CID`](https://github.com/multiformats/js-cid) instance. + From 8f378a36a89d2094714c2d32419a78fd0b14b857 Mon Sep 17 00:00:00 2001 From: Alex Potsides Date: Thu, 11 Jul 2019 13:12:58 +0100 Subject: [PATCH 081/233] feat: add support for js-ipfs dag api and also some tests (#957) * feat: add support for js-ipfs dag api and also some tests * test: move tests to interface suite * chore: update interface-ipfs-core dep License: MIT Signed-off-by: Alan Shaw * chore: update interface-ipfs-core License: MIT Signed-off-by: Alan Shaw --- package.json | 3 ++- src/dag/get.js | 7 +++++-- test/dag.spec.js | 13 ++++++------- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/package.json b/package.json index 96f647d95..8e9142c11 100644 --- a/package.json +++ b/package.json @@ -50,6 +50,7 @@ "ipfs-utils": "~0.0.3", "ipld-dag-cbor": "~0.15.0", "ipld-dag-pb": "~0.17.3", + "ipld-raw": "^4.0.0", "is-ipfs": "~0.6.1", "is-pull-stream": "0.0.0", "is-stream": "^2.0.0", @@ -85,7 +86,7 @@ "cross-env": "^5.2.0", "dirty-chai": "^2.0.1", "go-ipfs-dep": "~0.4.21", - "interface-ipfs-core": "~0.107.0", + "interface-ipfs-core": "^0.107.1", "ipfsd-ctl": "~0.43.0", "nock": "^10.0.2", "stream-equal": "^1.1.1" diff --git a/src/dag/get.js b/src/dag/get.js index c46ada33c..d0a1dac13 100644 --- a/src/dag/get.js +++ b/src/dag/get.js @@ -2,6 +2,7 @@ const dagPB = require('ipld-dag-pb') const dagCBOR = require('ipld-dag-cbor') +const raw = require('ipld-raw') const promisify = require('promisify-es6') const CID = require('cids') const waterfall = require('async/waterfall') @@ -9,7 +10,8 @@ const block = require('../block') const resolvers = { 'dag-cbor': dagCBOR.resolver, - 'dag-pb': dagPB.resolver + 'dag-pb': dagPB.resolver, + raw: raw.resolver } module.exports = (send) => { @@ -48,7 +50,7 @@ module.exports = (send) => { const dagResolver = resolvers[ipfsBlock.cid.codec] if (!dagResolver) { - const error = new Error('ipfs-http-client is missing DAG resolver for "' + ipfsBlock.cid.codec + '" multicodec') + const error = new Error(`Missing IPLD format "${ipfsBlock.cid.codec}"`) error.missingMulticodec = ipfsBlock.cid.codec return cb(error) } @@ -59,6 +61,7 @@ module.exports = (send) => { } catch (err) { return cb(err) } + cb(null, res) } ], callback) diff --git a/test/dag.spec.js b/test/dag.spec.js index 1b0cfc683..eb69a959c 100644 --- a/test/dag.spec.js +++ b/test/dag.spec.js @@ -68,16 +68,15 @@ describe('.dag', function () { }) }) - it('should callback with error when missing DAG resolver for raw multicodec', (done) => { - ipfs.dag.put(Buffer.from([0, 1, 2, 3]), { - // CIDv1 with multicodec = raw - cid: new CID('bafkreigh2akiscaildcqabsyg3dfr6chu3fgpregiymsck7e7aqa4s52zy') - }, (err, cid) => { + it('should callback with error when missing DAG resolver for multicodec from requested CID', (done) => { + ipfs.block.put(Buffer.from([0, 1, 2, 3]), { + cid: new CID('z8mWaJ1dZ9fH5EetPuRsj8jj26pXsgpsr') + }, (err, block) => { expect(err).to.not.exist() - ipfs.dag.get(cid, (err, result) => { + ipfs.dag.get(block.cid, (err, result) => { expect(result).to.not.exist() - expect(err.message).to.equal('ipfs-http-client is missing DAG resolver for "raw" multicodec') + expect(err.message).to.equal('Missing IPLD format "git-raw"') done() }) }) From 9e6dfe754a95c954eb8ca015b3fd784593e98089 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20Mur=C3=A9?= Date: Thu, 11 Jul 2019 14:43:08 +0200 Subject: [PATCH 082/233] fix: invalid multipart/form-data (#948) According to https://tools.ietf.org/html/rfc7578#section-4.2, in a Content-Disposition header of a part in a multipart/form-data body: - the disposition must be of type `form-data` - a `name` parameter (not explicitely specified by the RFC, but I suppose non-empty) As this `name` parameter is unused by IPFS, this commit simply generate a placeholder with a counter, to conform to the HTTP specification. --- src/utils/send-files-stream.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/utils/send-files-stream.js b/src/utils/send-files-stream.js index 4c91798fc..fa2b51b4c 100644 --- a/src/utils/send-files-stream.js +++ b/src/utils/send-files-stream.js @@ -7,12 +7,12 @@ const once = require('once') const prepareFile = require('./prepare-file') const Multipart = require('./multipart') -function headers (file) { - const name = file.path +function headers (file, i) { + const filename = file.path ? encodeURIComponent(file.path) : '' - const header = { 'Content-Disposition': `file; filename="${name}"` } + const header = { 'Content-Disposition': `form-data; name="data${i}"; filename="${filename}"` } if (!file.content) { header['Content-Type'] = 'application/x-directory' @@ -43,7 +43,7 @@ module.exports = (send, path) => { const next = once(_next) try { const files = prepareFile(file, options) - .map((file) => Object.assign({ headers: headers(file) }, file)) + .map((file, i) => Object.assign({ headers: headers(file, i) }, file)) writing = true eachSeries( From 65cc606b6d611d13322415b9cf5d9798a4ea9f08 Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Thu, 11 Jul 2019 14:03:42 +0100 Subject: [PATCH 083/233] chore: update contributors --- package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 8e9142c11..673b5e58d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ipfs-http-client", - "version": "33.0.2", + "version": "33.1.0", "description": "A client library for the IPFS HTTP API", "keywords": [ "ipfs" @@ -144,6 +144,7 @@ "Matt Bell ", "Maxime Lathuilière ", "Michael Bradley ", + "Michael Muré ", "Michael Muré ", "Mikeal Rogers ", "Mitar ", From 6d3480acc3c0052c9da27a3318578d8a76008e84 Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Thu, 11 Jul 2019 14:03:43 +0100 Subject: [PATCH 084/233] chore: release version v33.1.0 --- CHANGELOG.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 043fe2c7b..c9f689264 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,19 @@ + +# [33.1.0](https://github.com/ipfs/js-ipfs-http-client/compare/v33.0.2...v33.1.0) (2019-07-11) + + +### Bug Fixes + +* changelog for 33.x does not include breaking change ([cd41a16](https://github.com/ipfs/js-ipfs-http-client/commit/cd41a16)) +* invalid multipart/form-data ([#948](https://github.com/ipfs/js-ipfs-http-client/issues/948)) ([9e6dfe7](https://github.com/ipfs/js-ipfs-http-client/commit/9e6dfe7)), closes [/tools.ietf.org/html/rfc7578#section-4](https://github.com//tools.ietf.org/html/rfc7578/issues/section-4) + + +### Features + +* add support for js-ipfs dag api and also some tests ([#957](https://github.com/ipfs/js-ipfs-http-client/issues/957)) ([8f378a3](https://github.com/ipfs/js-ipfs-http-client/commit/8f378a3)) + + + ## [33.0.2](https://github.com/ipfs/js-ipfs-http-client/compare/v33.0.1...v33.0.2) (2019-07-11) From 758d451b3426e9ac6d80576a676cb816e666eac8 Mon Sep 17 00:00:00 2001 From: Teri Chadbourne Date: Tue, 16 Jul 2019 11:49:03 -0400 Subject: [PATCH 085/233] docs: link to ProtoSchool tutorials (#1047) Link to relevant MFS and DAG API tutorials on ProtoSchool, as part of the Q3 IPFS Docs task force efforts. See issue https://github.com/ProtoSchool/protoschool.github.io/issues/260 --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 23e800092..c93113485 100644 --- a/README.md +++ b/README.md @@ -203,6 +203,8 @@ const ipfs = ipfsClient({ - [`ipfs.lsPullStream(ipfsPath)`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#lspullstream) - [`ipfs.lsReadableStream(ipfsPath)`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#lsreadablestream) - [MFS (mutable file system) specific](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#mutable-file-system) + + _Explore the Mutable File System through interactive coding challenges in our [ProtoSchool tutorial](https://proto.school/#/mutable-file-system/)._ - [`ipfs.files.cp([from, to], [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#filescp) - [`ipfs.files.flush([path], [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#filesflush) - [`ipfs.files.ls([path], [options], [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#filesls) @@ -231,6 +233,8 @@ const ipfs = ipfsClient({ #### Graph - [dag](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/DAG.md) + + _Explore the DAG API through interactive coding challenges in our [ProtoSchool tutorial](https://proto.school/#/basics)._ - [`ipfs.dag.get(cid, [path], [options], [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/DAG.md#dagget) - [`ipfs.dag.put(dagNode, [options], [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/DAG.md#dagput) - [`ipfs.dag.tree(cid, [path], [options], [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/DAG.md#dagtree) From 42626d8e6101f6b3e0abf02675fb5352327ef1ae Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Fri, 26 Jul 2019 14:30:55 +0100 Subject: [PATCH 086/233] docs: how to add an interface core test (#1058) --- CONTRIBUTING.md | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 33fe54e07..ba4ef9f8f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -26,6 +26,32 @@ Tests in the browser $ npm run test:browser ``` +### Writing a new core interface test + +The core interface tests are kept in a separate repo, because they are used by multiple other projects. To add a core interface test, follow this guide: + +1. Clone this project repo and the interface core tests repo: + * `git clone https://github.com/ipfs/js-ipfs-http-client.git` + * `git clone https://github.com/ipfs/interface-js-ipfs-core.git` +1. Install dependencies and globally [link](https://docs.npmjs.com/cli/link) the interface core tests: + * `cd interface-js-ipfs-core` + * `npm install` + * `npm link` +1. Write your test +1. Install dependencies for this project and link to the interface core tests + * `cd ../js-ipfs-http-client` + * `npm install` + * `npm link interface-ipfs-core` +1. Run the tests: + * `npm test` + +Next: + +1. Send a PR to `ipfs/interface-js-ipfs-core` (please also add to the documentation!) +1. This will be reviewed by a core contributor and they will perform the same steps as above +1. When merged, a new version of `interface-ipfs-core` will be released +1. Finally, a PR needs to be created or updated to `ipfs/js-ipfs-http-client` to use the new version + ## Building browser version ```bash From 92b05945a4a97d13c8cddeb3b9d168cdf5275bc4 Mon Sep 17 00:00:00 2001 From: Matt Ober Date: Fri, 26 Jul 2019 11:34:34 -0500 Subject: [PATCH 087/233] fix: allow passing timeout option to object stat (#1055) The ipfs object stat command couldn't handle the {timeout: '1s'} option (or any other options). We're already checking for the opts parameter so it makes sense that we should be sending it as well. Things work as desired now with this one line addition. --- package.json | 2 +- src/object/stat.js | 3 ++- test/interface.spec.js | 14 +++++++++++++- 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 673b5e58d..5668a65ed 100644 --- a/package.json +++ b/package.json @@ -86,7 +86,7 @@ "cross-env": "^5.2.0", "dirty-chai": "^2.0.1", "go-ipfs-dep": "~0.4.21", - "interface-ipfs-core": "^0.107.1", + "interface-ipfs-core": "^0.109.0", "ipfsd-ctl": "~0.43.0", "nock": "^10.0.2", "stream-equal": "^1.1.1" diff --git a/src/object/stat.js b/src/object/stat.js index 280e9f8e1..6488a297e 100644 --- a/src/object/stat.js +++ b/src/object/stat.js @@ -21,7 +21,8 @@ module.exports = (send) => { send({ path: 'object/stat', - args: cid.toString() + args: cid.toString(), + qs: opts }, callback) }) } diff --git a/test/interface.spec.js b/test/interface.spec.js index 1c7ed2b7d..962a076b4 100644 --- a/test/interface.spec.js +++ b/test/interface.spec.js @@ -49,6 +49,11 @@ describe('interface-ipfs-core tests', () => { { name: 'replace', reason: 'FIXME Waiting for fix on go-ipfs https://github.com/ipfs/js-ipfs-http-client/pull/307#discussion_r69281789 and https://github.com/ipfs/go-ipfs/issues/2927' + }, + // config.profile + { + name: 'profile', + reason: 'TODO not yet implemented https://github.com/ipfs/js-ipfs-http-client/pull/1030' } ] }) @@ -182,7 +187,14 @@ describe('interface-ipfs-core tests', () => { ] }) - tests.filesMFS(defaultCommonFactory) + tests.filesMFS(defaultCommonFactory, { + skip: [ + { + name: 'should ls directory with long option', + reason: 'TODO unskip when go-ipfs supports --long https://github.com/ipfs/go-ipfs/pull/6528' + } + ] + }) tests.key(defaultCommonFactory, { skip: [ From 1bede3f8521d8af4d1e52667d1e615bf7a290d82 Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Fri, 26 Jul 2019 19:46:49 +0100 Subject: [PATCH 088/233] chore: update contributors --- package.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 5668a65ed..ece2c88e9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ipfs-http-client", - "version": "33.1.0", + "version": "33.1.1", "description": "A client library for the IPFS HTTP API", "keywords": [ "ipfs" @@ -142,6 +142,7 @@ "Kristoffer Ström ", "Marcin Rataj ", "Matt Bell ", + "Matt Ober ", "Maxime Lathuilière ", "Michael Bradley ", "Michael Muré ", @@ -163,6 +164,7 @@ "SeungWon ", "Stephen Whitmore ", "Tara Vancil ", + "Teri Chadbourne ", "Travis Person ", "Travis Person ", "Vasco Santos ", From b65bba35368280a90aa5f7cab9c3a2ea256c50cd Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Fri, 26 Jul 2019 19:46:50 +0100 Subject: [PATCH 089/233] chore: release version v33.1.1 --- CHANGELOG.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c9f689264..3ad9df13d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,13 @@ + +## [33.1.1](https://github.com/ipfs/js-ipfs-http-client/compare/v33.1.0...v33.1.1) (2019-07-26) + + +### Bug Fixes + +* allow passing timeout option to object stat ([#1055](https://github.com/ipfs/js-ipfs-http-client/issues/1055)) ([92b0594](https://github.com/ipfs/js-ipfs-http-client/commit/92b0594)) + + + # [33.1.0](https://github.com/ipfs/js-ipfs-http-client/compare/v33.0.2...v33.1.0) (2019-07-11) From 339c4a729e4ea67ab692ccbd4ce53f6382a3cf82 Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Sat, 27 Jul 2019 07:45:38 +0100 Subject: [PATCH 090/233] chore: unskip dag refs test (#1061) License: MIT Signed-off-by: Alan Shaw --- test/interface.spec.js | 5 ----- 1 file changed, 5 deletions(-) diff --git a/test/interface.spec.js b/test/interface.spec.js index 962a076b4..220c79aa2 100644 --- a/test/interface.spec.js +++ b/test/interface.spec.js @@ -178,11 +178,6 @@ describe('interface-ipfs-core tests', () => { isNode ? null : { name: 'should readable stream ls with a base58 encoded CID', reason: 'FIXME https://github.com/ipfs/js-ipfs-http-client/issues/339' - }, - // .refs - { - name: 'dag refs test', - reason: 'FIXME unskip when 0.4.21 is released' } ] }) From 719bfad4d0cef994960f80c0b481ffb1d1ad1fab Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Tue, 30 Jul 2019 20:26:56 +0100 Subject: [PATCH 091/233] chore(package): update peer-id to version 0.12.3 (#1065) --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ece2c88e9..ba8121d2b 100644 --- a/package.json +++ b/package.json @@ -66,7 +66,7 @@ "multihashes": "~0.4.14", "ndjson": "github:hugomrdias/ndjson#feat/readable-stream3", "once": "^1.4.0", - "peer-id": "~0.12.2", + "peer-id": "~0.12.3", "peer-info": "~0.15.1", "promisify-es6": "^1.0.3", "pull-defer": "~0.2.3", From e3ed6e92a7fd85e3c3108ebb212fee8b850d84bd Mon Sep 17 00:00:00 2001 From: Alex Potsides Date: Fri, 23 Aug 2019 15:19:11 +0100 Subject: [PATCH 092/233] feat: expose pin and preload arguments (#1079) --- src/utils/send-files-stream.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/utils/send-files-stream.js b/src/utils/send-files-stream.js index fa2b51b4c..232dd34da 100644 --- a/src/utils/send-files-stream.js +++ b/src/utils/send-files-stream.js @@ -79,6 +79,8 @@ module.exports = (send, path) => { qs['raw-leaves'] = propOrProp(options, 'raw-leaves', 'rawLeaves') qs['only-hash'] = propOrProp(options, 'only-hash', 'onlyHash') qs['wrap-with-directory'] = propOrProp(options, 'wrap-with-directory', 'wrapWithDirectory') + qs['pin'] = propOrProp(options, 'pin') + qs['preload'] = propOrProp(options, 'preload') qs.hash = propOrProp(options, 'hash', 'hashAlg') if (options.strategy === 'trickle' || options.trickle) { From f52389ddf73b423bbd22079d8206f955e8c28bf6 Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" <23040076+greenkeeper[bot]@users.noreply.github.com> Date: Wed, 28 Aug 2019 09:26:11 +0100 Subject: [PATCH 093/233] chore(package): update aegir to version 20.0.0 (#1046) License: MIT Signed-off-by: Alan Shaw --- package.json | 4 ++-- src/dag/get.js | 4 ++-- src/dag/put.js | 4 ++-- src/dht/findprovs.js | 2 +- src/dht/get.js | 3 +-- src/utils/multipart.js | 2 +- src/utils/prepare-file.js | 2 +- src/utils/pubsub-message-stream.js | 2 +- src/utils/send-files-stream.js | 5 ++--- src/utils/tar-stream-to-objects.js | 4 ++-- test/files-mfs.spec.js | 6 +++--- test/log.spec.js | 2 +- 12 files changed, 19 insertions(+), 21 deletions(-) diff --git a/package.json b/package.json index ba8121d2b..33cd7bde1 100644 --- a/package.json +++ b/package.json @@ -80,12 +80,12 @@ "through2": "^3.0.1" }, "devDependencies": { - "aegir": "^19.0.3", + "aegir": "^20.0.0", "browser-process-platform": "~0.1.1", "chai": "^4.2.0", "cross-env": "^5.2.0", "dirty-chai": "^2.0.1", - "go-ipfs-dep": "~0.4.21", + "go-ipfs-dep": "0.4.21", "interface-ipfs-core": "^0.109.0", "ipfsd-ctl": "~0.43.0", "nock": "^10.0.2", diff --git a/src/dag/get.js b/src/dag/get.js index d0a1dac13..771c38bf4 100644 --- a/src/dag/get.js +++ b/src/dag/get.js @@ -42,8 +42,8 @@ module.exports = (send) => { }, cb) }, (resolved, cb) => { - block(send).get(new CID(resolved['Cid']['/']), (err, ipfsBlock) => { - cb(err, ipfsBlock, resolved['RemPath']) + block(send).get(new CID(resolved.Cid['/']), (err, ipfsBlock) => { + cb(err, ipfsBlock, resolved.RemPath) }) }, (ipfsBlock, path, cb) => { diff --git a/src/dag/put.js b/src/dag/put.js index 42d92b285..6cfca99c0 100644 --- a/src/dag/put.js +++ b/src/dag/put.js @@ -77,8 +77,8 @@ module.exports = (send) => { if (err) { return callback(err) } - if (result['Cid']) { - return callback(null, new CID(result['Cid']['/'])) + if (result.Cid) { + return callback(null, new CID(result.Cid['/'])) } else { return callback(result) } diff --git a/src/dht/findprovs.js b/src/dht/findprovs.js index 41ef4aaeb..695ef04df 100644 --- a/src/dht/findprovs.js +++ b/src/dht/findprovs.js @@ -27,7 +27,7 @@ module.exports = (send) => { res = [res] } - let responses = [] + const responses = [] res.forEach(result => { // 4 = Provider if (result.Type !== 4) return diff --git a/src/dht/get.js b/src/dht/get.js index 279ad51bf..ab64fa892 100644 --- a/src/dht/get.js +++ b/src/dht/get.js @@ -35,8 +35,7 @@ module.exports = (send) => { if (res.Type === 5) { done(null, res.Extra) } else { - let error = new Error('key was not found (type 6)') - done(error) + done(new Error('key was not found (type 6)')) } } diff --git a/src/utils/multipart.js b/src/utils/multipart.js index a6df61fd4..78bead247 100644 --- a/src/utils/multipart.js +++ b/src/utils/multipart.js @@ -67,7 +67,7 @@ class Multipart extends Transform { this.push(leading) - let content = file.content || Buffer.alloc(0) + const content = file.content || Buffer.alloc(0) if (Buffer.isBuffer(content)) { this.push(content) diff --git a/src/utils/prepare-file.js b/src/utils/prepare-file.js index 1ffe3f31c..9a02f8338 100644 --- a/src/utils/prepare-file.js +++ b/src/utils/prepare-file.js @@ -106,7 +106,7 @@ function contentToStream (content) { } function prepareFile (file, opts) { - let files = [].concat(file) + const files = [].concat(file) return flatmap(files, (file) => { // add from fs with file path diff --git a/src/utils/pubsub-message-stream.js b/src/utils/pubsub-message-stream.js index 992529213..d5925f714 100644 --- a/src/utils/pubsub-message-stream.js +++ b/src/utils/pubsub-message-stream.js @@ -10,7 +10,7 @@ class PubsubMessageStream extends TransformStream { } static from (inputStream, callback) { - let outputStream = inputStream.pipe(new PubsubMessageStream()) + const outputStream = inputStream.pipe(new PubsubMessageStream()) inputStream.on('end', () => outputStream.emit('end')) callback(null, outputStream) } diff --git a/src/utils/send-files-stream.js b/src/utils/send-files-stream.js index 232dd34da..91bd90fb4 100644 --- a/src/utils/send-files-stream.js +++ b/src/utils/send-files-stream.js @@ -27,7 +27,6 @@ function headers (file, i) { module.exports = (send, path) => { return (options) => { - let request let ended = false let writing = false @@ -84,7 +83,7 @@ module.exports = (send, path) => { qs.hash = propOrProp(options, 'hash', 'hashAlg') if (options.strategy === 'trickle' || options.trickle) { - qs['trickle'] = 'true' + qs.trickle = 'true' } const args = { @@ -102,7 +101,7 @@ module.exports = (send, path) => { retStream.emit('error', err) }) - request = send(args, (err, response) => { + const request = send(args, (err, response) => { if (err) { return retStream.emit('error', err) } diff --git a/src/utils/tar-stream-to-objects.js b/src/utils/tar-stream-to-objects.js index 6d7765a03..724544583 100644 --- a/src/utils/tar-stream-to-objects.js +++ b/src/utils/tar-stream-to-objects.js @@ -20,8 +20,8 @@ class ObjectsStreams extends ReadableStream { { path: 'string', content: Stream } */ const TarStreamToObjects = (inputStream, callback) => { - let outputStream = new ObjectsStreams() - let extractStream = tar.extract() + const outputStream = new ObjectsStreams() + const extractStream = tar.extract() extractStream .on('entry', (header, stream, next) => { diff --git a/test/files-mfs.spec.js b/test/files-mfs.spec.js index f9b46cdd7..beda9b24a 100644 --- a/test/files-mfs.spec.js +++ b/test/files-mfs.spec.js @@ -65,10 +65,10 @@ describe('.files (the MFS API part)', function () { }) it('.add with Buffer module', (done) => { - let Buffer = require('buffer').Buffer + const { Buffer } = require('buffer') - let expectedBufferMultihash = 'QmWfVY9y3xjsixTgbd9AorQxH7VtMpzfx2HaWtsoUYecaX' - let file = Buffer.from('hello') + const expectedBufferMultihash = 'QmWfVY9y3xjsixTgbd9AorQxH7VtMpzfx2HaWtsoUYecaX' + const file = Buffer.from('hello') ipfs.add(file, (err, res) => { expect(err).to.not.exist() diff --git a/test/log.spec.js b/test/log.spec.js index 16782d66a..1e800f075 100644 --- a/test/log.spec.js +++ b/test/log.spec.js @@ -31,7 +31,7 @@ describe('.log', function () { }) it('.log.tail', (done) => { - let i = setInterval(() => { + const i = setInterval(() => { ipfs.add(Buffer.from('just adding some data to generate logs')) }, 1000) From 07e684119417abc1040077c0a7b1e5c606222805 Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Wed, 28 Aug 2019 10:35:42 +0100 Subject: [PATCH 094/233] chore: silence greenkeeper in examples (#1077) Too much greenkeeper noise and they are not critical to the project. --- greenkeeper.json | 9 --------- 1 file changed, 9 deletions(-) diff --git a/greenkeeper.json b/greenkeeper.json index ae2649cc9..2d593daf5 100644 --- a/greenkeeper.json +++ b/greenkeeper.json @@ -4,15 +4,6 @@ "packages": [ "package.json" ] - }, - "examples": { - "packages": [ - "examples/bundle-browserify/package.json", - "examples/bundle-webpack/package.json", - "examples/name-api/package.json", - "examples/sub-module/package.json", - "examples/upload-file-via-browser/package.json" - ] } } } From 3764d060563a4fb4972b0dfbefdbd8c2a72e5cf5 Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Wed, 28 Aug 2019 11:04:38 +0100 Subject: [PATCH 095/233] feat: browser pubsub (#1059) This PR enabled pubsub in the browser and paves the way for a switch to using `fetch` by default and allowing for cancelable requests via the use of `AbortController`. It's mostly the work done in https://github.com/ipfs-shipyard/js-ipfs-http-client-lite/pull/1 but adapted a bit for use here. If approved, we can start work moving the other commands to use `fetch`. The work in https://github.com/ipfs-shipyard/js-ipfs-http-client-lite has proven the hard parts (uploading files) are all possible using the `fetch` API. Since `fetch` is promise based, when moving the other commands it makes sense to just switch to async/await as per https://github.com/ipfs/js-ipfs/issues/1670 (and callbackify instead of promisify). Depends on: * [x] https://github.com/ipfs/interface-js-ipfs-core/pull/505 resolves https://github.com/ipfs/js-ipfs-http-client/issues/518 refs https://github.com/ipfs/js-ipfs/issues/2093 resolves https://github.com/ipfs/js-ipfs-http-client/issues/932 License: MIT Signed-off-by: Alan Shaw --- package.json | 8 +- src/lib/configure.js | 59 ++++++++ src/lib/error-handler.js | 31 ++++ src/lib/multiaddr.js | 18 +++ src/lib/stream-to-iterable.js | 25 ++++ src/pubsub.js | 212 ---------------------------- src/pubsub/index.js | 50 +++++++ src/pubsub/ls.js | 18 +++ src/pubsub/peers.js | 26 ++++ src/pubsub/publish.js | 45 ++++++ src/pubsub/subscribe.js | 85 +++++++++++ src/pubsub/subscription-tracker.js | 52 +++++++ src/pubsub/unsubscribe.js | 10 ++ src/utils/pubsub-message-stream.js | 34 ----- src/utils/pubsub-message-utils.js | 39 ----- src/utils/stringlist-to-array.js | 9 -- test/interface.spec.js | 18 ++- test/lib.configure.spec.js | 77 ++++++++++ test/lib.error-handler.spec.js | 54 +++++++ test/lib.stream-to-iterable.spec.js | 43 ++++++ test/pubsub-in-browser.spec.js | 162 --------------------- test/utils/throws-async.js | 10 ++ 22 files changed, 618 insertions(+), 467 deletions(-) create mode 100644 src/lib/configure.js create mode 100644 src/lib/error-handler.js create mode 100644 src/lib/multiaddr.js create mode 100644 src/lib/stream-to-iterable.js delete mode 100644 src/pubsub.js create mode 100644 src/pubsub/index.js create mode 100644 src/pubsub/ls.js create mode 100644 src/pubsub/peers.js create mode 100644 src/pubsub/publish.js create mode 100644 src/pubsub/subscribe.js create mode 100644 src/pubsub/subscription-tracker.js create mode 100644 src/pubsub/unsubscribe.js delete mode 100644 src/utils/pubsub-message-stream.js delete mode 100644 src/utils/pubsub-message-utils.js delete mode 100644 src/utils/stringlist-to-array.js create mode 100644 test/lib.configure.spec.js create mode 100644 test/lib.error-handler.spec.js create mode 100644 test/lib.stream-to-iterable.spec.js delete mode 100644 test/pubsub-in-browser.spec.js create mode 100644 test/utils/throws-async.js diff --git a/package.json b/package.json index 33cd7bde1..16dc4850b 100644 --- a/package.json +++ b/package.json @@ -33,6 +33,7 @@ "coverage": "npx nyc -r html npm run test:node -- --bail" }, "dependencies": { + "abort-controller": "^3.0.0", "async": "^2.6.1", "bignumber.js": "^9.0.0", "bl": "^3.0.0", @@ -44,6 +45,7 @@ "detect-node": "^2.0.4", "end-of-stream": "^1.4.1", "err-code": "^1.1.2", + "explain-error": "^1.0.4", "flatmap": "0.0.3", "glob": "^7.1.3", "ipfs-block": "~0.8.1", @@ -56,9 +58,12 @@ "is-stream": "^2.0.0", "iso-stream-http": "~0.1.2", "iso-url": "~0.4.6", + "iterable-ndjson": "^1.1.0", "just-kebab-case": "^1.1.0", "just-map-keys": "^1.1.0", "kind-of": "^6.0.2", + "ky": "^0.11.2", + "ky-universal": "^0.2.2", "lru-cache": "^5.1.1", "multiaddr": "^6.0.6", "multibase": "~0.6.0", @@ -68,6 +73,7 @@ "once": "^1.4.0", "peer-id": "~0.12.3", "peer-info": "~0.15.1", + "promise-nodeify": "^3.0.1", "promisify-es6": "^1.0.3", "pull-defer": "~0.2.3", "pull-stream": "^3.6.9", @@ -86,7 +92,7 @@ "cross-env": "^5.2.0", "dirty-chai": "^2.0.1", "go-ipfs-dep": "0.4.21", - "interface-ipfs-core": "^0.109.0", + "interface-ipfs-core": "^0.111.0", "ipfsd-ctl": "~0.43.0", "nock": "^10.0.2", "stream-equal": "^1.1.1" diff --git a/src/lib/configure.js b/src/lib/configure.js new file mode 100644 index 000000000..a9036d1cd --- /dev/null +++ b/src/lib/configure.js @@ -0,0 +1,59 @@ +'use strict' +/* eslint-env browser */ + +const ky = require('ky-universal').default +const { isBrowser, isWebWorker } = require('ipfs-utils/src/env') +const { toUri } = require('./multiaddr') +const errorHandler = require('./error-handler') + +// Set default configuration and call create function with them +module.exports = create => config => { + config = config || {} + + if (typeof config === 'string') { + config = { apiAddr: config } + } else if (config.constructor && config.constructor.isMultiaddr) { + config = { apiAddr: config } + } else { + config = { ...config } + } + + config.apiAddr = (config.apiAddr || getDefaultApiAddr(config)).toString() + config.apiAddr = config.apiAddr.startsWith('/') ? toUri(config.apiAddr) : config.apiAddr + config.apiPath = config.apiPath || config['api-path'] || '/api/v0' + + return create({ + // TODO configure ky to use config.fetch when this is released: + // https://github.com/sindresorhus/ky/pull/153 + ky: ky.extend({ + prefixUrl: config.apiAddr + config.apiPath, + timeout: config.timeout || 60 * 1000, + headers: config.headers, + hooks: { + afterResponse: [errorHandler] + } + }), + ...config + }) +} + +function getDefaultApiAddr ({ protocol, host, port }) { + if (isBrowser || isWebWorker) { + if (!protocol && !host && !port) { // Use current origin + return '' + } + + if (!protocol) { + protocol = location.protocol.startsWith('http') + ? location.protocol.split(':')[0] + : 'http' + } + + host = host || location.hostname + port = port || location.port + + return `${protocol}://${host}${port ? ':' + port : ''}` + } + + return `${protocol || 'http'}://${host || 'localhost'}:${port || 5001}` +} diff --git a/src/lib/error-handler.js b/src/lib/error-handler.js new file mode 100644 index 000000000..1e788227c --- /dev/null +++ b/src/lib/error-handler.js @@ -0,0 +1,31 @@ +'use strict' + +const { HTTPError } = require('ky-universal') +const log = require('debug')('ipfs-http-client:lib:error-handler') + +function isJsonResponse (res) { + return (res.headers.get('Content-Type') || '').startsWith('application/json') +} + +module.exports = async function errorHandler (response) { + if (response.ok) return + + let msg + + try { + if (isJsonResponse(response)) { + const data = await response.json() + log(data) + msg = data.Message || data.message + } else { + msg = await response.text() + } + } catch (err) { + log('Failed to parse error response', err) + // Failed to extract/parse error message from response + throw new HTTPError(response) + } + + if (!msg) throw new HTTPError(response) + throw Object.assign(new Error(msg), { status: response.status }) +} diff --git a/src/lib/multiaddr.js b/src/lib/multiaddr.js new file mode 100644 index 000000000..09462ab34 --- /dev/null +++ b/src/lib/multiaddr.js @@ -0,0 +1,18 @@ +'use strict' + +// Convert a multiaddr to a URI +// Assumes multiaddr is in a format that can be converted to a HTTP(s) URI +exports.toUri = ma => { + const parts = `${ma}`.split('/') + const port = getPort(parts) + return `${getProtocol(parts)}://${parts[2]}${port == null ? '' : ':' + port}` +} + +function getProtocol (maParts) { + return maParts.indexOf('https') === -1 ? 'http' : 'https' +} + +function getPort (maParts) { + const tcpIndex = maParts.indexOf('tcp') + return tcpIndex === -1 ? null : maParts[tcpIndex + 1] +} diff --git a/src/lib/stream-to-iterable.js b/src/lib/stream-to-iterable.js new file mode 100644 index 000000000..5e06a99c6 --- /dev/null +++ b/src/lib/stream-to-iterable.js @@ -0,0 +1,25 @@ +'use strict' + +module.exports = function toIterable (body) { + // Node.js stream + if (body[Symbol.asyncIterator]) return body + + // Browser ReadableStream + if (body.getReader) { + return (async function * () { + const reader = body.getReader() + + try { + while (true) { + const { done, value } = await reader.read() + if (done) return + yield value + } + } finally { + reader.releaseLock() + } + })() + } + + throw new Error('unknown stream') +} diff --git a/src/pubsub.js b/src/pubsub.js deleted file mode 100644 index 6b298351d..000000000 --- a/src/pubsub.js +++ /dev/null @@ -1,212 +0,0 @@ -'use strict' - -const promisify = require('promisify-es6') -const EventEmitter = require('events') -const eos = require('end-of-stream') -const isNode = require('detect-node') -const setImmediate = require('async/setImmediate') -const PubsubMessageStream = require('./utils/pubsub-message-stream') -const stringlistToArray = require('./utils/stringlist-to-array') -const moduleConfig = require('./utils/module-config') - -const NotSupportedError = () => new Error('pubsub is currently not supported when run in the browser') - -/* Public API */ -module.exports = (arg) => { - const send = moduleConfig(arg) - - /* Internal subscriptions state and functions */ - const ps = new EventEmitter() - const subscriptions = {} - ps.id = Math.random() - return { - subscribe: (topic, handler, options, callback) => { - const defaultOptions = { - discover: false - } - - if (typeof options === 'function') { - callback = options - options = defaultOptions - } - - if (!options) { - options = defaultOptions - } - - // Throw an error if ran in the browsers - if (!isNode) { - if (!callback) { - return Promise.reject(NotSupportedError()) - } - - return setImmediate(() => callback(NotSupportedError())) - } - - // promisify doesn't work as we always pass a - // function as last argument (`handler`) - if (!callback) { - return new Promise((resolve, reject) => { - subscribe(topic, handler, options, (err) => { - if (err) { - return reject(err) - } - resolve() - }) - }) - } - - subscribe(topic, handler, options, callback) - }, - unsubscribe: (topic, handler, callback) => { - if (!isNode) { - if (!callback) { - return Promise.reject(NotSupportedError()) - } - - return setImmediate(() => callback(NotSupportedError())) - } - - if (ps.listenerCount(topic) === 0 || !subscriptions[topic]) { - const err = new Error(`Not subscribed to '${topic}'`) - - if (!callback) { - return Promise.reject(err) - } - - return setImmediate(() => callback(err)) - } - - if (!handler && !callback) { - ps.removeAllListeners(topic) - } else { - ps.removeListener(topic, handler) - } - - // Drop the request once we are actually done - if (ps.listenerCount(topic) === 0) { - if (!callback) { - return new Promise((resolve, reject) => { - // When the response stream has ended, resolve the promise - eos(subscriptions[topic].res, (err) => { - // FIXME: Artificial timeout needed to ensure unsubscribed - setTimeout(() => { - if (err) return reject(err) - resolve() - }) - }) - subscriptions[topic].req.abort() - subscriptions[topic] = null - }) - } - - // When the response stream has ended, call the callback - eos(subscriptions[topic].res, (err) => { - // FIXME: Artificial timeout needed to ensure unsubscribed - setTimeout(() => callback(err)) - }) - subscriptions[topic].req.abort() - subscriptions[topic] = null - return - } - - if (!callback) { - return Promise.resolve() - } - - setImmediate(() => callback()) - }, - publish: promisify((topic, data, callback) => { - if (!isNode) { - return callback(NotSupportedError()) - } - - if (!Buffer.isBuffer(data)) { - return callback(new Error('data must be a Buffer')) - } - - const request = { - path: 'pubsub/pub', - args: [topic, data] - } - - send(request, callback) - }), - ls: promisify((callback) => { - if (!isNode) { - return callback(NotSupportedError()) - } - - const request = { - path: 'pubsub/ls' - } - - send.andTransform(request, stringlistToArray, callback) - }), - peers: promisify((topic, callback) => { - if (!isNode) { - return callback(NotSupportedError()) - } - - const request = { - path: 'pubsub/peers', - args: [topic] - } - - send.andTransform(request, stringlistToArray, callback) - }), - setMaxListeners (n) { - return ps.setMaxListeners(n) - } - } - - function subscribe (topic, handler, options, callback) { - ps.on(topic, handler) - - if (subscriptions[topic]) { - // TODO: should a callback error be returned? - return callback() - } - - // Request params - const request = { - path: 'pubsub/sub', - args: [topic], - qs: { - discover: options.discover - } - } - - // Start the request and transform the response - // stream to Pubsub messages stream - subscriptions[topic] = {} - subscriptions[topic].req = send.andTransform(request, PubsubMessageStream.from, (err, stream) => { - if (err) { - subscriptions[topic] = null - ps.removeListener(topic, handler) - return callback(err) - } - - subscriptions[topic].res = stream - - stream.on('data', (msg) => { - ps.emit(topic, msg) - }) - - stream.on('error', (err) => { - ps.emit('error', err) - }) - - eos(stream, (err) => { - if (err) { - ps.emit('error', err) - } - - subscriptions[topic] = null - ps.removeListener(topic, handler) - }) - - callback() - }) - } -} diff --git a/src/pubsub/index.js b/src/pubsub/index.js new file mode 100644 index 000000000..2738bd5ac --- /dev/null +++ b/src/pubsub/index.js @@ -0,0 +1,50 @@ +'use strict' + +const nodeify = require('promise-nodeify') + +// This file is temporary and for compatibility with legacy usage +module.exports = (send, options) => { + if (typeof send !== 'function') { + options = send + } + + const ls = require('./ls')(options) + const peers = require('./peers')(options) + const publish = require('./publish')(options) + const subscribe = require('./subscribe')(options) + const unsubscribe = require('./unsubscribe')(options) + + return { + ls: (options, callback) => { + if (typeof options === 'function') { + callback = options + options = {} + } + return nodeify(ls(options), callback) + }, + peers: (topic, options, callback) => { + if (typeof options === 'function') { + callback = options + options = {} + } + return nodeify(peers(topic, options), callback) + }, + publish: (topic, data, options, callback) => { + if (typeof options === 'function') { + callback = options + options = {} + } + return nodeify(publish(topic, data, options), callback) + }, + subscribe: (topic, handler, options, callback) => { + if (typeof options === 'function') { + callback = options + options = {} + } + return nodeify(subscribe(topic, handler, options), callback) + }, + unsubscribe: (topic, handler, callback) => { + return nodeify(unsubscribe(topic, handler), callback) + } + } +} diff --git a/src/pubsub/ls.js b/src/pubsub/ls.js new file mode 100644 index 000000000..177dcd491 --- /dev/null +++ b/src/pubsub/ls.js @@ -0,0 +1,18 @@ +'use strict' + +const configure = require('../lib/configure') + +module.exports = configure(({ ky }) => { + return async (options) => { + options = options || {} + + const { Strings } = await ky.get('pubsub/ls', { + timeout: options.timeout, + signal: options.signal, + headers: options.headers, + searchParams: options.searchParams + }).json() + + return Strings || [] + } +}) diff --git a/src/pubsub/peers.js b/src/pubsub/peers.js new file mode 100644 index 000000000..bdeca60e4 --- /dev/null +++ b/src/pubsub/peers.js @@ -0,0 +1,26 @@ +'use strict' + +const configure = require('../lib/configure') + +module.exports = configure(({ ky }) => { + return async (topic, options) => { + if (!options && typeof topic === 'object') { + options = topic + topic = null + } + + options = options || {} + + const searchParams = new URLSearchParams(options.searchParams) + searchParams.set('arg', topic) + + const { Strings } = await ky.get('pubsub/peers', { + timeout: options.timeout, + signal: options.signal, + headers: options.headers, + searchParams + }).json() + + return Strings || [] + } +}) diff --git a/src/pubsub/publish.js b/src/pubsub/publish.js new file mode 100644 index 000000000..a41c8fba0 --- /dev/null +++ b/src/pubsub/publish.js @@ -0,0 +1,45 @@ +'use strict' + +const { Buffer } = require('buffer') +const configure = require('../lib/configure') + +module.exports = configure(({ ky }) => { + return async (topic, data, options) => { + options = options || {} + data = Buffer.from(data) + + const searchParams = new URLSearchParams(options.searchParams) + searchParams.set('arg', topic) + + const res = await ky.post(`pubsub/pub?${searchParams}&arg=${encodeBuffer(data)}`, { + timeout: options.timeout, + signal: options.signal, + headers: options.headers + }).text() + + return res + } +}) + +function encodeBuffer (buf) { + let uriEncoded = '' + for (const byte of buf) { + // https://tools.ietf.org/html/rfc3986#page-14 + // ALPHA (%41-%5A and %61-%7A), DIGIT (%30-%39), hyphen (%2D), period (%2E), + // underscore (%5F), or tilde (%7E) + if ( + (byte >= 0x41 && byte <= 0x5A) || + (byte >= 0x61 && byte <= 0x7A) || + (byte >= 0x30 && byte <= 0x39) || + (byte === 0x2D) || + (byte === 0x2E) || + (byte === 0x5F) || + (byte === 0x7E) + ) { + uriEncoded += String.fromCharCode(byte) + } else { + uriEncoded += `%${byte.toString(16).padStart(2, '0')}` + } + } + return uriEncoded +} diff --git a/src/pubsub/subscribe.js b/src/pubsub/subscribe.js new file mode 100644 index 000000000..ae95ec5c8 --- /dev/null +++ b/src/pubsub/subscribe.js @@ -0,0 +1,85 @@ +'use strict' + +const ndjson = require('iterable-ndjson') +const explain = require('explain-error') +const bs58 = require('bs58') +const { Buffer } = require('buffer') +const log = require('debug')('ipfs-http-client:pubsub:subscribe') +const configure = require('../lib/configure') +const toIterable = require('../lib/stream-to-iterable') +const SubscriptionTracker = require('./subscription-tracker') + +module.exports = configure(({ ky }) => { + const subsTracker = SubscriptionTracker.singleton() + const publish = require('./publish')({ ky }) + + return async (topic, handler, options) => { + options = options || {} + options.signal = subsTracker.subscribe(topic, handler, options.signal) + + const searchParams = new URLSearchParams(options.searchParams) + searchParams.set('arg', topic) + if (options.discover != null) searchParams.set('discover', options.discover) + + let res + + // In Firefox, the initial call to fetch does not resolve until some data + // is received. If this doesn't happen within 1 second send an empty message + // to kickstart the process. + const ffWorkaround = setTimeout(async () => { + log(`Publishing empty message to "${topic}" to resolve subscription request`) + try { + await publish(topic, Buffer.alloc(0), options) + } catch (err) { + log('Failed to publish empty message', err) + } + }, 1000) + + try { + res = await ky.post('pubsub/sub', { + timeout: options.timeout, + signal: options.signal, + headers: options.headers, + searchParams + }) + } catch (err) { // Initial subscribe fail, ensure we clean up + subsTracker.unsubscribe(topic, handler) + throw err + } + + clearTimeout(ffWorkaround) + + readMessages(ndjson(toIterable(res.body)), { + onMessage: handler, + onEnd: () => subsTracker.unsubscribe(topic, handler), + onError: options.onError + }) + } +}) + +async function readMessages (msgStream, { onMessage, onEnd, onError }) { + onError = onError || log + + try { + for await (const msg of msgStream) { + try { + onMessage({ + from: bs58.encode(Buffer.from(msg.from, 'base64')).toString(), + data: Buffer.from(msg.data, 'base64'), + seqno: Buffer.from(msg.seqno, 'base64'), + topicIDs: msg.topicIDs + }) + } catch (err) { + onError(explain(err, 'Failed to parse pubsub message'), false, msg) // Not fatal + } + } + } catch (err) { + // FIXME: In testing with Chrome, err.type is undefined (should not be!) + // Temporarily use the name property instead. + if (err.type !== 'aborted' && err.name !== 'AbortError') { + onError(err, true) // Fatal + } + } finally { + onEnd() + } +} diff --git a/src/pubsub/subscription-tracker.js b/src/pubsub/subscription-tracker.js new file mode 100644 index 000000000..bbd7c2d7a --- /dev/null +++ b/src/pubsub/subscription-tracker.js @@ -0,0 +1,52 @@ +'use strict' + +const AbortController = require('abort-controller') + +class SubscriptionTracker { + constructor () { + this._subs = new Map() + } + + static singleton () { + if (SubscriptionTracker.instance) return SubscriptionTracker.instance + SubscriptionTracker.instance = new SubscriptionTracker() + return SubscriptionTracker.instance + } + + subscribe (topic, handler, signal) { + const topicSubs = this._subs.get(topic) || [] + + if (topicSubs.find(s => s.handler === handler)) { + throw new Error(`Already subscribed to ${topic} with this handler`) + } + + // Create controller so a call to unsubscribe can cancel the request + const controller = new AbortController() + + this._subs.set(topic, [{ handler, controller }].concat(topicSubs)) + + // If there is an external signal, forward the abort event + if (signal) { + signal.addEventListener('abort', () => this.unsubscribe(topic, handler)) + } + + return controller.signal + } + + unsubscribe (topic, handler) { + const subs = this._subs.get(topic) || [] + let unsubs + + if (handler) { + this._subs.set(topic, subs.filter(s => s.handler !== handler)) + unsubs = subs.filter(s => s.handler === handler) + } else { + this._subs.set(topic, []) + unsubs = subs + } + + unsubs.forEach(s => s.controller.abort()) + } +} + +module.exports = SubscriptionTracker diff --git a/src/pubsub/unsubscribe.js b/src/pubsub/unsubscribe.js new file mode 100644 index 000000000..6e7c727f4 --- /dev/null +++ b/src/pubsub/unsubscribe.js @@ -0,0 +1,10 @@ +'use strict' + +const configure = require('../lib/configure') +const SubscriptionTracker = require('./subscription-tracker') + +module.exports = configure(({ ky }) => { + const subsTracker = SubscriptionTracker.singleton() + // eslint-disable-next-line require-await + return async (topic, handler) => subsTracker.unsubscribe(topic, handler) +}) diff --git a/src/utils/pubsub-message-stream.js b/src/utils/pubsub-message-stream.js deleted file mode 100644 index d5925f714..000000000 --- a/src/utils/pubsub-message-stream.js +++ /dev/null @@ -1,34 +0,0 @@ -'use strict' - -const TransformStream = require('readable-stream').Transform -const PubsubMessage = require('./pubsub-message-utils') - -class PubsubMessageStream extends TransformStream { - constructor (options) { - const opts = Object.assign(options || {}, { objectMode: true }) - super(opts) - } - - static from (inputStream, callback) { - const outputStream = inputStream.pipe(new PubsubMessageStream()) - inputStream.on('end', () => outputStream.emit('end')) - callback(null, outputStream) - } - - _transform (obj, enc, callback) { - // go-ipfs returns '{}' as the very first object atm, we skip that - if (Object.keys(obj).length === 0) { - return callback() - } - - try { - const msg = PubsubMessage.deserialize(obj, 'base64') - this.push(msg) - callback() - } catch (err) { - return callback(err) - } - } -} - -module.exports = PubsubMessageStream diff --git a/src/utils/pubsub-message-utils.js b/src/utils/pubsub-message-utils.js deleted file mode 100644 index 53d1e397a..000000000 --- a/src/utils/pubsub-message-utils.js +++ /dev/null @@ -1,39 +0,0 @@ -'use strict' - -const bs58 = require('bs58') - -module.exports = { - deserialize (data, enc) { - enc = enc ? enc.toLowerCase() : 'json' - - if (enc === 'json') { - return deserializeFromJson(data) - } else if (enc === 'base64') { - return deserializeFromBase64(data) - } - - throw new Error(`Unsupported encoding: '${enc}'`) - } -} - -function deserializeFromJson (data) { - const json = JSON.parse(data) - return deserializeFromBase64(json) -} - -function deserializeFromBase64 (obj) { - if (!isPubsubMessage(obj)) { - throw new Error(`Not a pubsub message`) - } - - return { - from: bs58.encode(Buffer.from(obj.from, 'base64')).toString(), - seqno: Buffer.from(obj.seqno, 'base64'), - data: Buffer.from(obj.data, 'base64'), - topicIDs: obj.topicIDs || obj.topicCIDs - } -} - -function isPubsubMessage (obj) { - return obj && obj.from && obj.seqno && obj.data && (obj.topicIDs || obj.topicCIDs) -} diff --git a/src/utils/stringlist-to-array.js b/src/utils/stringlist-to-array.js deleted file mode 100644 index df28ee6df..000000000 --- a/src/utils/stringlist-to-array.js +++ /dev/null @@ -1,9 +0,0 @@ -'use strict' - -// Converts a go-ipfs "stringList" to an array -// { Strings: ['A', 'B'] } --> ['A', 'B'] -function stringlistToArray (res, cb) { - cb(null, res.Strings || []) -} - -module.exports = stringlistToArray diff --git a/test/interface.spec.js b/test/interface.spec.js index 220c79aa2..86ffac21d 100644 --- a/test/interface.spec.js +++ b/test/interface.spec.js @@ -226,7 +226,7 @@ describe('interface-ipfs-core tests', () => { tests.namePubsub(CommonFactory.create({ spawnOptions: { args: ['--enable-namesys-pubsub'], - initOptions: { bits: 1024 } + initOptions: { bits: 1024, profile: 'test' } } }), { skip: [ @@ -267,22 +267,20 @@ describe('interface-ipfs-core tests', () => { tests.pubsub(CommonFactory.create({ spawnOptions: { args: ['--enable-pubsub-experiment'], - initOptions: { bits: 1024 } + initOptions: { bits: 1024, profile: 'test' } } }), { - skip: isNode ? [ + skip: isWindows ? [ // pubsub.subscribe - isWindows ? { + { name: 'should send/receive 100 messages', reason: 'FIXME https://github.com/ipfs/interface-ipfs-core/pull/188#issuecomment-354673246 and https://github.com/ipfs/go-ipfs/issues/4778' - } : null, - isWindows ? { + }, + { name: 'should receive multiple messages', reason: 'FIXME https://github.com/ipfs/interface-ipfs-core/pull/188#issuecomment-354673246 and https://github.com/ipfs/go-ipfs/issues/4778' - } : null - ] : { - reason: 'FIXME pubsub is not supported in the browser https://github.com/ipfs/js-ipfs-http-client/issues/518' - } + } + ] : null }) tests.repo(defaultCommonFactory) diff --git a/test/lib.configure.spec.js b/test/lib.configure.spec.js new file mode 100644 index 000000000..f58ca4de7 --- /dev/null +++ b/test/lib.configure.spec.js @@ -0,0 +1,77 @@ +/* eslint-env mocha, browser */ +'use strict' + +const chai = require('chai') +const dirtyChai = require('dirty-chai') +const expect = chai.expect +chai.use(dirtyChai) +const Multiaddr = require('multiaddr') +const { isBrowser, isWebWorker } = require('ipfs-utils/src/env') + +const configure = require('../src/lib/configure') + +describe('lib/configure', () => { + it('should accept no config', () => { + configure(config => { + if (isBrowser || isWebWorker) { + expect(config.apiAddr).to.eql('') + } else { + expect(config.apiAddr).to.eql('http://localhost:5001') + } + })() + }) + + it('should accept string multiaddr', () => { + const input = '/ip4/127.0.0.1/tcp/5001' + configure(config => { + expect(config.apiAddr).to.eql('http://127.0.0.1:5001') + })(input) + }) + + it('should accept multiaddr instance', () => { + const input = Multiaddr('/ip4/127.0.0.1') + configure(config => { + expect(config.apiAddr).to.eql('http://127.0.0.1') + })(input) + }) + + it('should accept object with protocol, host and port', () => { + const input = { protocol: 'https', host: 'ipfs.io', port: 138 } + configure(config => { + expect(config.apiAddr).to.eql('https://ipfs.io:138') + })(input) + }) + + it('should accept object with protocol only', () => { + const input = { protocol: 'https' } + configure(config => { + if (isBrowser || isWebWorker) { + expect(config.apiAddr).to.eql(`https://${location.host}`) + } else { + expect(config.apiAddr).to.eql('https://localhost:5001') + } + })(input) + }) + + it('should accept object with host only', () => { + const input = { host: 'ipfs.io' } + configure(config => { + if (isBrowser || isWebWorker) { + expect(config.apiAddr).to.eql(`http://ipfs.io:${location.port}`) + } else { + expect(config.apiAddr).to.eql('http://ipfs.io:5001') + } + })(input) + }) + + it('should accept object with port only', () => { + const input = { port: 138 } + configure(config => { + if (isBrowser || isWebWorker) { + expect(config.apiAddr).to.eql(`http://${location.hostname}:138`) + } else { + expect(config.apiAddr).to.eql('http://localhost:138') + } + })(input) + }) +}) diff --git a/test/lib.error-handler.spec.js b/test/lib.error-handler.spec.js new file mode 100644 index 000000000..4e97260ec --- /dev/null +++ b/test/lib.error-handler.spec.js @@ -0,0 +1,54 @@ +/* eslint-env mocha */ +'use strict' + +const chai = require('chai') +const dirtyChai = require('dirty-chai') +const { HTTPError } = require('ky-universal') +const expect = chai.expect +chai.use(dirtyChai) +const throwsAsync = require('./utils/throws-async') +const errorHandler = require('../src/lib/error-handler') + +describe('lib/error-handler', () => { + it('should parse json error response', async () => { + const res = { + ok: false, + headers: { get: () => 'application/json' }, + json: () => Promise.resolve({ + Message: 'boom', + Code: 0, + Type: 'error' + }), + status: 500 + } + + const err = await throwsAsync(errorHandler(res)) + + expect(err.message).to.eql('boom') + expect(err.status).to.eql(500) + }) + + it('should gracefully fail on parse json', async () => { + const res = { + ok: false, + headers: { get: () => 'application/json' }, + json: () => 'boom', // not valid json! + status: 500 + } + + const err = await throwsAsync(errorHandler(res)) + expect(err instanceof HTTPError).to.be.true() + }) + + it('should gracefully fail on read text', async () => { + const res = { + ok: false, + headers: { get: () => 'text/plain' }, + text: () => Promise.reject(new Error('boom')), + status: 500 + } + + const err = await throwsAsync(errorHandler(res)) + expect(err instanceof HTTPError).to.be.true() + }) +}) diff --git a/test/lib.stream-to-iterable.spec.js b/test/lib.stream-to-iterable.spec.js new file mode 100644 index 000000000..6c14cac94 --- /dev/null +++ b/test/lib.stream-to-iterable.spec.js @@ -0,0 +1,43 @@ +/* eslint-env mocha */ +'use strict' + +const chai = require('chai') +const dirtyChai = require('dirty-chai') +const expect = chai.expect +chai.use(dirtyChai) +const toIterable = require('../src/lib/stream-to-iterable') + +describe('lib/stream-to-iterable', () => { + it('should return input if already async iterable', () => { + const input = { [Symbol.asyncIterator] () { return this } } + expect(toIterable(input)).to.equal(input) + }) + + it('should convert reader to async iterable', async () => { + const inputData = [2, 31, 3, 4] + const input = { + getReader () { + let i = 0 + return { + read () { + return i === inputData.length + ? { done: true } + : { value: inputData[i++] } + }, + releaseLock () {} + } + } + } + + const chunks = [] + for await (const chunk of toIterable(input)) { + chunks.push(chunk) + } + + expect(chunks).to.eql(inputData) + }) + + it('should throw on unknown stream', () => { + expect(() => toIterable({})).to.throw('unknown stream') + }) +}) diff --git a/test/pubsub-in-browser.spec.js b/test/pubsub-in-browser.spec.js deleted file mode 100644 index ff1a22347..000000000 --- a/test/pubsub-in-browser.spec.js +++ /dev/null @@ -1,162 +0,0 @@ -/* - We currently don't support pubsub when run in the browser, - and we test it with separate set of tests to make sure - if it's being used in the browser, pubsub errors. - - More info: https://github.com/ipfs/js-ipfs-http-client/issues/518 - - This means: - - You can use pubsub from js-ipfs-http-client in Node.js - - You can use pubsub from js-ipfs-http-client in Electron - (when js-ipfs-http-client is ran in the main process of Electron) - - - You can't use pubsub from js-ipfs-http-client in the browser - - You can't use pubsub from js-ipfs-http-client in Electron's - renderer process - - - You can use pubsub from js-ipfs in the browsers - - You can use pubsub from js-ipfs in Node.js - - You can use pubsub from js-ipfs in Electron - (in both the main process and the renderer process) - - See https://github.com/ipfs/js-ipfs for details on - pubsub in js-ipfs -*/ - -/* eslint-env mocha */ -/* eslint max-nested-callbacks: ['error', 8] */ -'use strict' - -const isNode = require('detect-node') -const chai = require('chai') -const dirtyChai = require('dirty-chai') -const expect = chai.expect -chai.use(dirtyChai) - -const ipfsClient = require('../src') -const f = require('./utils/factory') - -const expectedError = 'pubsub is currently not supported when run in the browser' - -describe('.pubsub is not supported in the browser, yet!', function () { - this.timeout(50 * 1000) - - if (isNode) { return } - - const topic = 'pubsub-tests' - let ipfs - let ipfsd - - before((done) => { - f.spawn({ initOptions: { bits: 1024, profile: 'test' } }, (err, _ipfsd) => { - expect(err).to.not.exist() - ipfsd = _ipfsd - ipfs = ipfsClient(_ipfsd.apiAddr) - done() - }) - }) - - after((done) => { - if (!ipfsd) return done() - ipfsd.stop(done) - }) - - describe('everything errors', () => { - describe('Callback API', () => { - describe('.publish', () => { - it('throws an error if called in the browser', (done) => { - ipfs.pubsub.publish(topic, 'hello friend', (err, topics) => { - expect(err).to.exist() - expect(err.message).to.equal(expectedError) - done() - }) - }) - }) - - describe('.subscribe', () => { - const handler = () => {} - it('throws an error if called in the browser', (done) => { - ipfs.pubsub.subscribe(topic, handler, {}, (err, topics) => { - expect(err).to.exist() - expect(err.message).to.equal(expectedError) - done() - }) - }) - }) - - describe('.peers', () => { - it('throws an error if called in the browser', (done) => { - ipfs.pubsub.peers(topic, (err, topics) => { - expect(err).to.exist() - expect(err.message).to.equal(expectedError) - done() - }) - }) - }) - - describe('.ls', () => { - it('throws an error if called in the browser', (done) => { - ipfs.pubsub.ls((err, topics) => { - expect(err).to.exist() - expect(err.message).to.equal(expectedError) - done() - }) - }) - }) - }) - - describe('Promise API', () => { - describe('.publish', () => { - it('throws an error if called in the browser', () => { - return ipfs.pubsub.publish(topic, 'hello friend') - .catch((err) => { - expect(err).to.exist() - expect(err.message).to.equal(expectedError) - }) - }) - }) - - describe('.subscribe', () => { - const handler = () => {} - it('throws an error if called in the browser', (done) => { - ipfs.pubsub.subscribe(topic, handler, {}) - .catch((err) => { - expect(err).to.exist() - expect(err.message).to.equal(expectedError) - done() - }) - }) - }) - - describe('.peers', () => { - it('throws an error if called in the browser', (done) => { - ipfs.pubsub.peers(topic) - .catch((err) => { - expect(err).to.exist() - expect(err.message).to.equal(expectedError) - done() - }) - }) - }) - - describe('.ls', () => { - it('throws an error if called in the browser', () => { - return ipfs.pubsub.ls() - .catch((err) => { - expect(err).to.exist() - expect(err.message).to.equal(expectedError) - }) - }) - }) - }) - - describe('.unsubscribe', () => { - it('throws an error if called in the browser', (done) => { - ipfs.pubsub.unsubscribe('test', () => {}, (err) => { - expect(err).to.exist() - expect(err.message).to.equal(expectedError) - done() - }) - }) - }) - }) -}) diff --git a/test/utils/throws-async.js b/test/utils/throws-async.js new file mode 100644 index 000000000..0d4e677fd --- /dev/null +++ b/test/utils/throws-async.js @@ -0,0 +1,10 @@ +'use strict' + +module.exports = async fnOrPromise => { + try { + await (fnOrPromise.then ? fnOrPromise : fnOrPromise()) + } catch (err) { + return err + } + throw new Error('did not throw') +} From 501fd1c46fc2fdeba6ee6878666bbd15702c7f0d Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Wed, 28 Aug 2019 11:19:01 +0100 Subject: [PATCH 096/233] chore: update windows Travis config (#1084) Test on Node.js 12 and also utilise cache. License: MIT Signed-off-by: Alan Shaw --- .travis.yml | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/.travis.yml b/.travis.yml index 1368eb6eb..21dbade12 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,6 +12,7 @@ node_js: os: - linux - osx + - windows script: npx nyc -s npm run test:node -- --bail after_success: npx nyc report --reporter=text-lcov > coverage.lcov && npx codecov @@ -21,13 +22,8 @@ jobs: - name: electron-renderer fast_finish: true - - include: - - os: windows - filter_secrets: false - cache: false - + include: - stage: check script: - npx aegir build --bundlesize @@ -45,12 +41,12 @@ jobs: addons: firefox: latest script: npx aegir test -t browser -t webworker -- --browsers FirefoxHeadless - + - stage: test name: electron-main script: - xvfb-run npx aegir test -t electron-main -- --bail - + - stage: test name: electron-renderer script: From bee6143fee9c55741767171ad7b2aa6a562e7b20 Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Wed, 28 Aug 2019 12:33:24 +0100 Subject: [PATCH 097/233] chore(package): update go-ipfs-dep to version 0.4.22 (#1075) --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 16dc4850b..e86c4c6be 100644 --- a/package.json +++ b/package.json @@ -91,7 +91,7 @@ "chai": "^4.2.0", "cross-env": "^5.2.0", "dirty-chai": "^2.0.1", - "go-ipfs-dep": "0.4.21", + "go-ipfs-dep": "^0.4.22", "interface-ipfs-core": "^0.111.0", "ipfsd-ctl": "~0.43.0", "nock": "^10.0.2", From d5b64123270d2e224afe299ab419136c5ebd1d89 Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Wed, 28 Aug 2019 17:09:03 +0100 Subject: [PATCH 098/233] chore(package): update buffer to version 5.4.2 (#1085) * chore(package): update buffer to version 5.4.0 * chore: update buffer dep --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e86c4c6be..bb51c3e95 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,7 @@ "bignumber.js": "^9.0.0", "bl": "^3.0.0", "bs58": "^4.0.1", - "buffer": "^5.2.1", + "buffer": "^5.4.2", "cids": "~0.7.1", "concat-stream": "github:hugomrdias/concat-stream#feat/smaller", "debug": "^4.1.0", From 35150709d06cdd2293e83dc54a950761b9b795df Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" <23040076+greenkeeper[bot]@users.noreply.github.com> Date: Wed, 28 Aug 2019 18:11:11 +0100 Subject: [PATCH 099/233] fix(package): update err-code to version 2.0.0 (#1053) --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index bb51c3e95..882bf78e9 100644 --- a/package.json +++ b/package.json @@ -44,7 +44,7 @@ "debug": "^4.1.0", "detect-node": "^2.0.4", "end-of-stream": "^1.4.1", - "err-code": "^1.1.2", + "err-code": "^2.0.0", "explain-error": "^1.0.4", "flatmap": "0.0.3", "glob": "^7.1.3", From 69a56cb8b3f9152afca350278ab38fa6db72c263 Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Thu, 29 Aug 2019 12:08:11 +0100 Subject: [PATCH 100/233] docs: browser pubsub example (#1086) License: MIT Signed-off-by: Alan Shaw --- README.md | 26 +----- examples/browser-pubsub/.gitignore | 1 + examples/browser-pubsub/README.md | 94 +++++++++++++++++++ examples/browser-pubsub/index.html | 42 +++++++++ examples/browser-pubsub/index.js | 135 +++++++++++++++++++++++++++ examples/browser-pubsub/package.json | 20 ++++ examples/browser-pubsub/util.js | 31 ++++++ package.json | 3 +- 8 files changed, 327 insertions(+), 25 deletions(-) create mode 100644 examples/browser-pubsub/.gitignore create mode 100644 examples/browser-pubsub/README.md create mode 100644 examples/browser-pubsub/index.html create mode 100644 examples/browser-pubsub/index.js create mode 100644 examples/browser-pubsub/package.json create mode 100644 examples/browser-pubsub/util.js diff --git a/README.md b/README.md index c93113485..def4b05e5 100644 --- a/README.md +++ b/README.md @@ -203,7 +203,7 @@ const ipfs = ipfsClient({ - [`ipfs.lsPullStream(ipfsPath)`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#lspullstream) - [`ipfs.lsReadableStream(ipfsPath)`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#lsreadablestream) - [MFS (mutable file system) specific](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#mutable-file-system) - + _Explore the Mutable File System through interactive coding challenges in our [ProtoSchool tutorial](https://proto.school/#/mutable-file-system/)._ - [`ipfs.files.cp([from, to], [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#filescp) - [`ipfs.files.flush([path], [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#filesflush) @@ -233,7 +233,7 @@ const ipfs = ipfsClient({ #### Graph - [dag](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/DAG.md) - + _Explore the DAG API through interactive coding challenges in our [ProtoSchool tutorial](https://proto.school/#/basics)._ - [`ipfs.dag.get(cid, [path], [options], [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/DAG.md#dagget) - [`ipfs.dag.put(dagNode, [options], [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/DAG.md#dagput) @@ -339,28 +339,6 @@ const ipfs = ipfsClient({ - [`ipfs.key.rename(oldName, newName, [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/KEY.md#keyrename) - [`ipfs.key.rm(name, [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/KEY.md#keyrm) -#### Pubsub Caveat - -**Currently, the [PubSub API only works in Node.js environment](https://github.com/ipfs/js-ipfs-http-client/issues/518)** - -We currently don't support pubsub when run in the browser, and we test it with separate set of tests to make sure if it's being used in the browser, pubsub errors. - -More info: https://github.com/ipfs/js-ipfs-http-client/issues/518 - -This means: -- You can use pubsub from js-ipfs-http-client in Node.js -- You can use pubsub from js-ipfs-http-client in Electron - (when js-ipfs-http-client is ran in the main process of Electron) -- You can't use pubsub from js-ipfs-http-client in the browser -- You can't use pubsub from js-ipfs-http-client in Electron's - renderer process -- You can use pubsub from js-ipfs in the browsers -- You can use pubsub from js-ipfs in Node.js -- You can use pubsub from js-ipfs in Electron - (in both the main process and the renderer process) -- See https://github.com/ipfs/js-ipfs for details on - pubsub in js-ipfs - #### Instance utils - `ipfs.getEndpointConfig()` diff --git a/examples/browser-pubsub/.gitignore b/examples/browser-pubsub/.gitignore new file mode 100644 index 000000000..0e804e3a5 --- /dev/null +++ b/examples/browser-pubsub/.gitignore @@ -0,0 +1 @@ +bundle.js diff --git a/examples/browser-pubsub/README.md b/examples/browser-pubsub/README.md new file mode 100644 index 000000000..abe6a21f9 --- /dev/null +++ b/examples/browser-pubsub/README.md @@ -0,0 +1,94 @@ +# Pubsub in the browser + +> Use pubsub in the browser! + +This example is a demo web application that allows you to connect to an IPFS node, subscribe to a pubsub topic and send/receive messages. We'll start two IPFS nodes and two browsers and use the `ipfs-http-client` to instruct each node to listen to a pubsub topic and send/receive pubsub messages to/from each other. We're aiming for something like this: + +``` + +-----------+ +-----------+ + | +-------------------> | + | js-ipfs | pubsub | go-ipfs | + | <-------------------+ | + +-----^-----+ +-----^-----+ + | | + | HTTP API | HTTP API + | | ++-------------------+ +-------------------+ ++-------------------+ +-------------------+ +| | | | +| | | | +| Browser 1 | | Browser 2 | +| | | | +| | | | +| | | | ++-------------------+ +-------------------+ +``` + +## 1. Get started + +With Node.js and git installed, clone the repo and install the project dependencies: + +```sh +git clone https://github.com/ipfs/js-ipfs-http-client.git +cd js-ipfs-http-client +npm install # Installs ipfs-http-client dependencies +cd examples/browser-pubsub +npm install # Installs browser-pubsub app dependencies +``` + +Start the example application: + +```sh +npm start +``` + +You should see something similar to the following in your terminal and the web app should now be available if you navigate to http://127.0.0.1:8888 using your browser: + +```sh +Starting up http-server, serving ./ +Available on: + http://127.0.0.1:8888 +``` + +## 2. Start two IPFS nodes + +To demonstrate pubsub we need two nodes running so pubsub messages can be passed between them. + +Right now the easiest way to do this is to install and start a `js-ipfs` and `go-ipfs` node. There are other ways to do this, see [this document on running multiple nodes](https://github.com/ipfs/js-ipfs/tree/master/examples/running-multiple-nodes) for details. + +### Install and start the JS IPFS node + +```sh +npm install -g ipfs +jsipfs init +# Configure CORS to allow ipfs-http-client to access this IPFS node +jsipfs config --json API.HTTPHeaders.Access-Control-Allow-Origin '["http://127.0.0.1:8888"]' +# Start the IPFS node, enabling pubsub +jsipfs daemon --enable-pubsub-experiment +``` + +### Install and start the Go IPFS node + +Head over to https://dist.ipfs.io/#go-ipfs and hit the "Download go-ipfs" button. Extract the archive and read the instructions to install. + +After installation: + +```sh +ipfs init +# Configure CORS to allow ipfs-http-client to access this IPFS node +ipfs config --json API.HTTPHeaders.Access-Control-Allow-Origin '["http://127.0.0.1:8888"]' +# Start the IPFS node, enabling pubsub +ipfs daemon --enable-pubsub-experiment +``` + +## 3. Open two browsers and connect to each node + +Now, open up **two** browser windows. This could be two tabs in the same browser or two completely different browsers, it doesn't matter. Navigate to http://127.0.0.1:8888 in both. + +In the "API ADDR" field enter `/ip4/127.0.0.1/tcp/5001` in one browser and `/ip4/127.0.0.1/tcp/5002` in the other and hit the "Connect" button. + +This connects each browser to an IPFS node and now from the comfort of our browser we can instruct each node to listen to a pubsub topic and send/receive pubsub messages to each other. + +> N.B. Since our two IPFS nodes are running on the same network they should have already found each other by MDNS. So you probably won't need to use the "CONNECT TO PEER" field. If you find your pubsub messages aren't getting through, check the output from your `jsipfs daemon` command and find the first address listed in "Swarm listening on" - it'll look like `/ip4/127.0.0.1/tcp/4002/ipfs/Qm...`. Paste this address into the "CONNECT TO PEER" field for the browser that is connected to your go-ipfs node and hit connect. + +Finally, use the "SUBSCRIBE TO PUBSUB TOPIC" and "SEND MESSAGE" fields to do some pubsub-ing, you should see messages sent from one browser appear in the log of the other (provided they're both subscribed to the same topic). diff --git a/examples/browser-pubsub/index.html b/examples/browser-pubsub/index.html new file mode 100644 index 000000000..d5d84d564 --- /dev/null +++ b/examples/browser-pubsub/index.html @@ -0,0 +1,42 @@ + + + + Pubsub in the browser + + + + +
+ + + +

Pubsub

+
+
+
API Addr
+ + +
+
+
Connect to peer
+ + +
+
+
Subscribe to pubsub topic
+ + +
+
+
Send pubsub message
+ + +
+
+
Console
+
+
+
+ + + diff --git a/examples/browser-pubsub/index.js b/examples/browser-pubsub/index.js new file mode 100644 index 000000000..eae1dab17 --- /dev/null +++ b/examples/browser-pubsub/index.js @@ -0,0 +1,135 @@ +'use strict' + +const IpfsHttpClient = require('ipfs-http-client') +const { sleep, Logger, onEnterPress, catchAndLog } = require('./util') + +async function main () { + const apiUrlInput = document.getElementById('api-url') + const nodeConnectBtn = document.getElementById('node-connect') + + const peerAddrInput = document.getElementById('peer-addr') + const peerConnectBtn = document.getElementById('peer-connect') + + const topicInput = document.getElementById('topic') + const subscribeBtn = document.getElementById('subscribe') + + const messageInput = document.getElementById('message') + const sendBtn = document.getElementById('send') + + let log = Logger(document.getElementById('console')) + let ipfs + let topic + let peerId + + async function reset () { + if (ipfs && topic) { + log(`Unsubscribing from topic ${topic}`) + await ipfs.pubsub.unsubscribe(topic) + } + log = Logger(document.getElementById('console')) + topicInput.value = '' + topic = null + peerId = null + ipfs = null + } + + async function nodeConnect (url) { + await reset() + log(`Connecting to ${url}`) + ipfs = IpfsHttpClient(url) + const { id, agentVersion } = await ipfs.id() + peerId = id + log(`Success!`) + log(`Version ${agentVersion}`) + log(`Peer ID ${id}`) + } + + async function peerConnect (addr) { + if (!addr) throw new Error('Missing peer multiaddr') + if (!ipfs) throw new Error('Connect to a node first') + log(`Connecting to peer ${addr}`) + await ipfs.swarm.connect(addr) + log(`Success!`) + log('Listing swarm peers...') + await sleep() + const peers = await ipfs.swarm.peers() + peers.forEach(peer => { + const fullAddr = `${peer.addr}/ipfs/${peer.peer.toB58String()}` + log(`${fullAddr}`) + }) + log(`(${peers.length} peers total)`) + } + + async function subscribe (nextTopic) { + if (!nextTopic) throw new Error('Missing topic name') + if (!ipfs) throw new Error('Connect to a node first') + + const lastTopic = topic + + if (topic) { + topic = null + log(`Unsubscribing from topic ${lastTopic}`) + await ipfs.pubsub.unsubscribe(lastTopic) + } + + log(`Subscribing to ${nextTopic}...`) + + await ipfs.pubsub.subscribe(nextTopic, msg => { + const from = msg.from + const seqno = msg.seqno.toString('hex') + if (from === peerId) return log(`Ignoring message ${seqno} from self`) + log(`Message ${seqno} from ${from}:`) + try { + log(JSON.stringify(msg.data.toString(), null, 2)) + } catch (_) { + log(msg.data.toString('hex')) + } + }, { + onError: (err, fatal) => { + if (fatal) { + console.error(err) + log(`${err.message}`) + topic = null + log('Resubscribing in 5s...') + setTimeout(catchAndLog(() => subscribe(nextTopic), log), 5000) + } else { + console.warn(err) + } + } + }) + + topic = nextTopic + log(`Success!`) + } + + async function send (msg) { + if (!msg) throw new Error('Missing message') + if (!topic) throw new Error('Subscribe to a topic first') + if (!ipfs) throw new Error('Connect to a node first') + + log(`Sending message to ${topic}...`) + await ipfs.pubsub.publish(topic, msg) + log(`Success!`) + } + + const onNodeConnectClick = catchAndLog(() => nodeConnect(apiUrlInput.value), log) + apiUrlInput.addEventListener('keydown', onEnterPress(onNodeConnectClick)) + nodeConnectBtn.addEventListener('click', onNodeConnectClick) + + const onPeerConnectClick = catchAndLog(() => peerConnect(peerAddrInput.value), log) + peerAddrInput.addEventListener('keydown', onEnterPress(onPeerConnectClick)) + peerConnectBtn.addEventListener('click', onPeerConnectClick) + + const onSubscribeClick = catchAndLog(() => subscribe(topicInput.value), log) + topicInput.addEventListener('keydown', onEnterPress(onSubscribeClick)) + subscribeBtn.addEventListener('click', onSubscribeClick) + + const onSendClick = catchAndLog(async () => { + await send(messageInput.value) + messageInput.value = '' + }, log) + messageInput.addEventListener('keydown', onEnterPress(onSendClick)) + sendBtn.addEventListener('click', onSendClick) +} + +main() diff --git a/examples/browser-pubsub/package.json b/examples/browser-pubsub/package.json new file mode 100644 index 000000000..c4c6e2727 --- /dev/null +++ b/examples/browser-pubsub/package.json @@ -0,0 +1,20 @@ +{ + "name": "browser-pubsub-example", + "version": "0.0.0", + "description": "An example demonstrating pubsub in the browser", + "private": true, + "main": "index.js", + "scripts": { + "start": "npm run build && npm run serve", + "build": "browserify index.js > bundle.js", + "serve": "http-server -a 127.0.0.1 -p 8888", + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "Alan Shaw", + "license": "MIT", + "dependencies": { + "browserify": "^16.5.0", + "http-server": "^0.11.1", + "ipfs-http-client": "../../" + } +} diff --git a/examples/browser-pubsub/util.js b/examples/browser-pubsub/util.js new file mode 100644 index 000000000..e6aada61f --- /dev/null +++ b/examples/browser-pubsub/util.js @@ -0,0 +1,31 @@ +exports.sleep = (ms = 1000) => new Promise(resolve => setTimeout(resolve, ms)) + +exports.Logger = outEl => { + outEl.innerHTML = '' + return message => { + const container = document.createElement('div') + container.innerHTML = message + outEl.appendChild(container) + outEl.scrollTop = outEl.scrollHeight + } +} + +exports.onEnterPress = fn => { + return e => { + if (event.which == 13 || event.keyCode == 13) { + e.preventDefault() + fn() + } + } +} + +exports.catchAndLog = (fn, log) => { + return async (...args) => { + try { + await fn(...args) + } catch (err) { + console.error(err) + log(`${err.message}`) + } + } +} diff --git a/package.json b/package.json index 882bf78e9..f1bf35677 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,8 @@ "browser": { "glob": false, "fs": false, - "stream": "readable-stream" + "stream": "readable-stream", + "ky-universal": "ky/umd" }, "repository": "github:ipfs/js-ipfs-http-client", "scripts": { From 377042b62d09a76f7ec8e8a6b44df6615ecfa163 Mon Sep 17 00:00:00 2001 From: Alex Potsides Date: Thu, 29 Aug 2019 12:08:46 +0100 Subject: [PATCH 101/233] feat: support adding files via async iterator (#1078) Adds a method called `ipfs._addAsyncIterator`, prefixed with an underscore to mark it as sort of unofficial (though it's what `ipfs.add` will become once the async iterator migration is complete) and we don't want to implement symmetrical `ipfs.catAsyncIterator` etc methods, or at least not yet. --- src/files-regular/add-async-iterator.js | 23 +++++++++++++++++++++++ src/files-regular/index.js | 1 + src/utils/load-commands.js | 1 + 3 files changed, 25 insertions(+) create mode 100644 src/files-regular/add-async-iterator.js diff --git a/src/files-regular/add-async-iterator.js b/src/files-regular/add-async-iterator.js new file mode 100644 index 000000000..3fa2b23ed --- /dev/null +++ b/src/files-regular/add-async-iterator.js @@ -0,0 +1,23 @@ +'use strict' + +const SendFilesStream = require('../utils/send-files-stream') +const FileResultStreamConverter = require('../utils/file-result-stream-converter') + +module.exports = (send) => { + return async function * (source, options) { + options = options || {} + options.converter = FileResultStreamConverter + + const stream = SendFilesStream(send, 'add')(options) + + for await (const entry of source) { + stream.write(entry) + } + + stream.end() + + for await (const entry of stream) { + yield entry + } + } +} diff --git a/src/files-regular/index.js b/src/files-regular/index.js index 059d7ea1c..e5b49e495 100644 --- a/src/files-regular/index.js +++ b/src/files-regular/index.js @@ -12,6 +12,7 @@ module.exports = (arg) => { addFromFs: require('../files-regular/add-from-fs')(send), addFromURL: require('../files-regular/add-from-url')(send), addFromStream: require('../files-regular/add')(send), + _addAsyncIterator: require('../files-regular/add-async-iterator')(send), cat: require('../files-regular/cat')(send), catReadableStream: require('../files-regular/cat-readable-stream')(send), catPullStream: require('../files-regular/cat-pull-stream')(send), diff --git a/src/utils/load-commands.js b/src/utils/load-commands.js index e4a914dd0..467af3cea 100644 --- a/src/utils/load-commands.js +++ b/src/utils/load-commands.js @@ -9,6 +9,7 @@ function requireCommands () { addFromFs: require('../files-regular/add-from-fs'), addFromURL: require('../files-regular/add-from-url'), addFromStream: require('../files-regular/add'), + _addAsyncIterator: require('../files-regular/add-async-iterator'), cat: require('../files-regular/cat'), catReadableStream: require('../files-regular/cat-readable-stream'), catPullStream: require('../files-regular/cat-pull-stream'), From bd114d22c68098cd10b221f539aad57d53dc1552 Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Thu, 29 Aug 2019 12:33:45 +0100 Subject: [PATCH 102/233] chore: update contributors --- package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index f1bf35677..b055227e5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ipfs-http-client", - "version": "33.1.1", + "version": "34.0.0", "description": "A client library for the IPFS HTTP API", "keywords": [ "ipfs" @@ -183,6 +183,7 @@ "dmitriy ryajov ", "elsehow ", "ethers ", + "greenkeeper[bot] <23040076+greenkeeper[bot]@users.noreply.github.com>", "greenkeeper[bot] ", "haad ", "kumavis ", From 33b090ad9a8b6f422db05c34d4317e620cf61e0e Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Thu, 29 Aug 2019 12:33:46 +0100 Subject: [PATCH 103/233] chore: release version v34.0.0 --- CHANGELOG.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3ad9df13d..c45dc7126 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,20 @@ + +# [34.0.0](https://github.com/ipfs/js-ipfs-http-client/compare/v33.1.1...v34.0.0) (2019-08-29) + + +### Bug Fixes + +* **package:** update err-code to version 2.0.0 ([#1053](https://github.com/ipfs/js-ipfs-http-client/issues/1053)) ([3515070](https://github.com/ipfs/js-ipfs-http-client/commit/3515070)) + + +### Features + +* browser pubsub ([#1059](https://github.com/ipfs/js-ipfs-http-client/issues/1059)) ([3764d06](https://github.com/ipfs/js-ipfs-http-client/commit/3764d06)) +* expose pin and preload arguments ([#1079](https://github.com/ipfs/js-ipfs-http-client/issues/1079)) ([e3ed6e9](https://github.com/ipfs/js-ipfs-http-client/commit/e3ed6e9)) +* support adding files via async iterator ([#1078](https://github.com/ipfs/js-ipfs-http-client/issues/1078)) ([377042b](https://github.com/ipfs/js-ipfs-http-client/commit/377042b)) + + + ## [33.1.1](https://github.com/ipfs/js-ipfs-http-client/compare/v33.1.0...v33.1.1) (2019-07-26) From 4271c7a5b5b17a1b7ab7fb3b5b2397d51030fcfc Mon Sep 17 00:00:00 2001 From: Alex Potsides Date: Tue, 3 Sep 2019 17:07:55 +0100 Subject: [PATCH 104/233] chore: upgrade ipfsd-ctl (#1088) Also converts all tests to async/await --- .aegir.js | 6 +- package.json | 7 +- src/utils/send-files-stream.js | 4 +- test/commands.spec.js | 37 +- test/constructor.spec.js | 32 +- test/custom-headers.spec.js | 36 +- test/dag.spec.js | 88 +++-- test/diag.spec.js | 72 ++-- test/endpoint-config.spec.js | 21 +- test/files-mfs.spec.js | 453 +++++++++++-------------- test/get.spec.js | 108 +++--- test/interface.spec.js | 13 +- test/key.spec.js | 79 ++--- test/log.spec.js | 70 ++-- test/node/swarm.js | 91 +++-- test/ping.spec.js | 180 ++++------ test/repo.spec.js | 54 ++- test/stats.spec.js | 86 +++-- test/utils/interface-common-factory.js | 15 +- 19 files changed, 628 insertions(+), 824 deletions(-) diff --git a/.aegir.js b/.aegir.js index 65a309618..d9a727161 100644 --- a/.aegir.js +++ b/.aegir.js @@ -22,7 +22,9 @@ module.exports = { singleRun: true }, hooks: { - pre: server.start.bind(server), - post: server.stop.bind(server) + browser: { + pre: () => server.start(), + post: () => server.stop() + } } } diff --git a/package.json b/package.json index b055227e5..cc37fe15e 100644 --- a/package.json +++ b/package.json @@ -26,6 +26,10 @@ "test:node": "aegir test -t node", "test:browser": "aegir test -t browser", "test:webworker": "aegir test -t webworker", + "test:electron-main": "aegir test -t electron-main", + "test:electron-renderer": "aegir test -t electron-renderer", + "test:chrome": "aegir test -t browser -t webworker -- --browsers ChromeHeadless", + "test:firefox": "aegir test -t browser -t webworker -- --browsers FirefoxHeadless", "lint": "aegir lint", "build": "aegir build", "release": "aegir release ", @@ -90,11 +94,12 @@ "aegir": "^20.0.0", "browser-process-platform": "~0.1.1", "chai": "^4.2.0", + "chai-as-promised": "^7.1.1", "cross-env": "^5.2.0", "dirty-chai": "^2.0.1", "go-ipfs-dep": "^0.4.22", "interface-ipfs-core": "^0.111.0", - "ipfsd-ctl": "~0.43.0", + "ipfsd-ctl": "~0.45.0", "nock": "^10.0.2", "stream-equal": "^1.1.1" }, diff --git a/src/utils/send-files-stream.js b/src/utils/send-files-stream.js index 91bd90fb4..09c55d376 100644 --- a/src/utils/send-files-stream.js +++ b/src/utils/send-files-stream.js @@ -78,8 +78,8 @@ module.exports = (send, path) => { qs['raw-leaves'] = propOrProp(options, 'raw-leaves', 'rawLeaves') qs['only-hash'] = propOrProp(options, 'only-hash', 'onlyHash') qs['wrap-with-directory'] = propOrProp(options, 'wrap-with-directory', 'wrapWithDirectory') - qs['pin'] = propOrProp(options, 'pin') - qs['preload'] = propOrProp(options, 'preload') + qs.pin = propOrProp(options, 'pin') + qs.preload = propOrProp(options, 'preload') qs.hash = propOrProp(options, 'hash', 'hashAlg') if (options.strategy === 'trickle' || options.trickle) { diff --git a/test/commands.spec.js b/test/commands.spec.js index 3fb4f02e0..66072c5f9 100644 --- a/test/commands.spec.js +++ b/test/commands.spec.js @@ -16,34 +16,25 @@ describe('.commands', function () { let ipfsd let ipfs - before((done) => { - f.spawn({ initOptions: { bits: 1024, profile: 'test' } }, (err, _ipfsd) => { - expect(err).to.not.exist() - ipfsd = _ipfsd - ipfs = ipfsClient(_ipfsd.apiAddr) - done() + before(async () => { + ipfsd = await f.spawn({ + initOptions: { + bits: 1024, + profile: 'test' + } }) + ipfs = ipfsClient(ipfsd.apiAddr) }) - after((done) => { - if (!ipfsd) return done() - ipfsd.stop(done) + after(async () => { + if (ipfsd) { + await ipfsd.stop() + } }) - it('lists commands', (done) => { - ipfs.commands((err, res) => { - expect(err).to.not.exist() - expect(res).to.exist() - done() - }) - }) + it('lists commands', async () => { + const res = await ipfs.commands() - describe('promise', () => { - it('lists commands', () => { - return ipfs.commands() - .then((res) => { - expect(res).to.exist() - }) - }) + expect(res).to.exist() }) }) diff --git a/test/constructor.spec.js b/test/constructor.spec.js index c138b7fb0..cc6a250c2 100644 --- a/test/constructor.spec.js +++ b/test/constructor.spec.js @@ -109,36 +109,30 @@ describe('ipfs-http-client constructor tests', () => { let apiAddr let ipfsd - before(function (done) { + before(async function () { this.timeout(60 * 1000) // slow CI - f.spawn({ initOptions: { bits: 1024, profile: 'test' } }, (err, node) => { - expect(err).to.not.exist() - ipfsd = node - apiAddr = node.apiAddr.toString() - done() - }) + ipfsd = await f.spawn({ initOptions: { bits: 1024, profile: 'test' } }) + apiAddr = ipfsd.apiAddr.toString() }) - after((done) => { - if (!ipfsd) return done() - ipfsd.stop(done) + after(async () => { + if (ipfsd) { + await ipfsd.stop() + } }) - it('can connect to an ipfs http api', (done) => { - clientWorks(ipfsClient(apiAddr), done) + it('can connect to an ipfs http api', async () => { + await clientWorks(ipfsClient(apiAddr)) }) }) }) -function clientWorks (client, done) { - client.id((err, id) => { - expect(err).to.not.exist() +async function clientWorks (client) { + const id = await client.id() - expect(id).to.have.a.property('id') - expect(id).to.have.a.property('publicKey') - done() - }) + expect(id).to.have.a.property('id') + expect(id).to.have.a.property('publicKey') } function expectConfig (ipfs, { host, port, protocol, apiPath }) { diff --git a/test/custom-headers.spec.js b/test/custom-headers.spec.js index 1e1748515..8d05897a6 100644 --- a/test/custom-headers.spec.js +++ b/test/custom-headers.spec.js @@ -17,23 +17,25 @@ describe('custom headers', function () { let ipfs let ipfsd // initialize ipfs with custom headers - before(done => { - f.spawn({ initOptions: { bits: 1024, profile: 'test' } }, (err, _ipfsd) => { - expect(err).to.not.exist() - ipfsd = _ipfsd - ipfs = ipfsClient({ - host: 'localhost', - port: 6001, - protocol: 'http', - headers: { - authorization: 'Bearer ' + 'YOLO' - } - }) - done() + before(async () => { + ipfsd = await f.spawn({ + initOptions: { + bits: 1024, + profile: 'test' + } + }) + + ipfs = ipfsClient({ + host: 'localhost', + port: 6001, + protocol: 'http', + headers: { + authorization: 'Bearer ' + 'YOLO' + } }) }) - it('are supported', done => { + it('are supported', (done) => { // spin up a test http server to inspect the requests made by the library const server = require('http').createServer((req, res) => { req.on('data', () => {}) @@ -57,5 +59,9 @@ describe('custom headers', function () { }) }) - after(done => ipfsd.stop(done)) + after(async () => { + if (ipfsd) { + await ipfsd.stop() + } + }) }) diff --git a/test/dag.spec.js b/test/dag.spec.js index eb69a959c..8796ba72b 100644 --- a/test/dag.spec.js +++ b/test/dag.spec.js @@ -5,9 +5,10 @@ const chai = require('chai') const dirtyChai = require('dirty-chai') +const chaiAsPromised = require('chai-as-promised') const expect = chai.expect chai.use(dirtyChai) -const series = require('async/series') +chai.use(chaiAsPromised) const { DAGNode } = require('ipld-dag-pb') const CID = require('cids') const ipfsClient = require('../src') @@ -18,67 +19,56 @@ let ipfs describe('.dag', function () { this.timeout(20 * 1000) - before(function (done) { - series([ - (cb) => f.spawn({ initOptions: { bits: 1024, profile: 'test' } }, (err, _ipfsd) => { - expect(err).to.not.exist() - ipfsd = _ipfsd - ipfs = ipfsClient(_ipfsd.apiAddr) - cb() - }) - ], done) + before(async function () { + ipfsd = await f.spawn({ + initOptions: { + bits: 1024, + profile: 'test' + } + }) + ipfs = ipfsClient(ipfsd.apiAddr) }) - after((done) => { - if (!ipfsd) return done() - ipfsd.stop(done) + after(async () => { + if (ipfsd) { + await ipfsd.stop() + } }) - it('should be able to put and get a DAG node with format dag-pb', (done) => { + it('should be able to put and get a DAG node with format dag-pb', async () => { const data = Buffer.from('some data') const node = DAGNode.create(data) - ipfs.dag.put(node, { format: 'dag-pb', hashAlg: 'sha2-256' }, (err, cid) => { - expect(err).to.not.exist() - cid = cid.toV0() - expect(cid.codec).to.equal('dag-pb') - cid = cid.toBaseEncodedString('base58btc') - // expect(cid).to.equal('bafybeig3t3eugdchignsgkou3ly2mmy4ic4gtfor7inftnqn3yq4ws3a5u') - expect(cid).to.equal('Qmd7xRhW5f29QuBFtqu3oSD27iVy35NRB91XFjmKFhtgMr') - ipfs.dag.get(cid, (err, result) => { - expect(err).to.not.exist() - expect(result.value.Data).to.deep.equal(data) - done() - }) - }) + let cid = await ipfs.dag.put(node, { format: 'dag-pb', hashAlg: 'sha2-256' }) + cid = cid.toV0() + expect(cid.codec).to.equal('dag-pb') + cid = cid.toBaseEncodedString('base58btc') + // expect(cid).to.equal('bafybeig3t3eugdchignsgkou3ly2mmy4ic4gtfor7inftnqn3yq4ws3a5u') + expect(cid).to.equal('Qmd7xRhW5f29QuBFtqu3oSD27iVy35NRB91XFjmKFhtgMr') + + const result = await ipfs.dag.get(cid) + + expect(result.value.Data).to.deep.equal(data) }) - it('should be able to put and get a DAG node with format dag-cbor', (done) => { + it('should be able to put and get a DAG node with format dag-cbor', async () => { const cbor = { foo: 'dag-cbor-bar' } - ipfs.dag.put(cbor, { format: 'dag-cbor', hashAlg: 'sha2-256' }, (err, cid) => { - expect(err).to.not.exist() - expect(cid.codec).to.equal('dag-cbor') - cid = cid.toBaseEncodedString('base32') - expect(cid).to.equal('bafyreic6f672hnponukaacmk2mmt7vs324zkagvu4hcww6yba6kby25zce') - ipfs.dag.get(cid, (err, result) => { - expect(err).to.not.exist() - expect(result.value).to.deep.equal(cbor) - done() - }) - }) + let cid = await ipfs.dag.put(cbor, { format: 'dag-cbor', hashAlg: 'sha2-256' }) + + expect(cid.codec).to.equal('dag-cbor') + cid = cid.toBaseEncodedString('base32') + expect(cid).to.equal('bafyreic6f672hnponukaacmk2mmt7vs324zkagvu4hcww6yba6kby25zce') + + const result = await ipfs.dag.get(cid) + + expect(result.value).to.deep.equal(cbor) }) - it('should callback with error when missing DAG resolver for multicodec from requested CID', (done) => { - ipfs.block.put(Buffer.from([0, 1, 2, 3]), { + it('should callback with error when missing DAG resolver for multicodec from requested CID', async () => { + const block = await ipfs.block.put(Buffer.from([0, 1, 2, 3]), { cid: new CID('z8mWaJ1dZ9fH5EetPuRsj8jj26pXsgpsr') - }, (err, block) => { - expect(err).to.not.exist() - - ipfs.dag.get(block.cid, (err, result) => { - expect(result).to.not.exist() - expect(err.message).to.equal('Missing IPLD format "git-raw"') - done() - }) }) + + await expect(ipfs.dag.get(block.cid)).to.be.rejectedWith('Missing IPLD format "git-raw"') }) }) diff --git a/test/diag.spec.js b/test/diag.spec.js index 3f12106e0..73efbb2de 100644 --- a/test/diag.spec.js +++ b/test/diag.spec.js @@ -19,68 +19,42 @@ describe('.diag', function () { let ipfsd let ipfs - before((done) => { - f.spawn({ initOptions: { bits: 1024, profile: 'test' } }, (err, _ipfsd) => { - expect(err).to.not.exist() - ipfsd = _ipfsd - ipfs = ipfsClient(_ipfsd.apiAddr) - done() + before(async () => { + ipfsd = await f.spawn({ + initOptions: { + bits: 1024, + profile: 'test' + } }) + ipfs = ipfsClient(ipfsd.apiAddr) }) - after((done) => { - if (!ipfsd) return done() - ipfsd.stop(done) + after(async () => { + if (ipfsd) { + await ipfsd.stop() + } }) - describe('Callback API', () => { + describe('api API', () => { // Disabled in go-ipfs 0.4.10 - it.skip('.diag.net', (done) => { - ipfs.diag.net((err, res) => { - expect(err).to.not.exist() - expect(res).to.exist() - done() - }) - }) + it.skip('.diag.net', async () => { + const res = await ipfs.diag.net() - it('.diag.sys', (done) => { - ipfs.diag.sys((err, res) => { - expect(err).to.not.exist() - expect(res).to.exist() - expect(res).to.have.a.property('memory') - expect(res).to.have.a.property('diskinfo') - done() - }) + expect(res).to.exist() }) - it('.diag.cmds', (done) => { - ipfs.diag.cmds((err, res) => { - expect(err).to.not.exist() - expect(res).to.exist() - done() - }) - }) - }) + it('.diag.sys', async () => { + const res = await ipfs.diag.sys() - describe('Promise API', () => { - // Disabled in go-ipfs 0.4.10 - it.skip('.diag.net', () => { - return ipfs.diag.net() - .then((res) => expect(res).to.exist()) + expect(res).to.exist() + expect(res).to.have.a.property('memory') + expect(res).to.have.a.property('diskinfo') }) - it('.diag.sys', () => { - return ipfs.diag.sys() - .then((res) => { - expect(res).to.exist() - expect(res).to.have.a.property('memory') - expect(res).to.have.a.property('diskinfo') - }) - }) + it('.diag.cmds', async () => { + const res = await ipfs.diag.cmds() - it('.diag.cmds', () => { - return ipfs.diag.cmds() - .then((res) => expect(res).to.exist()) + expect(res).to.exist() }) }) }) diff --git a/test/endpoint-config.spec.js b/test/endpoint-config.spec.js index 8ff6532c7..4747df274 100644 --- a/test/endpoint-config.spec.js +++ b/test/endpoint-config.spec.js @@ -17,21 +17,24 @@ describe('.getEndpointConfig', () => { let ipfsd let ipfs - before(function (done) { + before(async function () { this.timeout(20 * 1000) // slow CI - f.spawn({ initOptions: { bits: 1024, profile: 'test' } }, (err, _ipfsd) => { - expect(err).to.not.exist() - ipfsd = _ipfsd - ipfs = ipfsClient(_ipfsd.apiAddr) - done() + ipfsd = await f.spawn({ + initOptions: { + bits: 1024, + profile: 'test' + } }) + ipfs = ipfsClient(ipfsd.apiAddr) }) - after(function (done) { + after(async function () { this.timeout(10 * 1000) - if (!ipfsd) return done() - ipfsd.stop(done) + + if (ipfsd) { + await ipfsd.stop() + } }) it('should return the endpoint configuration', function () { diff --git a/test/files-mfs.spec.js b/test/files-mfs.spec.js index beda9b24a..311659200 100644 --- a/test/files-mfs.spec.js +++ b/test/files-mfs.spec.js @@ -4,8 +4,10 @@ const chai = require('chai') const dirtyChai = require('dirty-chai') +const chaiAsPromised = require('chai-as-promised') const expect = chai.expect chai.use(dirtyChai) +chai.use(chaiAsPromised) const loadFixture = require('aegir/fixtures') const mh = require('multihashes') const CID = require('cids') @@ -39,136 +41,109 @@ describe('.files (the MFS API part)', function () { const expectedMultihash = 'Qma4hjFTnCasJ8PVp3mZbZK5g2vGDT4LByLJ7m8ciyRFZP' - before((done) => { - f.spawn({ initOptions: { bits: 1024, profile: 'test' } }, (err, _ipfsd) => { - expect(err).to.not.exist() - ipfsd = _ipfsd - ipfs = ipfsClient(_ipfsd.apiAddr) - done() + before(async () => { + ipfsd = await f.spawn({ + initOptions: { + bits: 1024, + profile: 'test' + } }) + ipfs = ipfsClient(ipfsd.apiAddr) }) - after((done) => { - if (!ipfsd) return done() - ipfsd.stop(done) + after(async () => { + if (ipfsd) { + await ipfsd.stop() + } }) - it('.add file for testing', (done) => { - ipfs.add(testfile, (err, res) => { - expect(err).to.not.exist() + it('.add file for testing', async () => { + const res = await ipfs.add(testfile) - expect(res).to.have.length(1) - expect(res[0].hash).to.equal(expectedMultihash) - expect(res[0].path).to.equal(expectedMultihash) - done() - }) + expect(res).to.have.length(1) + expect(res[0].hash).to.equal(expectedMultihash) + expect(res[0].path).to.equal(expectedMultihash) }) - it('.add with Buffer module', (done) => { + it('.add with Buffer module', async () => { const { Buffer } = require('buffer') const expectedBufferMultihash = 'QmWfVY9y3xjsixTgbd9AorQxH7VtMpzfx2HaWtsoUYecaX' const file = Buffer.from('hello') - ipfs.add(file, (err, res) => { - expect(err).to.not.exist() + const res = await ipfs.add(file) - expect(res).to.have.length(1) - expect(res[0].hash).to.equal(expectedBufferMultihash) - expect(res[0].path).to.equal(expectedBufferMultihash) - done() - }) + expect(res).to.have.length(1) + expect(res[0].hash).to.equal(expectedBufferMultihash) + expect(res[0].path).to.equal(expectedBufferMultihash) }) - it('.add with empty path and buffer content', (done) => { + it('.add with empty path and buffer content', async () => { const expectedHash = 'QmWfVY9y3xjsixTgbd9AorQxH7VtMpzfx2HaWtsoUYecaX' const content = Buffer.from('hello') - ipfs.add([{ path: '', content }], (err, res) => { - expect(err).to.not.exist() + const res = await ipfs.add([{ path: '', content }]) - expect(res).to.have.length(1) - expect(res[0].hash).to.equal(expectedHash) - expect(res[0].path).to.equal(expectedHash) - done() - }) + expect(res).to.have.length(1) + expect(res[0].hash).to.equal(expectedHash) + expect(res[0].path).to.equal(expectedHash) }) - it('.add with cid-version=1 and raw-leaves=false', (done) => { + it('.add with cid-version=1 and raw-leaves=false', async () => { const expectedCid = 'bafybeifogzovjqrcxvgt7g36y7g63hvwvoakledwk4b2fr2dl4wzawpnny' const options = { 'cid-version': 1, 'raw-leaves': false } - ipfs.add(testfile, options, (err, res) => { - expect(err).to.not.exist() + const res = await ipfs.add(testfile, options) - expect(res).to.have.length(1) - expect(res[0].hash).to.equal(expectedCid) - expect(res[0].path).to.equal(expectedCid) - done() - }) + expect(res).to.have.length(1) + expect(res[0].hash).to.equal(expectedCid) + expect(res[0].path).to.equal(expectedCid) }) - it('.add with only-hash=true', function () { + it('.add with only-hash=true', async () => { const content = String(Math.random() + Date.now()) - return ipfs.add(Buffer.from(content), { onlyHash: true }) - .then(files => { - expect(files).to.have.length(1) + const files = await ipfs.add(Buffer.from(content), { onlyHash: true }) + expect(files).to.have.length(1) - // 'ipfs.object.get()' should timeout because content wasn't actually added - return expectTimeout(ipfs.object.get(files[0].hash), 4000) - }) + // 'ipfs.object.get()' should timeout because content wasn't actually added + await expectTimeout(ipfs.object.get(files[0].hash), 4000) }) - it('.add with options', (done) => { - ipfs.add(testfile, { pin: false }, (err, res) => { - expect(err).to.not.exist() + it('.add with options', async () => { + const res = await ipfs.add(testfile, { pin: false }) - expect(res).to.have.length(1) - expect(res[0].hash).to.equal(expectedMultihash) - expect(res[0].path).to.equal(expectedMultihash) - done() - }) + expect(res).to.have.length(1) + expect(res[0].hash).to.equal(expectedMultihash) + expect(res[0].path).to.equal(expectedMultihash) }) - it('.add pins by default', (done) => { + it('.add pins by default', async () => { const newContent = Buffer.from(String(Math.random())) - ipfs.pin.ls((err, pins) => { - expect(err).to.not.exist() - const initialPinCount = pins.length - ipfs.add(newContent, (err, res) => { - expect(err).to.not.exist() + const initialPins = await ipfs.pin.ls() - ipfs.pin.ls((err, pins) => { - expect(err).to.not.exist() - expect(pins.length).to.eql(initialPinCount + 1) - done() - }) - }) - }) + await ipfs.add(newContent) + + const pinsAfterAdd = await ipfs.pin.ls() + + expect(pinsAfterAdd.length).to.eql(initialPins.length + 1) }) - it('.add with pin=false', (done) => { + it('.add with pin=false', async () => { const newContent = Buffer.from(String(Math.random())) - ipfs.pin.ls((err, pins) => { - expect(err).to.not.exist() - const initialPinCount = pins.length - ipfs.add(newContent, { pin: false }, (err, res) => { - expect(err).to.not.exist() + const initialPins = await ipfs.pin.ls() - ipfs.pin.ls((err, pins) => { - expect(err).to.not.exist() - expect(pins.length).to.eql(initialPinCount) - done() - }) - }) - }) + await ipfs.add(newContent, { pin: false }) + + const pinsAfterAdd = await ipfs.pin.ls() + + expect(pinsAfterAdd.length).to.eql(initialPins.length) }) HASH_ALGS.forEach((name) => { - it(`.add with hash=${name} and raw-leaves=false`, (done) => { + it(`.add with hash=${name} and raw-leaves=false`, async () => { const content = String(Math.random() + Date.now()) const file = { path: content + '.txt', @@ -176,17 +151,15 @@ describe('.files (the MFS API part)', function () { } const options = { hash: name, 'raw-leaves': false } - ipfs.add([file], options, (err, res) => { - if (err) return done(err) - expect(res).to.have.length(1) - const cid = new CID(res[0].hash) - expect(mh.decode(cid.multihash).name).to.equal(name) - done() - }) + const res = await ipfs.add([file], options) + + expect(res).to.have.length(1) + const cid = new CID(res[0].hash) + expect(mh.decode(cid.multihash).name).to.equal(name) }) }) - it('.add file with progress option', (done) => { + it('.add file with progress option', async () => { let progress let progressCount = 0 @@ -195,18 +168,14 @@ describe('.files (the MFS API part)', function () { progress = p } - ipfs.add(testfile, { progress: progressHandler }, (err, res) => { - expect(err).to.not.exist() - - expect(res).to.have.length(1) - expect(progress).to.be.equal(testfile.byteLength) - expect(progressCount).to.be.equal(1) + const res = await ipfs.add(testfile, { progress: progressHandler }) - done() - }) + expect(res).to.have.length(1) + expect(progress).to.be.equal(testfile.byteLength) + expect(progressCount).to.be.equal(1) }) - it('.add big file with progress option', (done) => { + it('.add big file with progress option', async () => { let progress = 0 let progressCount = 0 @@ -216,18 +185,14 @@ describe('.files (the MFS API part)', function () { } // TODO: needs to be using a big file - ipfs.add(testfile, { progress: progressHandler }, (err, res) => { - expect(err).to.not.exist() - - expect(res).to.have.length(1) - expect(progress).to.be.equal(testfile.byteLength) - expect(progressCount).to.be.equal(1) + const res = await ipfs.add(testfile, { progress: progressHandler }) - done() - }) + expect(res).to.have.length(1) + expect(progress).to.be.equal(testfile.byteLength) + expect(progressCount).to.be.equal(1) }) - it('.add directory with progress option', (done) => { + it('.add directory with progress option', async () => { let progress = 0 let progressCount = 0 @@ -237,28 +202,21 @@ describe('.files (the MFS API part)', function () { } // TODO: needs to be using a directory - ipfs.add(testfile, { progress: progressHandler }, (err, res) => { - expect(err).to.not.exist() - - expect(res).to.have.length(1) - expect(progress).to.be.equal(testfile.byteLength) - expect(progressCount).to.be.equal(1) + const res = await ipfs.add(testfile, { progress: progressHandler }) - done() - }) + expect(res).to.have.length(1) + expect(progress).to.be.equal(testfile.byteLength) + expect(progressCount).to.be.equal(1) }) - it('.add without progress options', (done) => { - ipfs.add(testfile, (err, res) => { - expect(err).to.not.exist() + it('.add without progress options', async () => { + const res = await ipfs.add(testfile) - expect(res).to.have.length(1) - done() - }) + expect(res).to.have.length(1) }) HASH_ALGS.forEach((name) => { - it(`.add with hash=${name} and raw-leaves=false`, (done) => { + it(`.add with hash=${name} and raw-leaves=false`, async () => { const content = String(Math.random() + Date.now()) const file = { path: content + '.txt', @@ -266,14 +224,11 @@ describe('.files (the MFS API part)', function () { } const options = { hash: name, 'raw-leaves': false } - ipfs.add([file], options, (err, res) => { - expect(err).to.not.exist() + const res = await ipfs.add([file], options) - expect(res).to.have.length(1) - const cid = new CID(res[0].hash) - expect(mh.decode(cid.multihash).name).to.equal(name) - done() - }) + expect(res).to.have.length(1) + const cid = new CID(res[0].hash) + expect(mh.decode(cid.multihash).name).to.equal(name) }) }) @@ -293,200 +248,170 @@ describe('.files (the MFS API part)', function () { ) }) - it('.add with pull stream (callback)', (done) => { - const expectedCid = 'QmRf22bZar3WKmojipms22PkXH1MZGmvsqzQtuSvQE3uhm' - - ipfs.add(values([Buffer.from('test')]), (err, res) => { - expect(err).to.not.exist() - - expect(res).to.have.length(1) - expect(res[0]).to.deep.equal({ path: expectedCid, hash: expectedCid, size: 12 }) - done() - }) - }) - - it('.add with pull stream (promise)', () => { + it('.add with pull stream', async () => { const expectedCid = 'QmRf22bZar3WKmojipms22PkXH1MZGmvsqzQtuSvQE3uhm' + const res = await ipfs.add(values([Buffer.from('test')])) - return ipfs.add(values([Buffer.from('test')])) - .then((res) => { - expect(res).to.have.length(1) - expect(res[0]).to.deep.equal({ path: expectedCid, hash: expectedCid, size: 12 }) - }) + expect(res).to.have.length(1) + expect(res[0]).to.deep.equal({ path: expectedCid, hash: expectedCid, size: 12 }) }) - it('.add with array of objects with pull stream content', () => { + it('.add with array of objects with pull stream content', async () => { const expectedCid = 'QmRf22bZar3WKmojipms22PkXH1MZGmvsqzQtuSvQE3uhm' + const res = await ipfs.add([{ content: values([Buffer.from('test')]) }]) - return ipfs.add([{ content: values([Buffer.from('test')]) }]) - .then((res) => { - expect(res).to.have.length(1) - expect(res[0]).to.eql({ path: expectedCid, hash: expectedCid, size: 12 }) - }) + expect(res).to.have.length(1) + expect(res[0]).to.eql({ path: expectedCid, hash: expectedCid, size: 12 }) }) - it('files.mkdir', (done) => { - ipfs.files.mkdir('/test-folder', done) + it('files.mkdir', async () => { + await ipfs.files.mkdir('/test-folder') }) - it('files.flush', (done) => { - ipfs.files.flush('/', done) + it('files.flush', async () => { + await ipfs.files.flush('/') }) - it('files.cp', () => { + it('files.cp', async () => { const folder = `/test-folder-${Math.random()}` - return ipfs.files.mkdir(folder) - .then(() => ipfs.files.cp([ - '/ipfs/Qma4hjFTnCasJ8PVp3mZbZK5g2vGDT4LByLJ7m8ciyRFZP', - `${folder}/test-file-${Math.random()}` - ])) + await ipfs.files.mkdir(folder) + await ipfs.files.cp([ + '/ipfs/Qma4hjFTnCasJ8PVp3mZbZK5g2vGDT4LByLJ7m8ciyRFZP', + `${folder}/test-file-${Math.random()}` + ]) }) - it('files.cp with non-array arguments', () => { + it('files.cp with non-array arguments', async () => { const folder = `/test-folder-${Math.random()}` - return ipfs.files.mkdir(folder) - .then(() => ipfs.files.cp( - '/ipfs/Qma4hjFTnCasJ8PVp3mZbZK5g2vGDT4LByLJ7m8ciyRFZP', - `${folder}/test-file-${Math.random()}` - )) + await ipfs.files.mkdir(folder) + await ipfs.files.cp( + '/ipfs/Qma4hjFTnCasJ8PVp3mZbZK5g2vGDT4LByLJ7m8ciyRFZP', + `${folder}/test-file-${Math.random()}` + ) }) - it('files.mv', () => { + it('files.mv', async () => { const folder = `/test-folder-${Math.random()}` const source = `${folder}/test-file-${Math.random()}` const dest = `${folder}/test-file-${Math.random()}` - return ipfs.files.mkdir(folder) - .then(() => ipfs.files.cp( - '/ipfs/Qma4hjFTnCasJ8PVp3mZbZK5g2vGDT4LByLJ7m8ciyRFZP', - source - )) - .then(() => ipfs.files.mv([ - source, - dest - ])) + await ipfs.files.mkdir(folder) + await ipfs.files.cp( + '/ipfs/Qma4hjFTnCasJ8PVp3mZbZK5g2vGDT4LByLJ7m8ciyRFZP', + source + ) + await ipfs.files.mv([ + source, + dest + ]) }) - it('files.mv with non-array arguments', () => { + it('files.mv with non-array arguments', async () => { const folder = `/test-folder-${Math.random()}` const source = `${folder}/test-file-${Math.random()}` const dest = `${folder}/test-file-${Math.random()}` - return ipfs.files.mkdir(folder) - .then(() => ipfs.files.cp( - '/ipfs/Qma4hjFTnCasJ8PVp3mZbZK5g2vGDT4LByLJ7m8ciyRFZP', - source - )) - .then(() => ipfs.files.mv( - source, - dest - )) + await ipfs.files.mkdir(folder) + await ipfs.files.cp( + '/ipfs/Qma4hjFTnCasJ8PVp3mZbZK5g2vGDT4LByLJ7m8ciyRFZP', + source + ) + await ipfs.files.mv( + source, + dest + ) }) - it('files.ls', () => { + it('files.ls', async () => { const folder = `/test-folder-${Math.random()}` const file = `${folder}/test-file-${Math.random()}` - return ipfs.files.mkdir(folder) - .then(() => ipfs.files.write(file, Buffer.from('Hello, world'), { - create: true - })) - .then(() => ipfs.files.ls(folder)) - .then(files => { - expect(files.length).to.equal(1) - }) + await ipfs.files.mkdir(folder) + await ipfs.files.write(file, Buffer.from('Hello, world'), { + create: true + }) + const files = await ipfs.files.ls(folder) + + expect(files.length).to.equal(1) }) - it('files.ls mfs root by default', () => { + it('files.ls mfs root by default', async () => { const folder = `test-folder-${Math.random()}` - return ipfs.files.mkdir(`/${folder}`) - .then(() => ipfs.files.ls()) - .then(files => { - expect(files.find(file => file.name === folder)).to.be.ok() - }) + await ipfs.files.mkdir(`/${folder}`) + const files = await ipfs.files.ls() + + expect(files.find(file => file.name === folder)).to.be.ok() }) - it('files.write', (done) => { - ipfs.files - .write('/test-folder/test-file-2.txt', Buffer.from('hello world'), { create: true }, (err) => { - expect(err).to.not.exist() + it('files.write', async () => { + await ipfs.files.write('/test-folder/test-file-2.txt', Buffer.from('hello world'), { + create: true + }) - ipfs.files.read('/test-folder/test-file-2.txt', (err, buf) => { - expect(err).to.not.exist() - expect(buf.toString()).to.be.equal('hello world') - done() - }) - }) + const buf = await ipfs.files.read('/test-folder/test-file-2.txt') + + expect(buf.toString()).to.be.equal('hello world') }) - it('files.write without options', (done) => { - ipfs.files - .write('/test-folder/test-file-2.txt', Buffer.from('hello world'), (err) => { - expect(err).to.not.exist() + it('files.write without options', async () => { + await ipfs.files.write('/test-folder/test-file-2.txt', Buffer.from('hello world')) - ipfs.files.read('/test-folder/test-file-2.txt', (err, buf) => { - expect(err).to.not.exist() - expect(buf.toString()).to.be.equal('hello world') - done() - }) - }) + const buf = await ipfs.files.read('/test-folder/test-file-2.txt') + + expect(buf.toString()).to.be.equal('hello world') }) - it('files.stat', () => { + it('files.stat', async () => { const folder = `/test-folder-${Math.random()}` const file = `${folder}/test-file-${Math.random()}` - return ipfs.files.mkdir(folder) - .then(() => ipfs.files.write(file, testfile, { - create: true - })) - .then(() => ipfs.files.stat(file)) - .then((stats) => { - expect(stats).to.deep.equal({ - hash: 'QmQhouoDPAnzhVM148yCa9CbUXK65wSEAZBtgrLGHtmdmP', - size: 12, - cumulativeSize: 70, - blocks: 1, - type: 'file', - withLocality: false, - local: undefined, - sizeLocal: undefined - }) - }) - }) + await ipfs.files.mkdir(folder) + await ipfs.files.write(file, testfile, { + create: true + }) - it('files.stat file that does not exist()', (done) => { - ipfs.files.stat('/test-folder/does-not-exist()', (err, res) => { - expect(err).to.exist() - expect(err.code).to.equal(0) - expect(err.type).to.equal('error') + const stats = await ipfs.files.stat(file) + + expect(stats).to.deep.equal({ + hash: 'QmQhouoDPAnzhVM148yCa9CbUXK65wSEAZBtgrLGHtmdmP', + size: 12, + cumulativeSize: 70, + blocks: 1, + type: 'file', + withLocality: false, + local: undefined, + sizeLocal: undefined + }) + }) - done() + it('files.stat file that does not exist()', async () => { + await expect(ipfs.files.stat('/test-folder/does-not-exist()')).to.be.rejectedWith({ + code: 0, + type: 'error' }) }) - it('files.read', () => { + it('files.read', async () => { const folder = `/test-folder-${Math.random()}` const file = `${folder}/test-file-${Math.random()}` - return ipfs.files.mkdir(folder) - .then(() => ipfs.files.write(file, testfile, { - create: true - })) - .then(() => ipfs.files.read(file)) - .then((buf) => { - expect(Buffer.from(buf)).to.deep.equal(testfile) - }) + await ipfs.files.mkdir(folder) + await ipfs.files.write(file, testfile, { + create: true + }) + const buf = await ipfs.files.read(file) + + expect(Buffer.from(buf)).to.deep.equal(testfile) }) - it('files.rm without options', (done) => { - ipfs.files.rm('/test-folder/test-file-2.txt', done) + it('files.rm without options', async () => { + await ipfs.files.rm('/test-folder/test-file-2.txt') }) - it('files.rm', (done) => { - ipfs.files.rm('/test-folder', { recursive: true }, done) + it('files.rm', async () => { + await ipfs.files.rm('/test-folder', { recursive: true }) }) }) diff --git a/test/get.spec.js b/test/get.spec.js index 2c5adb6d9..acdcf833b 100644 --- a/test/get.spec.js +++ b/test/get.spec.js @@ -5,17 +5,18 @@ const chai = require('chai') const dirtyChai = require('dirty-chai') +const chaiAsPromised = require('chai-as-promised') const expect = chai.expect chai.use(dirtyChai) +chai.use(chaiAsPromised) const isNode = require('detect-node') -const series = require('async/series') const loadFixture = require('aegir/fixtures') const ipfsClient = require('../src') const f = require('./utils/factory') describe('.get (specific go-ipfs features)', function () { - this.timeout(20 * 1000) + this.timeout(60 * 1000) function fixture (path) { return loadFixture(path, 'interface-ipfs-core') @@ -29,89 +30,84 @@ describe('.get (specific go-ipfs features)', function () { let ipfsd let ipfs - before(function (done) { - series([ - (cb) => f.spawn({ initOptions: { bits: 1024, profile: 'test' } }, (err, _ipfsd) => { - expect(err).to.not.exist() - ipfsd = _ipfsd - ipfs = ipfsClient(_ipfsd.apiAddr) - cb() - }), - (cb) => ipfs.add(smallFile.data, cb) - ], done) + before(async () => { + ipfsd = await f.spawn({ + initOptions: { + bits: 1024, + profile: 'test' + } + }) + ipfs = ipfsClient(ipfsd.apiAddr) + + await ipfs.add(smallFile.data) }) - after((done) => { - if (!ipfsd) { return done() } - ipfsd.stop(done) + after(async () => { + if (ipfsd) { + await ipfsd.stop() + } }) - it('no compression args', (done) => { - ipfs.get(smallFile.cid, (err, files) => { - expect(err).to.not.exist() + it('no compression args', async () => { + const files = await ipfs.get(smallFile.cid) - expect(files).to.be.length(1) - expect(files[0].content.toString()).to.contain(smallFile.data.toString()) - done() - }) + expect(files).to.be.length(1) + expect(files[0].content.toString()).to.contain(smallFile.data.toString()) }) - it('archive true', (done) => { - ipfs.get(smallFile.cid, { archive: true }, (err, files) => { - expect(err).to.not.exist() + it('archive true', async () => { + const files = await ipfs.get(smallFile.cid, { archive: true }) - expect(files).to.be.length(1) - expect(files[0].content.toString()).to.contain(smallFile.data.toString()) - done() - }) + expect(files).to.be.length(1) + expect(files[0].content.toString()).to.contain(smallFile.data.toString()) }) - it('err with out of range compression level', (done) => { - ipfs.get(smallFile.cid, { + it('err with out of range compression level', async () => { + await expect(ipfs.get(smallFile.cid, { compress: true, 'compression-level': 10 - }, (err, files) => { - expect(err).to.exist() - expect(err.toString()).to.equal('Error: compression level must be between 1 and 9') - done() - }) + })).to.be.rejectedWith('compression level must be between 1 and 9') }) // TODO Understand why this test started failing - it.skip('with compression level', (done) => { - ipfs.get(smallFile.cid, { compress: true, 'compression-level': 1 }, done) + it.skip('with compression level', async () => { + await ipfs.get(smallFile.cid, { compress: true, 'compression-level': 1 }) }) - it('add path containing "+"s (for testing get)', (done) => { - if (!isNode) { return done() } + it('add path containing "+"s (for testing get)', async () => { + if (!isNode) { + return + } const filename = 'ti,c64x+mega++mod-pic.txt' const subdir = 'tmp/c++files' const expectedCid = 'QmPkmARcqjo5fqK1V1o8cFsuaXxWYsnwCNLJUYS4KeZyff' - ipfs.add([{ + const files = await ipfs.add([{ path: subdir + '/' + filename, content: Buffer.from(subdir + '/' + filename, 'utf-8') - }], (err, files) => { - expect(err).to.not.exist() - expect(files[2].hash).to.equal(expectedCid) - done() - }) + }]) + + expect(files[2].hash).to.equal(expectedCid) }) - it('get path containing "+"s', (done) => { - if (!isNode) { return done() } + it('get path containing "+"s', async () => { + if (!isNode) { + return + } const cid = 'QmPkmARcqjo5fqK1V1o8cFsuaXxWYsnwCNLJUYS4KeZyff' let count = 0 - ipfs.get(cid, (err, files) => { - expect(err).to.not.exist() - files.forEach((file) => { - if (file.path !== cid) { - count++ - expect(file.path).to.contain('+') - if (count === 2) done() + const files = await ipfs.get(cid) + + files.forEach((file) => { + if (file.path !== cid) { + count++ + expect(file.path).to.contain('+') + + if (count === 2) { + // done() } - }) + } }) }) }) diff --git a/test/interface.spec.js b/test/interface.spec.js index 86ffac21d..fb54c422b 100644 --- a/test/interface.spec.js +++ b/test/interface.spec.js @@ -304,14 +304,11 @@ describe('interface-ipfs-core tests', () => { const spawnOptions = { repoPath, config, initOptions: { bits: 1024, profile: 'test' } } - ipfsFactory.spawn(spawnOptions, (err, _ipfsd) => { - if (err) { - return cb(err) - } - - nodes.push(_ipfsd) - cb(null, ipfsClient(_ipfsd.apiAddr)) - }) + ipfsFactory.spawn(spawnOptions) + .then(ipfsd => { + nodes.push(ipfsd) + cb(null, ipfsClient(ipfsd.apiAddr)) + }, cb) } }) } diff --git a/test/key.spec.js b/test/key.spec.js index 8ed35d42b..b332b91ba 100644 --- a/test/key.spec.js +++ b/test/key.spec.js @@ -16,73 +16,42 @@ describe('.key', function () { let ipfsd let ipfs - before((done) => { - f.spawn({ initOptions: { bits: 1024, profile: 'test' } }, (err, _ipfsd) => { - expect(err).to.not.exist() - ipfsd = _ipfsd - ipfs = ipfsClient(_ipfsd.apiAddr) - done() + before(async () => { + ipfsd = await f.spawn({ + initOptions: { + bits: 1024, + profile: 'test' + } }) + ipfs = ipfsClient(ipfsd.apiAddr) }) - after((done) => { - if (!ipfsd) return done() - ipfsd.stop(done) + after(async () => { + if (ipfsd) { + await ipfsd.stop() + } }) - describe('Callback API', () => { - describe('.gen', () => { - it('create a new rsa key', (done) => { - ipfs.key.gen('foobarsa', { type: 'rsa', size: 2048 }, (err, res) => { - expect(err).to.not.exist() - expect(res).to.exist() - done() - }) - }) + describe('.gen', () => { + it('create a new rsa key', async () => { + const res = await ipfs.key.gen('foobarsa', { type: 'rsa', size: 2048 }) - it('create a new ed25519 key', (done) => { - ipfs.key.gen('bazed', { type: 'ed25519' }, (err, res) => { - expect(err).to.not.exist() - expect(res).to.exist() - done() - }) - }) + expect(res).to.exist() }) - describe('.list', () => { - it('both keys show up + self', (done) => { - ipfs.key.list((err, res) => { - expect(err).to.not.exist() - expect(res).to.exist() - expect(res.length).to.equal(3) - done() - }) - }) + it('create a new ed25519 key', async () => { + const res = await ipfs.key.gen('bazed', { type: 'ed25519' }) + + expect(res).to.exist() }) }) - describe('Promise API', () => { - describe('.gen', () => { - it('create a new rsa key', () => { - return ipfs.key.gen('foobarsa2', { type: 'rsa', size: 2048 }).then((res) => { - expect(res).to.exist() - }) - }) - - it('create a new ed25519 key', () => { - return ipfs.key.gen('bazed2', { type: 'ed25519' }).then((res) => { - expect(res).to.exist() - }) - }) - }) + describe('.list', () => { + it('both keys show up + self', async () => { + const res = await ipfs.key.list() - describe('.list', () => { - it('4 keys to show up + self', () => { - return ipfs.key.list().then((res) => { - expect(res).to.exist() - expect(res.length).to.equal(5) - }) - }) + expect(res).to.exist() + expect(res.length).to.equal(3) }) }) }) diff --git a/test/log.spec.js b/test/log.spec.js index 1e800f075..73ff556e2 100644 --- a/test/log.spec.js +++ b/test/log.spec.js @@ -16,58 +16,60 @@ describe('.log', function () { let ipfsd let ipfs - before((done) => { - f.spawn({ initOptions: { bits: 1024, profile: 'test' } }, (err, _ipfsd) => { - expect(err).to.not.exist() - ipfsd = _ipfsd - ipfs = ipfsClient(_ipfsd.apiAddr) - done() + before(async () => { + ipfsd = await f.spawn({ + initOptions: { + bits: 1024, + profile: 'test' + } }) + ipfs = ipfsClient(ipfsd.apiAddr) }) - after((done) => { - if (!ipfsd) return done() - ipfsd.stop(done) + after(async () => { + if (ipfsd) { + await ipfsd.stop() + } }) - it('.log.tail', (done) => { - const i = setInterval(() => { - ipfs.add(Buffer.from('just adding some data to generate logs')) + it('.log.tail', async () => { + const i = setInterval(async () => { + try { + await ipfs.add(Buffer.from('just adding some data to generate logs')) + } catch (_) { + // this can error if the test has finished and we're shutting down the node + } }, 1000) - const req = ipfs.log.tail((err, res) => { - expect(err).to.not.exist() - expect(req).to.exist() + const res = await ipfs.log.tail() + + return new Promise((resolve, reject) => { + res.on('error', (err) => { + reject(err) + }) res.once('data', (obj) => { clearInterval(i) expect(obj).to.be.an('object') - done() + res.end() + resolve() }) }) }) - it('.log.ls', (done) => { - ipfs.log.ls((err, res) => { - expect(err).to.not.exist() - expect(res).to.exist() - - expect(res).to.be.an('array') + it('.log.ls', async () => { + const res = await ipfs.log.ls() - done() - }) + expect(res).to.exist() + expect(res).to.be.an('array') }) - it('.log.level', (done) => { - ipfs.log.level('all', 'error', (err, res) => { - expect(err).to.not.exist() - expect(res).to.exist() - - expect(res).to.be.an('object') - expect(res).to.not.have.property('Error') - expect(res).to.have.property('Message') + it('.log.level', async () => { + const res = await ipfs.log.level('all', 'error') - done() - }) + expect(res).to.exist() + expect(res).to.be.an('object') + expect(res).to.not.have.property('Error') + expect(res).to.have.property('Message') }) }) diff --git a/test/node/swarm.js b/test/node/swarm.js index 0ba0fe73f..3ec634aea 100644 --- a/test/node/swarm.js +++ b/test/node/swarm.js @@ -4,8 +4,10 @@ const nock = require('nock') const chai = require('chai') const dirtyChai = require('dirty-chai') +const chaiAsPromised = require('chai-as-promised') const expect = chai.expect chai.use(dirtyChai) +chai.use(chaiAsPromised) const ipfsClient = require('../../src') @@ -15,7 +17,7 @@ describe('.swarm.peers', function () { const ipfs = ipfsClient('/ip4/127.0.0.1/tcp/5001') const apiUrl = 'http://127.0.0.1:5001' - it('handles a peer response', (done) => { + it('handles a peer response', async () => { const response = { Peers: [{ Addr: '/ip4/104.131.131.82/tcp/4001', Peer: 'QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ', Latency: '', Muxer: '', Streams: null }] } const scope = nock(apiUrl) @@ -23,19 +25,17 @@ describe('.swarm.peers', function () { .query(true) .reply(200, response) - ipfs.swarm.peers((err, res) => { - expect(err).to.not.exist() - expect(res).to.be.a('array') - expect(res.length).to.equal(1) - expect(res[0].error).to.not.exist() - expect(res[0].addr.toString()).to.equal(response.Peers[0].Addr) - expect(res[0].peer.toB58String()).to.equal(response.Peers[0].Peer) - expect(scope.isDone()).to.equal(true) - done() - }) + const res = await ipfs.swarm.peers() + + expect(res).to.be.a('array') + expect(res.length).to.equal(1) + expect(res[0].error).to.not.exist() + expect(res[0].addr.toString()).to.equal(response.Peers[0].Addr) + expect(res[0].peer.toB58String()).to.equal(response.Peers[0].Peer) + expect(scope.isDone()).to.equal(true) }) - it('handles a go-ipfs <= 0.4.4 peer response', (done) => { + it('handles a go-ipfs <= 0.4.4 peer response', async () => { const response = { Strings: ['/ip4/73.109.217.59/tcp/49311/ipfs/QmWjxEGC7BthJrCf7QTModrcsRweHbupdPTY4oGMVoDZXm'] } const scope = nock(apiUrl) @@ -43,19 +43,17 @@ describe('.swarm.peers', function () { .query(true) .reply(200, response) - ipfs.swarm.peers((err, res) => { - expect(err).to.not.exist() - expect(res).to.be.a('array') - expect(res.length).to.equal(1) - expect(res[0].error).to.not.exist() - expect(res[0].addr.toString()).to.equal('/ip4/73.109.217.59/tcp/49311/ipfs/QmWjxEGC7BthJrCf7QTModrcsRweHbupdPTY4oGMVoDZXm') - expect(res[0].peer.toB58String()).to.equal('QmWjxEGC7BthJrCf7QTModrcsRweHbupdPTY4oGMVoDZXm') - expect(scope.isDone()).to.equal(true) - done() - }) + const res = await ipfs.swarm.peers() + + expect(res).to.be.a('array') + expect(res.length).to.equal(1) + expect(res[0].error).to.not.exist() + expect(res[0].addr.toString()).to.equal('/ip4/73.109.217.59/tcp/49311/ipfs/QmWjxEGC7BthJrCf7QTModrcsRweHbupdPTY4oGMVoDZXm') + expect(res[0].peer.toB58String()).to.equal('QmWjxEGC7BthJrCf7QTModrcsRweHbupdPTY4oGMVoDZXm') + expect(scope.isDone()).to.equal(true) }) - it('handles an ip6 quic peer', (done) => { + it('handles an ip6 quic peer', async () => { const response = { Peers: [{ Addr: '/ip6/2001:8a0:7ac5:4201:3ac9:86ff:fe31:7095/udp/4001/quic', Peer: 'QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC', Latency: '', Muxer: '', Streams: null }] } const scope = nock(apiUrl) @@ -63,19 +61,17 @@ describe('.swarm.peers', function () { .query(true) .reply(200, response) - ipfs.swarm.peers((err, res) => { - expect(err).to.not.exist() - expect(res).to.be.a('array') - expect(res.length).to.equal(1) - expect(res[0].error).to.not.exist() - expect(res[0].addr.toString()).to.equal(response.Peers[0].Addr) - expect(res[0].peer.toB58String()).to.equal(response.Peers[0].Peer) - expect(scope.isDone()).to.equal(true) - done() - }) + const res = await ipfs.swarm.peers() + + expect(res).to.be.a('array') + expect(res.length).to.equal(1) + expect(res[0].error).to.not.exist() + expect(res[0].addr.toString()).to.equal(response.Peers[0].Addr) + expect(res[0].peer.toB58String()).to.equal(response.Peers[0].Peer) + expect(scope.isDone()).to.equal(true) }) - it('handles unvalidatable peer addr', (done) => { + it('handles unvalidatable peer addr', async () => { const response = { Peers: [{ Addr: '/ip4/104.131.131.82/future-tech', Peer: 'QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC', Latency: '', Muxer: '', Streams: null }] } const scope = nock(apiUrl) @@ -83,28 +79,23 @@ describe('.swarm.peers', function () { .query(true) .reply(200, response) - ipfs.swarm.peers((err, res) => { - expect(err).to.not.exist() - expect(res).to.be.a('array') - expect(res.length).to.equal(1) - expect(res[0].error).to.exist() - expect(res[0].rawPeerInfo).to.deep.equal(response.Peers[0]) - expect(scope.isDone()).to.equal(true) - done() - }) + const res = await ipfs.swarm.peers() + + expect(res).to.be.a('array') + expect(res.length).to.equal(1) + expect(res[0].error).to.exist() + expect(res[0].rawPeerInfo).to.deep.equal(response.Peers[0]) + expect(scope.isDone()).to.equal(true) }) - it('handles an error response', (done) => { + it('handles an error response', async () => { const scope = nock(apiUrl) .post('/api/v0/swarm/peers') .query(true) .replyWithError('something awful happened') - ipfs.swarm.peers((err, res) => { - expect(err.message).to.equal('something awful happened') - expect(res).to.not.exist() - expect(scope.isDone()).to.equal(true) - done() - }) + await expect(ipfs.swarm.peers()).to.be.rejectedWith('something awful happened') + + expect(scope.isDone()).to.equal(true) }) }) diff --git a/test/ping.spec.js b/test/ping.spec.js index 5f6ecd3ea..da141702c 100644 --- a/test/ping.spec.js +++ b/test/ping.spec.js @@ -3,13 +3,12 @@ const chai = require('chai') const dirtyChai = require('dirty-chai') -const pull = require('pull-stream/pull') -const collect = require('pull-stream/sinks/collect') +const chaiAsPromised = require('chai-as-promised') const expect = chai.expect chai.use(dirtyChai) - -const parallel = require('async/parallel') -const series = require('async/series') +chai.use(chaiAsPromised) +const pull = require('pull-stream/pull') +const collect = require('pull-stream/sinks/collect') const ipfsClient = require('../src') const PingMessageStream = require('../src/utils/ping-message-stream') @@ -29,126 +28,97 @@ describe('.ping', function () { let otherd let otherId - before(function (done) { + before(async function () { this.timeout(30 * 1000) // slow CI - series([ - (cb) => { - f.spawn({ initOptions: { bits: 1024, profile: 'test' } }, (err, _ipfsd) => { - expect(err).to.not.exist() - ipfsd = _ipfsd - ipfs = ipfsClient(_ipfsd.apiAddr) - cb() - }) - }, - (cb) => { - f.spawn({ initOptions: { bits: 1024, profile: 'test' } }, (err, node) => { - expect(err).to.not.exist() - other = node.api - otherd = node - cb() - }) - }, - (cb) => { - parallel([ - (cb) => { - ipfs.id((err, id) => { - expect(err).to.not.exist() - const ma = id.addresses[0] - other.swarm.connect(ma, cb) - }) - }, - (cb) => { - other.id((err, id) => { - expect(err).to.not.exist() - otherId = id.id - cb() - }) - } - ], cb) + ipfsd = await f.spawn({ + initOptions: { + bits: 1024, + profile: 'test' } - ], done) - }) + }) + ipfs = ipfsClient(ipfsd.apiAddr) - after((done) => { - parallel([ - (cb) => { - if (!ipfsd) return cb() - ipfsd.stop(cb) - }, - (cb) => { - if (!otherd) return cb() - otherd.stop(cb) + otherd = await f.spawn({ + initOptions: { + bits: 1024, + profile: 'test' } - ], done) + }) + other = otherd.api + + const ma = (await ipfs.id()).addresses[0] + await other.swarm.connect(ma) + + otherId = (await other.id()).id }) - it('.ping with default n', (done) => { - ipfs.ping(otherId, (err, res) => { - expect(err).to.not.exist() - expect(res).to.be.an('array') - expect(res.filter(isPong)).to.have.lengthOf(1) - res.forEach(packet => { - expect(packet).to.have.keys('success', 'time', 'text') - expect(packet.time).to.be.a('number') - }) - const resultMsg = res.find(packet => packet.text.includes('Average latency')) - expect(resultMsg).to.exist() - done() + after(async () => { + if (ipfsd) { + await ipfsd.stop() + } + + if (otherd) { + await otherd.stop() + } + }) + + it('.ping with default n', async () => { + const res = await ipfs.ping(otherId) + + expect(res).to.be.an('array') + expect(res.filter(isPong)).to.have.lengthOf(1) + res.forEach(packet => { + expect(packet).to.have.keys('success', 'time', 'text') + expect(packet.time).to.be.a('number') }) + + const resultMsg = res.find(packet => packet.text.includes('Average latency')) + expect(resultMsg).to.exist() }) - it('.ping with count = 2', (done) => { - ipfs.ping(otherId, { count: 2 }, (err, res) => { - expect(err).to.not.exist() - expect(res).to.be.an('array') - expect(res.filter(isPong)).to.have.lengthOf(2) - res.forEach(packet => { - expect(packet).to.have.keys('success', 'time', 'text') - expect(packet.time).to.be.a('number') - }) - const resultMsg = res.find(packet => packet.text.includes('Average latency')) - expect(resultMsg).to.exist() - done() + it('.ping with count = 2', async () => { + const res = await ipfs.ping(otherId, { count: 2 }) + + expect(res).to.be.an('array') + expect(res.filter(isPong)).to.have.lengthOf(2) + res.forEach(packet => { + expect(packet).to.have.keys('success', 'time', 'text') + expect(packet.time).to.be.a('number') }) + const resultMsg = res.find(packet => packet.text.includes('Average latency')) + expect(resultMsg).to.exist() }) - it('.ping with n = 2', (done) => { - ipfs.ping(otherId, { n: 2 }, (err, res) => { - expect(err).to.not.exist() - expect(res).to.be.an('array') - expect(res.filter(isPong)).to.have.lengthOf(2) - res.forEach(packet => { - expect(packet).to.have.keys('success', 'time', 'text') - expect(packet.time).to.be.a('number') - }) - const resultMsg = res.find(packet => packet.text.includes('Average latency')) - expect(resultMsg).to.exist() - done() + it('.ping with n = 2', async () => { + const res = await ipfs.ping(otherId, { n: 2 }) + + expect(res).to.be.an('array') + expect(res.filter(isPong)).to.have.lengthOf(2) + res.forEach(packet => { + expect(packet).to.have.keys('success', 'time', 'text') + expect(packet.time).to.be.a('number') }) + const resultMsg = res.find(packet => packet.text.includes('Average latency')) + expect(resultMsg).to.exist() }) - it('.ping fails with count & n', function (done) { + it('.ping fails with count & n', async function () { this.timeout(20 * 1000) - ipfs.ping(otherId, { count: 2, n: 2 }, (err, res) => { - expect(err).to.exist() - done() - }) + await expect(ipfs.ping(otherId, { count: 2, n: 2 })).to.be.rejected() }) - it('.ping with Promises', () => { - return ipfs.ping(otherId) - .then((res) => { - expect(res).to.be.an('array') - expect(res.filter(isPong)).to.have.lengthOf(1) - res.forEach(packet => { - expect(packet).to.have.keys('success', 'time', 'text') - expect(packet.time).to.be.a('number') - }) - const resultMsg = res.find(packet => packet.text.includes('Average latency')) - expect(resultMsg).to.exist() - }) + it('.ping with Promises', async () => { + const res = await ipfs.ping(otherId) + expect(res).to.be.an('array') + expect(res.filter(isPong)).to.have.lengthOf(1) + res.forEach(packet => { + expect(packet).to.have.keys('success', 'time', 'text') + expect(packet.time).to.be.a('number') + }) + const resultMsg = res.find(packet => packet.text.includes('Average latency')) + expect(resultMsg).to.exist() }) it('.pingPullStream', (done) => { diff --git a/test/repo.spec.js b/test/repo.spec.js index e01868810..c6306f5af 100644 --- a/test/repo.spec.js +++ b/test/repo.spec.js @@ -15,43 +15,39 @@ describe('.repo', function () { let ipfs let ipfsd - before((done) => { - f.spawn({ initOptions: { bits: 1024, profile: 'test' } }, (err, _ipfsd) => { - expect(err).to.not.exist() - ipfsd = _ipfsd - ipfs = ipfsClient(_ipfsd.apiAddr) - done() + before(async () => { + ipfsd = await f.spawn({ + initOptions: { + bits: 1024, + profile: 'test' + } }) + ipfs = ipfsClient(ipfsd.apiAddr) }) - after((done) => { - if (!ipfsd) return done() - ipfsd.stop(done) + after(async () => { + if (ipfsd) { + await ipfsd.stop() + } }) - it('.repo.gc', (done) => { - ipfs.repo.gc((err, res) => { - expect(err).to.not.exist() - expect(res).to.exist() - done() - }) + it('.repo.gc', async () => { + const res = await ipfs.repo.gc() + + expect(res).to.exist() }) - it('.repo.stat', (done) => { - ipfs.repo.stat((err, res) => { - expect(err).to.not.exist() - expect(res).to.exist() - expect(res).to.have.a.property('numObjects') - expect(res).to.have.a.property('repoSize') - done() - }) + it('.repo.stat', async () => { + const res = await ipfs.repo.stat() + + expect(res).to.exist() + expect(res).to.have.a.property('numObjects') + expect(res).to.have.a.property('repoSize') }) - it('.repo.version', (done) => { - ipfs.repo.version((err, res) => { - expect(err).to.not.exist() - expect(res).to.exist() - done() - }) + it('.repo.version', async () => { + const res = await ipfs.repo.version() + + expect(res).to.exist() }) }) diff --git a/test/stats.spec.js b/test/stats.spec.js index 4597e0397..66b76b270 100644 --- a/test/stats.spec.js +++ b/test/stats.spec.js @@ -15,59 +15,55 @@ describe('stats', function () { let ipfs let ipfsd - before((done) => { - f.spawn({ initOptions: { bits: 1024, profile: 'test' } }, (err, _ipfsd) => { - expect(err).to.not.exist() - ipfsd = _ipfsd - ipfs = ipfsClient(_ipfsd.apiAddr) - done() + before(async () => { + ipfsd = await f.spawn({ + initOptions: { + bits: 1024, + profile: 'test' + } }) + ipfs = ipfsClient(ipfsd.apiAddr) }) - after((done) => { - if (!ipfsd) return done() - ipfsd.stop(done) + after(async () => { + if (ipfsd) { + await ipfsd.stop() + } }) - it('.stats.bitswap', (done) => { - ipfs.stats.bitswap((err, res) => { - expect(err).to.not.exist() - expect(res).to.exist() - expect(res).to.have.a.property('provideBufLen') - expect(res).to.have.a.property('wantlist') - expect(res).to.have.a.property('peers') - expect(res).to.have.a.property('blocksReceived') - expect(res).to.have.a.property('dataReceived') - expect(res).to.have.a.property('blocksSent') - expect(res).to.have.a.property('dataSent') - expect(res).to.have.a.property('dupBlksReceived') - expect(res).to.have.a.property('dupDataReceived') - done() - }) + it('.stats.bitswap', async () => { + const res = await ipfs.stats.bitswap() + + expect(res).to.exist() + expect(res).to.have.a.property('provideBufLen') + expect(res).to.have.a.property('wantlist') + expect(res).to.have.a.property('peers') + expect(res).to.have.a.property('blocksReceived') + expect(res).to.have.a.property('dataReceived') + expect(res).to.have.a.property('blocksSent') + expect(res).to.have.a.property('dataSent') + expect(res).to.have.a.property('dupBlksReceived') + expect(res).to.have.a.property('dupDataReceived') }) - it('.stats.bw', (done) => { - ipfs.stats.bw((err, res) => { - expect(err).to.not.exist() - expect(res).to.exist() - expect(res).to.have.a.property('totalIn') - expect(res).to.have.a.property('totalOut') - expect(res).to.have.a.property('rateIn') - expect(res).to.have.a.property('rateOut') - done() - }) + it('.stats.bw', async () => { + const res = await ipfs.stats.bw() + + expect(res).to.exist() + expect(res).to.have.a.property('totalIn') + expect(res).to.have.a.property('totalOut') + expect(res).to.have.a.property('rateIn') + expect(res).to.have.a.property('rateOut') }) - it('.stats.repo', (done) => { - ipfs.stats.repo((err, res) => { - expect(err).to.not.exist() - expect(res).to.exist() - expect(res).to.have.a.property('numObjects') - expect(res).to.have.a.property('repoSize') - expect(res).to.have.a.property('repoPath') - expect(res).to.have.a.property('version') - expect(res).to.have.a.property('storageMax') - done() - }) + it('.stats.repo', async () => { + const res = await ipfs.stats.repo() + + expect(res).to.exist() + expect(res).to.have.a.property('numObjects') + expect(res).to.have.a.property('repoSize') + expect(res).to.have.a.property('repoPath') + expect(res).to.have.a.property('version') + expect(res).to.have.a.property('storageMax') }) }) diff --git a/test/utils/interface-common-factory.js b/test/utils/interface-common-factory.js index ad5010080..6f1cad7ca 100644 --- a/test/utils/interface-common-factory.js +++ b/test/utils/interface-common-factory.js @@ -23,14 +23,11 @@ function createFactory (options) { setup = (callback) => { callback(null, { spawnNode (cb) { - ipfsFactory.spawn(options.spawnOptions, (err, _ipfsd) => { - if (err) { - return cb(err) - } - - nodes.push(_ipfsd) - cb(null, ipfsClient(_ipfsd.apiAddr)) - }) + ipfsFactory.spawn(options.spawnOptions) + .then((ipfsd) => { + nodes.push(ipfsd) + cb(null, ipfsClient(ipfsd.apiAddr)) + }, cb) } }) } @@ -39,7 +36,7 @@ function createFactory (options) { if (options.createTeardown) { teardown = options.createTeardown({ ipfsFactory, nodes }, options) } else { - teardown = callback => each(nodes, (node, cb) => node.stop(cb), callback) + teardown = callback => each(nodes, (node, cb) => node.stop().then(cb, cb), callback) } return { setup, teardown } From 9616aed5ece058a3c98d12aa2dbe2999d08acb1f Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Wed, 4 Sep 2019 12:22:43 +0100 Subject: [PATCH 105/233] refactor: fetch add (#1087) License: MIT Signed-off-by: Alan Shaw --- .aegir.js | 2 +- package.json | 14 ++++- src/add-from-fs/index.browser.js | 3 + src/add-from-fs/index.js | 9 +++ src/add-from-url.js | 22 +++++++ src/add/form-data.browser.js | 31 ++++++++++ src/add/form-data.js | 42 ++++++++++++++ src/add/index.js | 54 +++++++++++++++++ src/files-mfs/write.js | 4 +- src/files-regular/add-async-iterator.js | 23 -------- src/files-regular/add-from-fs.js | 40 ------------- src/files-regular/add-from-url.js | 70 ----------------------- src/files-regular/add-pull-stream.js | 13 ----- src/files-regular/add-readable-stream.js | 12 ---- src/files-regular/add.js | 55 ------------------ src/files-regular/index.js | 43 +++++++++++--- src/lib/converters.js | 16 ++++++ src/lib/object-to-camel.js | 21 +++++++ src/utils/file-result-stream-converter.js | 44 -------------- src/utils/load-commands.js | 43 ++++---------- test/files-mfs.spec.js | 6 +- test/interface.spec.js | 5 -- 22 files changed, 260 insertions(+), 312 deletions(-) create mode 100644 src/add-from-fs/index.browser.js create mode 100644 src/add-from-fs/index.js create mode 100644 src/add-from-url.js create mode 100644 src/add/form-data.browser.js create mode 100644 src/add/form-data.js create mode 100644 src/add/index.js delete mode 100644 src/files-regular/add-async-iterator.js delete mode 100644 src/files-regular/add-from-fs.js delete mode 100644 src/files-regular/add-from-url.js delete mode 100644 src/files-regular/add-pull-stream.js delete mode 100644 src/files-regular/add-readable-stream.js delete mode 100644 src/files-regular/add.js create mode 100644 src/lib/converters.js create mode 100644 src/lib/object-to-camel.js delete mode 100644 src/utils/file-result-stream-converter.js diff --git a/.aegir.js b/.aegir.js index d9a727161..20aa93b74 100644 --- a/.aegir.js +++ b/.aegir.js @@ -5,7 +5,7 @@ const createServer = require('ipfsd-ctl').createServer const server = createServer() module.exports = { - bundlesize: { maxSize: '237kB' }, + bundlesize: { maxSize: '240kB' }, webpack: { resolve: { mainFields: ['browser', 'main'] diff --git a/package.json b/package.json index cc37fe15e..fd4d82c69 100644 --- a/package.json +++ b/package.json @@ -18,7 +18,9 @@ "glob": false, "fs": false, "stream": "readable-stream", - "ky-universal": "ky/umd" + "ky-universal": "ky/umd", + "./src/add/form-data.js": "./src/add/form-data.browser.js", + "./src/add-from-fs/index.js": "./src/add-from-fs/index.browser.js" }, "repository": "github:ipfs/js-ipfs-http-client", "scripts": { @@ -40,6 +42,8 @@ "dependencies": { "abort-controller": "^3.0.0", "async": "^2.6.1", + "async-iterator-all": "^1.0.0", + "async-iterator-to-pull-stream": "^1.3.0", "bignumber.js": "^9.0.0", "bl": "^3.0.0", "bs58": "^4.0.1", @@ -52,9 +56,10 @@ "err-code": "^2.0.0", "explain-error": "^1.0.4", "flatmap": "0.0.3", + "fs-extra": "^8.1.0", "glob": "^7.1.3", "ipfs-block": "~0.8.1", - "ipfs-utils": "~0.0.3", + "ipfs-utils": "^0.1.0", "ipld-dag-cbor": "~0.15.0", "ipld-dag-pb": "~0.17.3", "ipld-raw": "^4.0.0", @@ -63,6 +68,8 @@ "is-stream": "^2.0.0", "iso-stream-http": "~0.1.2", "iso-url": "~0.4.6", + "it-glob": "0.0.4", + "it-to-stream": "^0.1.1", "iterable-ndjson": "^1.1.0", "just-kebab-case": "^1.1.0", "just-map-keys": "^1.1.0", @@ -82,6 +89,7 @@ "promisify-es6": "^1.0.3", "pull-defer": "~0.2.3", "pull-stream": "^3.6.9", + "pull-stream-to-async-iterator": "^1.0.2", "pull-to-stream": "~0.1.1", "pump": "^3.0.0", "qs": "^6.5.2", @@ -98,7 +106,7 @@ "cross-env": "^5.2.0", "dirty-chai": "^2.0.1", "go-ipfs-dep": "^0.4.22", - "interface-ipfs-core": "^0.111.0", + "interface-ipfs-core": "^0.112.0", "ipfsd-ctl": "~0.45.0", "nock": "^10.0.2", "stream-equal": "^1.1.1" diff --git a/src/add-from-fs/index.browser.js b/src/add-from-fs/index.browser.js new file mode 100644 index 000000000..81d551294 --- /dev/null +++ b/src/add-from-fs/index.browser.js @@ -0,0 +1,3 @@ +'use strict' + +module.exports = () => () => { throw new Error('unavailable in the browser') } diff --git a/src/add-from-fs/index.js b/src/add-from-fs/index.js new file mode 100644 index 000000000..01a82e166 --- /dev/null +++ b/src/add-from-fs/index.js @@ -0,0 +1,9 @@ +'use strict' + +const configure = require('../lib/configure') +const globSource = require('ipfs-utils/src/files/glob-source') + +module.exports = configure(({ ky }) => { + const add = require('../add')({ ky }) + return (path, options) => add(globSource(path, options), options) +}) diff --git a/src/add-from-url.js b/src/add-from-url.js new file mode 100644 index 000000000..336906ea1 --- /dev/null +++ b/src/add-from-url.js @@ -0,0 +1,22 @@ +'use strict' + +const kyDefault = require('ky-universal').default +const configure = require('./lib/configure') +const toIterable = require('./lib/stream-to-iterable') + +module.exports = configure(({ ky }) => { + const add = require('./add')({ ky }) + + return (url, options) => (async function * () { + options = options || {} + + const { body } = await kyDefault.get(url) + + const input = { + path: decodeURIComponent(new URL(url).pathname.split('/').pop() || ''), + content: toIterable(body) + } + + yield * add(input, options) + })() +}) diff --git a/src/add/form-data.browser.js b/src/add/form-data.browser.js new file mode 100644 index 000000000..8e228c164 --- /dev/null +++ b/src/add/form-data.browser.js @@ -0,0 +1,31 @@ +'use strict' +/* eslint-env browser */ + +const { Buffer } = require('buffer') +const normaliseInput = require('ipfs-utils/src/files/normalise-input') + +exports.toFormData = async input => { + const files = normaliseInput(input) + const formData = new FormData() + let i = 0 + + for await (const file of files) { + if (file.content) { + // In the browser there's _currently_ no streaming upload, buffer up our + // async iterator chunks and append a big Blob :( + // One day, this will be browser streams + const bufs = [] + for await (const chunk of file.content) { + bufs.push(Buffer.isBuffer(chunk) ? chunk.buffer : chunk) + } + + formData.append(`file-${i}`, new Blob(bufs, { type: 'application/octet-stream' }), file.path) + } else { + formData.append(`dir-${i}`, new Blob([], { type: 'application/x-directory' }), file.path) + } + + i++ + } + + return formData +} diff --git a/src/add/form-data.js b/src/add/form-data.js new file mode 100644 index 000000000..2465ce2e3 --- /dev/null +++ b/src/add/form-data.js @@ -0,0 +1,42 @@ +'use strict' + +const FormData = require('form-data') +const { Buffer } = require('buffer') +const toStream = require('it-to-stream') +const normaliseInput = require('ipfs-utils/src/files/normalise-input') + +exports.toFormData = async input => { + const files = normaliseInput(input) + const formData = new FormData() + let i = 0 + + for await (const file of files) { + if (file.content) { + // In Node.js, FormData can be passed a stream so no need to buffer + formData.append( + `file-${i}`, + // FIXME: add a `path` property to the stream so `form-data` doesn't set + // a Content-Length header that is only the sum of the size of the + // header/footer when knownLength option (below) is null. + Object.assign( + toStream.readable(file.content), + { path: file.path || `file-${i}` } + ), + { + filepath: encodeURIComponent(file.path), + contentType: 'application/octet-stream', + knownLength: file.content.length // Send Content-Length header if known + } + ) + } else { + formData.append(`dir-${i}`, Buffer.alloc(0), { + filepath: encodeURIComponent(file.path), + contentType: 'application/x-directory' + }) + } + + i++ + } + + return formData +} diff --git a/src/add/index.js b/src/add/index.js new file mode 100644 index 000000000..34a5d33bd --- /dev/null +++ b/src/add/index.js @@ -0,0 +1,54 @@ +'use strict' + +const ndjson = require('iterable-ndjson') +const configure = require('../lib/configure') +const toIterable = require('../lib/stream-to-iterable') +const { toFormData } = require('./form-data') +const toCamel = require('../lib/object-to-camel') + +module.exports = configure(({ ky }) => { + return (input, options) => (async function * () { + options = options || {} + + const searchParams = new URLSearchParams(options.searchParams) + + searchParams.set('stream-channels', true) + if (options.chunker) searchParams.set('chunker', options.chunker) + if (options.cidVersion) searchParams.set('cid-version', options.cidVersion) + if (options.cidBase) searchParams.set('cid-base', options.cidBase) + if (options.enableShardingExperiment != null) searchParams.set('enable-sharding-experiment', options.enableShardingExperiment) + if (options.hashAlg) searchParams.set('hash', options.hashAlg) + if (options.onlyHash != null) searchParams.set('only-hash', options.onlyHash) + if (options.pin != null) searchParams.set('pin', options.pin) + if (options.progress) searchParams.set('progress', true) + if (options.quiet != null) searchParams.set('quiet', options.quiet) + if (options.quieter != null) searchParams.set('quieter', options.quieter) + if (options.rawLeaves != null) searchParams.set('raw-leaves', options.rawLeaves) + if (options.shardSplitThreshold) searchParams.set('shard-split-threshold', options.shardSplitThreshold) + if (options.silent) searchParams.set('silent', options.silent) + if (options.trickle != null) searchParams.set('trickle', options.trickle) + if (options.wrapWithDirectory != null) searchParams.set('wrap-with-directory', options.wrapWithDirectory) + + const res = await ky.post('add', { + timeout: options.timeout, + signal: options.signal, + headers: options.headers, + searchParams, + body: await toFormData(input) + }) + + for await (let file of ndjson(toIterable(res.body))) { + file = toCamel(file) + // console.log(file) + if (options.progress && file.bytes) { + options.progress(file.bytes) + } else { + yield toCoreInterface(file) + } + } + })() +}) + +function toCoreInterface ({ name, hash, size }) { + return { path: name, hash, size: parseInt(size) } +} diff --git a/src/files-mfs/write.js b/src/files-mfs/write.js index 0485406bd..33f1ec973 100644 --- a/src/files-mfs/write.js +++ b/src/files-mfs/write.js @@ -3,7 +3,6 @@ const promisify = require('promisify-es6') const concatStream = require('concat-stream') const once = require('once') -const FileResultStreamConverter = require('../utils/file-result-stream-converter') const SendFilesStream = require('../utils/send-files-stream') module.exports = (send) => { @@ -29,8 +28,7 @@ module.exports = (send) => { const options = { args: pathDst, - qs: opts, - converter: FileResultStreamConverter + qs: opts } const stream = sendFilesStream({ qs: options }) diff --git a/src/files-regular/add-async-iterator.js b/src/files-regular/add-async-iterator.js deleted file mode 100644 index 3fa2b23ed..000000000 --- a/src/files-regular/add-async-iterator.js +++ /dev/null @@ -1,23 +0,0 @@ -'use strict' - -const SendFilesStream = require('../utils/send-files-stream') -const FileResultStreamConverter = require('../utils/file-result-stream-converter') - -module.exports = (send) => { - return async function * (source, options) { - options = options || {} - options.converter = FileResultStreamConverter - - const stream = SendFilesStream(send, 'add')(options) - - for await (const entry of source) { - stream.write(entry) - } - - stream.end() - - for await (const entry of stream) { - yield entry - } - } -} diff --git a/src/files-regular/add-from-fs.js b/src/files-regular/add-from-fs.js deleted file mode 100644 index 2320fc537..000000000 --- a/src/files-regular/add-from-fs.js +++ /dev/null @@ -1,40 +0,0 @@ -'use strict' - -const isNode = require('detect-node') -const promisify = require('promisify-es6') -const SendOneFile = require('../utils/send-one-file-multiple-results') -const FileResultStreamConverter = require('../utils/file-result-stream-converter') - -module.exports = (send) => { - const sendOneFile = SendOneFile(send, 'add') - - return promisify((path, opts, callback) => { - if (typeof opts === 'function' && - callback === undefined) { - callback = opts - opts = {} - } - - // opts is the real callback -- - // 'callback' is being injected by promisify - if (typeof opts === 'function' && - typeof callback === 'function') { - callback = opts - opts = {} - } - - if (!isNode) { - return callback(new Error('fsAdd does not work in the browser')) - } - - if (typeof path !== 'string') { - return callback(new Error('"path" must be a string')) - } - - const requestOpts = { - qs: opts, - converter: FileResultStreamConverter - } - sendOneFile(path, requestOpts, callback) - }) -} diff --git a/src/files-regular/add-from-url.js b/src/files-regular/add-from-url.js deleted file mode 100644 index f1065f2de..000000000 --- a/src/files-regular/add-from-url.js +++ /dev/null @@ -1,70 +0,0 @@ -'use strict' - -const promisify = require('promisify-es6') -const { URL } = require('iso-url') -const { getRequest } = require('iso-stream-http') -const SendOneFile = require('../utils/send-one-file-multiple-results') -const FileResultStreamConverter = require('../utils/file-result-stream-converter') - -module.exports = (send) => { - const sendOneFile = SendOneFile(send, 'add') - - return promisify((url, opts, callback) => { - if (typeof (opts) === 'function' && - callback === undefined) { - callback = opts - opts = {} - } - - // opts is the real callback -- - // 'callback' is being injected by promisify - if (typeof opts === 'function' && - typeof callback === 'function') { - callback = opts - opts = {} - } - - if (!validUrl(url)) { - return callback(new Error('"url" param must be an http(s) url')) - } - - requestWithRedirect(url, opts, sendOneFile, callback) - }) -} - -const validUrl = (url) => typeof url === 'string' && url.startsWith('http') - -const requestWithRedirect = (url, opts, sendOneFile, callback) => { - const parsedUrl = new URL(url) - - const req = getRequest(parsedUrl, (res) => { - if (res.statusCode >= 400) { - return callback(new Error(`Failed to download with ${res.statusCode}`)) - } - - const redirection = res.headers.location - - if (res.statusCode >= 300 && res.statusCode < 400 && redirection) { - if (!validUrl(redirection)) { - return callback(new Error('redirection url must be an http(s) url')) - } - - requestWithRedirect(redirection, opts, sendOneFile, callback) - } else { - const requestOpts = { - qs: opts, - converter: FileResultStreamConverter - } - const fileName = decodeURIComponent(parsedUrl.pathname.split('/').pop()) - - sendOneFile({ - content: res, - path: fileName - }, requestOpts, callback) - } - }) - - req.once('error', callback) - - req.end() -} diff --git a/src/files-regular/add-pull-stream.js b/src/files-regular/add-pull-stream.js deleted file mode 100644 index 2076ffa8d..000000000 --- a/src/files-regular/add-pull-stream.js +++ /dev/null @@ -1,13 +0,0 @@ -'use strict' - -const SendFilesStream = require('../utils/send-files-stream') -const FileResultStreamConverter = require('../utils/file-result-stream-converter') -const toPull = require('stream-to-pull-stream') - -module.exports = (send) => { - return (options) => { - options = options || {} - options.converter = FileResultStreamConverter - return toPull(SendFilesStream(send, 'add')({ qs: options })) - } -} diff --git a/src/files-regular/add-readable-stream.js b/src/files-regular/add-readable-stream.js deleted file mode 100644 index 320abe692..000000000 --- a/src/files-regular/add-readable-stream.js +++ /dev/null @@ -1,12 +0,0 @@ -'use strict' - -const SendFilesStream = require('../utils/send-files-stream') -const FileResultStreamConverter = require('../utils/file-result-stream-converter') - -module.exports = (send) => { - return (options) => { - options = options || {} - options.converter = FileResultStreamConverter - return SendFilesStream(send, 'add')(options) - } -} diff --git a/src/files-regular/add.js b/src/files-regular/add.js deleted file mode 100644 index cb5898265..000000000 --- a/src/files-regular/add.js +++ /dev/null @@ -1,55 +0,0 @@ -'use strict' - -const promisify = require('promisify-es6') -const ConcatStream = require('concat-stream') -const once = require('once') -const { isSource } = require('is-pull-stream') -const FileResultStreamConverter = require('../utils/file-result-stream-converter') -const SendFilesStream = require('../utils/send-files-stream') -const validateAddInput = require('ipfs-utils/src/files/add-input-validation') - -module.exports = (send) => { - const createAddStream = SendFilesStream(send, 'add') - - const add = promisify((_files, options, _callback) => { - if (typeof options === 'function') { - _callback = options - options = null - } - const callback = once(_callback) - - if (!options) { - options = {} - } - options.converter = FileResultStreamConverter - - try { - validateAddInput(_files) - } catch (err) { - return callback(err) - } - - const files = [].concat(_files) - - const stream = createAddStream({ qs: options }) - const concat = ConcatStream((result) => callback(null, result)) - stream.once('error', callback) - stream.pipe(concat) - - files.forEach((file) => stream.write(file)) - stream.end() - }) - - return function () { - const args = Array.from(arguments) - - // If we files.add(), then promisify thinks the pull stream is - // a callback! Add an empty options object in this case so that a promise - // is returned. - if (args.length === 1 && isSource(args[0])) { - args.push({}) - } - - return add.apply(null, args) - } -} diff --git a/src/files-regular/index.js b/src/files-regular/index.js index e5b49e495..d098516f1 100644 --- a/src/files-regular/index.js +++ b/src/files-regular/index.js @@ -1,18 +1,47 @@ 'use strict' +const nodeify = require('promise-nodeify') const moduleConfig = require('../utils/module-config') +const { collectify, pullify, streamify } = require('../lib/converters') module.exports = (arg) => { const send = moduleConfig(arg) + const add = require('../add')(arg) + const addFromFs = require('../add-from-fs')(arg) + const addFromURL = require('../add-from-url')(arg) return { - add: require('../files-regular/add')(send), - addReadableStream: require('../files-regular/add-readable-stream')(send), - addPullStream: require('../files-regular/add-pull-stream')(send), - addFromFs: require('../files-regular/add-from-fs')(send), - addFromURL: require('../files-regular/add-from-url')(send), - addFromStream: require('../files-regular/add')(send), - _addAsyncIterator: require('../files-regular/add-async-iterator')(send), + add: (input, options, callback) => { + if (typeof options === 'function') { + callback = options + options = {} + } + return nodeify(collectify(add)(input, options), callback) + }, + addReadableStream: streamify.transform(add), + addPullStream: pullify.transform(add), + addFromFs: (path, options, callback) => { + if (typeof options === 'function') { + callback = options + options = {} + } + return nodeify(collectify(addFromFs)(path, options), callback) + }, + addFromURL: (url, options, callback) => { + if (typeof options === 'function') { + callback = options + options = {} + } + return nodeify(collectify(addFromURL)(url, options), callback) + }, + addFromStream: (input, options, callback) => { + if (typeof options === 'function') { + callback = options + options = {} + } + return nodeify(collectify(add)(input, options), callback) + }, + _addAsyncIterator: add, cat: require('../files-regular/cat')(send), catReadableStream: require('../files-regular/cat-readable-stream')(send), catPullStream: require('../files-regular/cat-pull-stream')(send), diff --git a/src/lib/converters.js b/src/lib/converters.js new file mode 100644 index 000000000..7c5965feb --- /dev/null +++ b/src/lib/converters.js @@ -0,0 +1,16 @@ +'use strict' + +const toPull = require('async-iterator-to-pull-stream') +const all = require('async-iterator-all') +const toStream = require('it-to-stream') + +exports.collectify = fn => (...args) => all(fn(...args)) + +exports.pullify = { + source: fn => (...args) => toPull(fn(...args)), + transform: fn => (...args) => toPull.transform(source => fn(source, ...args)) +} + +exports.streamify = { + transform: fn => (...args) => toStream.transform(source => fn(source, ...args), { objectMode: true }) +} diff --git a/src/lib/object-to-camel.js b/src/lib/object-to-camel.js new file mode 100644 index 000000000..f13b2b6a1 --- /dev/null +++ b/src/lib/object-to-camel.js @@ -0,0 +1,21 @@ +'use strict' + +// Convert object properties to camel case. +// NOT recursive! +// e.g. +// AgentVersion => agentVersion +// ID => id +module.exports = obj => { + if (obj == null) return obj + const caps = /^[A-Z]+$/ + return Object.keys(obj).reduce((camelObj, k) => { + if (caps.test(k)) { // all caps + camelObj[k.toLowerCase()] = obj[k] + } else if (caps.test(k[0])) { // pascal + camelObj[k[0].toLowerCase() + k.slice(1)] = obj[k] + } else { + camelObj[k] = obj[k] + } + return camelObj + }, {}) +} diff --git a/src/utils/file-result-stream-converter.js b/src/utils/file-result-stream-converter.js deleted file mode 100644 index 7f5b19aeb..000000000 --- a/src/utils/file-result-stream-converter.js +++ /dev/null @@ -1,44 +0,0 @@ -'use strict' - -const TransformStream = require('readable-stream').Transform - -/* - Transforms a stream of {Name, Hash} objects to include size - of the DAG object. - - Usage: inputStream.pipe(new FileResultStreamConverter()) - - Input object format: - { - Name: '/path/to/file/foo.txt', - Hash: 'Qma4hjFTnCasJ8PVp3mZbZK5g2vGDT4LByLJ7m8ciyRFZP' - Size: '20' - } - - Output object format: - { - path: '/path/to/file/foo.txt', - hash: 'Qma4hjFTnCasJ8PVp3mZbZK5g2vGDT4LByLJ7m8ciyRFZP', - size: 20 - } -*/ -class FileResultStreamConverter extends TransformStream { - constructor (options) { - const opts = Object.assign({}, options || {}, { objectMode: true }) - super(opts) - } - - _transform (obj, enc, callback) { - if (!obj.Hash) { - return callback() - } - - callback(null, { - path: obj.Name, - hash: obj.Hash, - size: parseInt(obj.Size, 10) - }) - } -} - -module.exports = FileResultStreamConverter diff --git a/src/utils/load-commands.js b/src/utils/load-commands.js index 467af3cea..710b8396f 100644 --- a/src/utils/load-commands.js +++ b/src/utils/load-commands.js @@ -1,28 +1,12 @@ 'use strict' -function requireCommands () { - return { - // Files Regular (not MFS) - add: require('../files-regular/add'), - addReadableStream: require('../files-regular/add-readable-stream'), - addPullStream: require('../files-regular/add-pull-stream'), - addFromFs: require('../files-regular/add-from-fs'), - addFromURL: require('../files-regular/add-from-url'), - addFromStream: require('../files-regular/add'), - _addAsyncIterator: require('../files-regular/add-async-iterator'), - cat: require('../files-regular/cat'), - catReadableStream: require('../files-regular/cat-readable-stream'), - catPullStream: require('../files-regular/cat-pull-stream'), - get: require('../files-regular/get'), - getReadableStream: require('../files-regular/get-readable-stream'), - getPullStream: require('../files-regular/get-pull-stream'), - ls: require('../files-regular/ls'), - lsReadableStream: require('../files-regular/ls-readable-stream'), - lsPullStream: require('../files-regular/ls-pull-stream'), - refs: require('../files-regular/refs'), - refsReadableStream: require('../files-regular/refs-readable-stream'), - refsPullStream: require('../files-regular/refs-pull-stream'), +function requireCommands (send, config) { + const cmds = { + ...require('../files-regular')(config), + getEndpointConfig: require('../get-endpoint-config')(config) + } + const subCmds = { // Files MFS (Mutable Filesystem) files: require('../files-mfs'), @@ -60,21 +44,14 @@ function requireCommands () { stats: require('../stats'), update: require('../update'), version: require('../version'), - resolve: require('../resolve'), - // ipfs-http-client instance - getEndpointConfig: (send, config) => require('../get-endpoint-config')(config) + resolve: require('../resolve') } -} - -function loadCommands (send, config) { - const files = requireCommands() - const cmds = {} - Object.keys(files).forEach((file) => { - cmds[file] = files[file](send, config) + Object.keys(subCmds).forEach((file) => { + cmds[file] = subCmds[file](send, config) }) return cmds } -module.exports = loadCommands +module.exports = requireCommands diff --git a/test/files-mfs.spec.js b/test/files-mfs.spec.js index 311659200..d1c2e0900 100644 --- a/test/files-mfs.spec.js +++ b/test/files-mfs.spec.js @@ -91,7 +91,7 @@ describe('.files (the MFS API part)', function () { it('.add with cid-version=1 and raw-leaves=false', async () => { const expectedCid = 'bafybeifogzovjqrcxvgt7g36y7g63hvwvoakledwk4b2fr2dl4wzawpnny' - const options = { 'cid-version': 1, 'raw-leaves': false } + const options = { cidVersion: 1, rawLeaves: false } const res = await ipfs.add(testfile, options) @@ -149,7 +149,7 @@ describe('.files (the MFS API part)', function () { path: content + '.txt', content: Buffer.from(content) } - const options = { hash: name, 'raw-leaves': false } + const options = { hashAlg: name, rawLeaves: false } const res = await ipfs.add([file], options) @@ -222,7 +222,7 @@ describe('.files (the MFS API part)', function () { path: content + '.txt', content: Buffer.from(content) } - const options = { hash: name, 'raw-leaves': false } + const options = { hashAlg: name, rawLeaves: false } const res = await ipfs.add([file], options) diff --git a/test/interface.spec.js b/test/interface.spec.js index fb54c422b..32c6f6749 100644 --- a/test/interface.spec.js +++ b/test/interface.spec.js @@ -126,11 +126,6 @@ describe('interface-ipfs-core tests', () => { name: 'should add readable stream of valid files and dirs', reason: 'FIXME https://github.com/ipfs/js-ipfs-http-client/issues/339' }, - // .addFromStream - isNode ? null : { - name: 'addFromStream', - reason: 'Not designed to run in the browser' - }, // .addFromFs isNode ? null : { name: 'addFromFs', From 0279b930bb011f5eda40445204bda3005f9e665a Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Wed, 4 Sep 2019 13:04:10 +0100 Subject: [PATCH 106/233] chore(package): update nock to version 11.3.2 (#1093) Closes #1092 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index fd4d82c69..f94e075eb 100644 --- a/package.json +++ b/package.json @@ -108,7 +108,7 @@ "go-ipfs-dep": "^0.4.22", "interface-ipfs-core": "^0.112.0", "ipfsd-ctl": "~0.45.0", - "nock": "^10.0.2", + "nock": "^11.3.2", "stream-equal": "^1.1.1" }, "engines": { From a09b90705e46673f291c6fe0652cd14646cd0d5b Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" <23040076+greenkeeper[bot]@users.noreply.github.com> Date: Wed, 4 Sep 2019 14:43:48 +0100 Subject: [PATCH 107/233] =?UTF-8?q?Update=20ky=20to=20the=20latest=20versi?= =?UTF-8?q?on=20=F0=9F=9A=80=20(#1090)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit License: MIT Signed-off-by: Alan Shaw --- package.json | 4 ++-- src/lib/error-handler.js | 2 +- test/lib.error-handler.spec.js | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index f94e075eb..7824f424a 100644 --- a/package.json +++ b/package.json @@ -74,8 +74,8 @@ "just-kebab-case": "^1.1.0", "just-map-keys": "^1.1.0", "kind-of": "^6.0.2", - "ky": "^0.11.2", - "ky-universal": "^0.2.2", + "ky": "^0.13.0", + "ky-universal": "^0.3.0", "lru-cache": "^5.1.1", "multiaddr": "^6.0.6", "multibase": "~0.6.0", diff --git a/src/lib/error-handler.js b/src/lib/error-handler.js index 1e788227c..6df198d78 100644 --- a/src/lib/error-handler.js +++ b/src/lib/error-handler.js @@ -7,7 +7,7 @@ function isJsonResponse (res) { return (res.headers.get('Content-Type') || '').startsWith('application/json') } -module.exports = async function errorHandler (response) { +module.exports = async function errorHandler (input, options, response) { if (response.ok) return let msg diff --git a/test/lib.error-handler.spec.js b/test/lib.error-handler.spec.js index 4e97260ec..d1a17d147 100644 --- a/test/lib.error-handler.spec.js +++ b/test/lib.error-handler.spec.js @@ -22,7 +22,7 @@ describe('lib/error-handler', () => { status: 500 } - const err = await throwsAsync(errorHandler(res)) + const err = await throwsAsync(errorHandler(null, null, res)) expect(err.message).to.eql('boom') expect(err.status).to.eql(500) @@ -36,7 +36,7 @@ describe('lib/error-handler', () => { status: 500 } - const err = await throwsAsync(errorHandler(res)) + const err = await throwsAsync(errorHandler(null, null, res)) expect(err instanceof HTTPError).to.be.true() }) @@ -48,7 +48,7 @@ describe('lib/error-handler', () => { status: 500 } - const err = await throwsAsync(errorHandler(res)) + const err = await throwsAsync(errorHandler(null, null, res)) expect(err instanceof HTTPError).to.be.true() }) }) From abe31770fd7165d55a3135b32271fda2bb35a4d0 Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Wed, 4 Sep 2019 16:35:41 +0100 Subject: [PATCH 108/233] chore: update contributors --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7824f424a..e88dcf56d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ipfs-http-client", - "version": "34.0.0", + "version": "35.0.0", "description": "A client library for the IPFS HTTP API", "keywords": [ "ipfs" From eb31b6c7786386a8f231702a4375ea6a1613cf88 Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Wed, 4 Sep 2019 16:35:41 +0100 Subject: [PATCH 109/233] chore: release version v35.0.0 --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c45dc7126..b76433cd4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ + +# [35.0.0](https://github.com/ipfs/js-ipfs-http-client/compare/v34.0.0...v35.0.0) (2019-09-04) + + + # [34.0.0](https://github.com/ipfs/js-ipfs-http-client/compare/v33.1.1...v34.0.0) (2019-08-29) From 3aaa3ee2490f6d7ae5ab89425c28d07cd22a42d5 Mon Sep 17 00:00:00 2001 From: dirkmc Date: Wed, 4 Sep 2019 12:37:51 -0400 Subject: [PATCH 110/233] feat: add config profile endpoint (#1030) License: MIT Signed-off-by: Alan Shaw --- src/config/index.js | 3 ++- src/config/profile.js | 41 ++++++++++++++++++++++++++++++++++++++++ test/interface.spec.js | 5 ----- test/sub-modules.spec.js | 1 + 4 files changed, 44 insertions(+), 6 deletions(-) create mode 100644 src/config/profile.js diff --git a/src/config/index.js b/src/config/index.js index 109865ab0..d690d8099 100644 --- a/src/config/index.js +++ b/src/config/index.js @@ -8,6 +8,7 @@ module.exports = (arg) => { return { get: require('./get')(send), set: require('./set')(send), - replace: require('./replace')(send) + replace: require('./replace')(send), + profile: require('./profile')(send) } } diff --git a/src/config/profile.js b/src/config/profile.js new file mode 100644 index 000000000..809adb5d4 --- /dev/null +++ b/src/config/profile.js @@ -0,0 +1,41 @@ +'use strict' + +const promisify = require('promisify-es6') + +const toObject = function (res, callback) { + if (Buffer.isBuffer(res)) { + callback(null, JSON.parse(res.toString())) + } else { + callback(null, res) + } +} + +module.exports = (send) => { + return promisify((profile, opts, callback) => { + if (typeof opts === 'function') { + callback = opts + opts = {} + } + + opts = normalizeOpts(opts) + + send.andTransform({ + path: 'config/profile/apply', + args: profile, + qs: opts + }, toObject, (err, response) => { + if (err) { + return callback(err) + } + callback(null, { oldCfg: response.OldCfg, newCfg: response.NewCfg }) + }) + }) +} + +function normalizeOpts (opts) { + opts = opts || {} + if (typeof opts.dryRun !== 'undefined') { + opts['dry-run'] = opts.dryRun + } + return opts +} diff --git a/test/interface.spec.js b/test/interface.spec.js index 32c6f6749..c51fc7e39 100644 --- a/test/interface.spec.js +++ b/test/interface.spec.js @@ -49,11 +49,6 @@ describe('interface-ipfs-core tests', () => { { name: 'replace', reason: 'FIXME Waiting for fix on go-ipfs https://github.com/ipfs/js-ipfs-http-client/pull/307#discussion_r69281789 and https://github.com/ipfs/go-ipfs/issues/2927' - }, - // config.profile - { - name: 'profile', - reason: 'TODO not yet implemented https://github.com/ipfs/js-ipfs-http-client/pull/1030' } ] }) diff --git a/test/sub-modules.spec.js b/test/sub-modules.spec.js index cabd09b55..b066b6278 100644 --- a/test/sub-modules.spec.js +++ b/test/sub-modules.spec.js @@ -42,6 +42,7 @@ describe('submodules', () => { expect(cfg.get).to.be.a('function') expect(cfg.set).to.be.a('function') expect(cfg.replace).to.be.a('function') + expect(cfg.profile).to.be.a('function') }) it('dht', () => { From 832022b2cef551ea45ac7da1c7f5d86f008f0256 Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Wed, 4 Sep 2019 17:42:31 +0100 Subject: [PATCH 111/233] chore: update contributors --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e88dcf56d..91ebcd75f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ipfs-http-client", - "version": "35.0.0", + "version": "35.1.0", "description": "A client library for the IPFS HTTP API", "keywords": [ "ipfs" From fadc6015c2b6fdc7d444b92a239d20da8da397f0 Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Wed, 4 Sep 2019 17:42:31 +0100 Subject: [PATCH 112/233] chore: release version v35.1.0 --- CHANGELOG.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b76433cd4..baffd2ddc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,13 @@ + +# [35.1.0](https://github.com/ipfs/js-ipfs-http-client/compare/v35.0.0...v35.1.0) (2019-09-04) + + +### Features + +* add config profile endpoint ([#1030](https://github.com/ipfs/js-ipfs-http-client/issues/1030)) ([3aaa3ee](https://github.com/ipfs/js-ipfs-http-client/commit/3aaa3ee)) + + + # [35.0.0](https://github.com/ipfs/js-ipfs-http-client/compare/v34.0.0...v35.0.0) (2019-09-04) From 0ff4d52478e6a1583edf917801c3bcaeb3036ec1 Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Tue, 10 Sep 2019 22:41:09 +0100 Subject: [PATCH 113/233] refactor: use fetch for ipfs.cat License: MIT Signed-off-by: Alan Shaw --- package.json | 2 +- src/cat.js | 34 +++++++++++++++++++++ src/files-regular/cat-pull-stream.js | 35 ---------------------- src/files-regular/cat-readable-stream.js | 35 ---------------------- src/files-regular/cat.js | 38 ------------------------ src/files-regular/index.js | 15 +++++++--- src/lib/converters.js | 4 +++ src/lib/error-handler.js | 14 ++++++++- 8 files changed, 63 insertions(+), 114 deletions(-) create mode 100644 src/cat.js delete mode 100644 src/files-regular/cat-pull-stream.js delete mode 100644 src/files-regular/cat-readable-stream.js delete mode 100644 src/files-regular/cat.js diff --git a/package.json b/package.json index 91ebcd75f..df023a9aa 100644 --- a/package.json +++ b/package.json @@ -74,7 +74,7 @@ "just-kebab-case": "^1.1.0", "just-map-keys": "^1.1.0", "kind-of": "^6.0.2", - "ky": "^0.13.0", + "ky": "^0.14.0", "ky-universal": "^0.3.0", "lru-cache": "^5.1.1", "multiaddr": "^6.0.6", diff --git a/src/cat.js b/src/cat.js new file mode 100644 index 000000000..496257e84 --- /dev/null +++ b/src/cat.js @@ -0,0 +1,34 @@ +'use strict' + +const CID = require('cids') +const { Buffer } = require('buffer') +const configure = require('./lib/configure') +const toIterable = require('./lib/stream-to-iterable') + +module.exports = configure(({ ky }) => { + return (path, options) => (async function * () { + options = options || {} + + const searchParams = new URLSearchParams(options.searchParams) + + if (typeof path === 'string') { + searchParams.set('arg', path) + } else { + searchParams.set('arg', new CID(path).toString()) + } + + if (options.offset) searchParams.set('offset', options.offset) + if (options.length) searchParams.set('length', options.length) + + const res = await ky.get('cat', { + timeout: options.timeout, + signal: options.signal, + headers: options.headers, + searchParams + }) + + for await (const chunk of toIterable(res.body)) { + yield Buffer.from(chunk) + } + })() +}) diff --git a/src/files-regular/cat-pull-stream.js b/src/files-regular/cat-pull-stream.js deleted file mode 100644 index 364f566d2..000000000 --- a/src/files-regular/cat-pull-stream.js +++ /dev/null @@ -1,35 +0,0 @@ -'use strict' - -const cleanCID = require('../utils/clean-cid') -const v = require('is-ipfs') -const toPull = require('stream-to-pull-stream') -const deferred = require('pull-defer') - -module.exports = (send) => { - return (hash, opts) => { - opts = opts || {} - - const p = deferred.source() - - try { - hash = cleanCID(hash) - } catch (err) { - if (!v.ipfsPath(hash)) { - return p.end(err) - } - } - - const query = { - offset: opts.offset, - length: opts.length - } - - send({ path: 'cat', args: hash, buffer: opts.buffer, qs: query }, (err, stream) => { - if (err) { return p.end(err) } - - p.resolve(toPull(stream)) - }) - - return p - } -} diff --git a/src/files-regular/cat-readable-stream.js b/src/files-regular/cat-readable-stream.js deleted file mode 100644 index 58ca69c67..000000000 --- a/src/files-regular/cat-readable-stream.js +++ /dev/null @@ -1,35 +0,0 @@ -'use strict' - -const cleanCID = require('../utils/clean-cid') -const v = require('is-ipfs') -const Stream = require('readable-stream') -const pump = require('pump') - -module.exports = (send) => { - return (hash, opts) => { - opts = opts || {} - - const pt = new Stream.PassThrough() - - try { - hash = cleanCID(hash) - } catch (err) { - if (!v.ipfsPath(hash)) { - return pt.destroy(err) - } - } - - const query = { - offset: opts.offset, - length: opts.length - } - - send({ path: 'cat', args: hash, buffer: opts.buffer, qs: query }, (err, stream) => { - if (err) { return pt.destroy(err) } - - pump(stream, pt) - }) - - return pt - } -} diff --git a/src/files-regular/cat.js b/src/files-regular/cat.js deleted file mode 100644 index ff468eb34..000000000 --- a/src/files-regular/cat.js +++ /dev/null @@ -1,38 +0,0 @@ -'use strict' - -const promisify = require('promisify-es6') -const cleanCID = require('../utils/clean-cid') -const v = require('is-ipfs') -const bl = require('bl') - -module.exports = (send) => { - return promisify((hash, opts, callback) => { - if (typeof opts === 'function') { - callback = opts - opts = {} - } - - try { - hash = cleanCID(hash) - } catch (err) { - if (!v.ipfsPath(hash)) { - return callback(err) - } - } - - const query = { - offset: opts.offset, - length: opts.length - } - - send({ path: 'cat', args: hash, buffer: opts.buffer, qs: query }, (err, stream) => { - if (err) { return callback(err) } - - stream.pipe(bl((err, data) => { - if (err) { return callback(err) } - - callback(null, data) - })) - }) - }) -} diff --git a/src/files-regular/index.js b/src/files-regular/index.js index d098516f1..9bfe10a5d 100644 --- a/src/files-regular/index.js +++ b/src/files-regular/index.js @@ -2,13 +2,14 @@ const nodeify = require('promise-nodeify') const moduleConfig = require('../utils/module-config') -const { collectify, pullify, streamify } = require('../lib/converters') +const { concatify, collectify, pullify, streamify } = require('../lib/converters') module.exports = (arg) => { const send = moduleConfig(arg) const add = require('../add')(arg) const addFromFs = require('../add-from-fs')(arg) const addFromURL = require('../add-from-url')(arg) + const cat = require('../cat')(arg) return { add: (input, options, callback) => { @@ -42,9 +43,15 @@ module.exports = (arg) => { return nodeify(collectify(add)(input, options), callback) }, _addAsyncIterator: add, - cat: require('../files-regular/cat')(send), - catReadableStream: require('../files-regular/cat-readable-stream')(send), - catPullStream: require('../files-regular/cat-pull-stream')(send), + cat: (path, options, callback) => { + if (typeof options === 'function') { + callback = options + options = {} + } + return nodeify(concatify(cat)(path, options), callback) + }, + catReadableStream: streamify.readable(cat), + catPullStream: pullify.source(cat), get: require('../files-regular/get')(send), getReadableStream: require('../files-regular/get-readable-stream')(send), getPullStream: require('../files-regular/get-pull-stream')(send), diff --git a/src/lib/converters.js b/src/lib/converters.js index 7c5965feb..a1ed8a010 100644 --- a/src/lib/converters.js +++ b/src/lib/converters.js @@ -3,14 +3,18 @@ const toPull = require('async-iterator-to-pull-stream') const all = require('async-iterator-all') const toStream = require('it-to-stream') +const { Buffer } = require('buffer') exports.collectify = fn => (...args) => all(fn(...args)) +exports.concatify = fn => async (...args) => Buffer.concat(await all(fn(...args))) + exports.pullify = { source: fn => (...args) => toPull(fn(...args)), transform: fn => (...args) => toPull.transform(source => fn(source, ...args)) } exports.streamify = { + readable: fn => (...args) => toStream(fn(...args), { objectMode: true }), transform: fn => (...args) => toStream.transform(source => fn(source, ...args), { objectMode: true }) } diff --git a/src/lib/error-handler.js b/src/lib/error-handler.js index 6df198d78..85e207831 100644 --- a/src/lib/error-handler.js +++ b/src/lib/error-handler.js @@ -2,13 +2,25 @@ const { HTTPError } = require('ky-universal') const log = require('debug')('ipfs-http-client:lib:error-handler') +const { isNode } = require('ipfs-utils/src/env') function isJsonResponse (res) { return (res.headers.get('Content-Type') || '').startsWith('application/json') } module.exports = async function errorHandler (input, options, response) { - if (response.ok) return + if (response.ok) { + // FIXME: remove when fixed https://github.com/sindresorhus/ky-universal/issues/8 + // + // ky clones the response for each handler. In Node.js the response body is + // piped to 2 PassThroughs, one becomes the real body and the other is used + // in the clone. + // + // If the body in the clone is not consumed or destroyed the highwater mark + // will be reached (for large payloads) and stop the real body from flowing. + if (isNode) response.body.destroy() + return + } let msg From 0288da18cf585769a4b33912a930a10bf1eaa3c6 Mon Sep 17 00:00:00 2001 From: achingbrain Date: Wed, 11 Sep 2019 08:50:34 +0100 Subject: [PATCH 114/233] chore: update multiaddrs module --- package.json | 2 +- test/constructor.spec.js | 18 +++++++++--------- test/node/swarm.js | 2 +- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/package.json b/package.json index 91ebcd75f..8f154540c 100644 --- a/package.json +++ b/package.json @@ -77,7 +77,7 @@ "ky": "^0.13.0", "ky-universal": "^0.3.0", "lru-cache": "^5.1.1", - "multiaddr": "^6.0.6", + "multiaddr": "^7.1.0", "multibase": "~0.6.0", "multicodec": "~0.5.1", "multihashes": "~0.4.14", diff --git a/test/constructor.spec.js b/test/constructor.spec.js index cc6a250c2..2f2ded23d 100644 --- a/test/constructor.spec.js +++ b/test/constructor.spec.js @@ -24,7 +24,7 @@ describe('ipfs-http-client constructor tests', () => { it('opts', () => { const host = 'wizard.world' - const port = '999' + const port = 999 const protocol = 'https' const ipfs = ipfsClient({ host, port, protocol }) expectConfig(ipfs, { host, port, protocol }) @@ -32,7 +32,7 @@ describe('ipfs-http-client constructor tests', () => { it('multiaddr dns4 string (implicit http)', () => { const host = 'foo.com' - const port = '1001' + const port = 1001 const protocol = 'http' // default to http if not specified in multiaddr const addr = `/dns4/${host}/tcp/${port}` const ipfs = ipfsClient(addr) @@ -41,7 +41,7 @@ describe('ipfs-http-client constructor tests', () => { it('multiaddr dns4 string (explicit https)', () => { const host = 'foo.com' - const port = '1001' + const port = 1001 const protocol = 'https' const addr = `/dns4/${host}/tcp/${port}/${protocol}` const ipfs = ipfsClient(addr) @@ -50,7 +50,7 @@ describe('ipfs-http-client constructor tests', () => { it('multiaddr dns4 string, explicit https in opts', () => { const host = 'foo.com' - const port = '1001' + const port = 1001 const protocol = 'https' const addr = `/dns4/${host}/tcp/${port}` const ipfs = ipfsClient(addr, { protocol }) @@ -59,7 +59,7 @@ describe('ipfs-http-client constructor tests', () => { it('multiaddr ipv4 string (implicit http)', () => { const host = '101.101.101.101' - const port = '1001' + const port = 1001 const protocol = 'http' const addr = `/ip4/${host}/tcp/${port}` const ipfs = ipfsClient(addr) @@ -68,7 +68,7 @@ describe('ipfs-http-client constructor tests', () => { it('multiaddr ipv4 string (explicit https)', () => { const host = '101.101.101.101' - const port = '1001' + const port = 1001 const protocol = 'https' const addr = `/ip4/${host}/tcp/${port}/${protocol}` const ipfs = ipfsClient(addr) @@ -77,7 +77,7 @@ describe('ipfs-http-client constructor tests', () => { it('multiaddr instance', () => { const host = 'ace.place' - const port = '1001' + const port = 1001 const addr = multiaddr(`/dns4/${host}/tcp/${port}`) const ipfs = ipfsClient(addr) expectConfig(ipfs, { host, port }) @@ -85,14 +85,14 @@ describe('ipfs-http-client constructor tests', () => { it('host and port strings', () => { const host = '1.1.1.1' - const port = '9999' + const port = 9999 const ipfs = ipfsClient(host, port) expectConfig(ipfs, { host, port }) }) it('host, port and api path', () => { const host = '10.100.100.255' - const port = '9999' + const port = 9999 const apiPath = '/future/api/v1/' const ipfs = ipfsClient(host, port, { 'api-path': apiPath }) expectConfig(ipfs, { host, port, apiPath }) diff --git a/test/node/swarm.js b/test/node/swarm.js index 3ec634aea..409f6c582 100644 --- a/test/node/swarm.js +++ b/test/node/swarm.js @@ -48,7 +48,7 @@ describe('.swarm.peers', function () { expect(res).to.be.a('array') expect(res.length).to.equal(1) expect(res[0].error).to.not.exist() - expect(res[0].addr.toString()).to.equal('/ip4/73.109.217.59/tcp/49311/ipfs/QmWjxEGC7BthJrCf7QTModrcsRweHbupdPTY4oGMVoDZXm') + expect(res[0].addr.toString()).to.equal('/ip4/73.109.217.59/tcp/49311/p2p/QmWjxEGC7BthJrCf7QTModrcsRweHbupdPTY4oGMVoDZXm') expect(res[0].peer.toB58String()).to.equal('QmWjxEGC7BthJrCf7QTModrcsRweHbupdPTY4oGMVoDZXm') expect(scope.isDone()).to.equal(true) }) From 919bcae91602cde3a83f93948e08b04743559447 Mon Sep 17 00:00:00 2001 From: achingbrain Date: Wed, 11 Sep 2019 08:55:09 +0100 Subject: [PATCH 115/233] chore: increase bundlesize --- .aegir.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.aegir.js b/.aegir.js index 20aa93b74..d85e96ca8 100644 --- a/.aegir.js +++ b/.aegir.js @@ -5,7 +5,7 @@ const createServer = require('ipfsd-ctl').createServer const server = createServer() module.exports = { - bundlesize: { maxSize: '240kB' }, + bundlesize: { maxSize: '245kB' }, webpack: { resolve: { mainFields: ['browser', 'main'] From a3c93e4ab6b9f3ff22b26bc2f36be4c57674f20e Mon Sep 17 00:00:00 2001 From: achingbrain Date: Wed, 11 Sep 2019 10:54:33 +0100 Subject: [PATCH 116/233] chore: update contributors --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 8f154540c..3f410a087 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ipfs-http-client", - "version": "35.1.0", + "version": "36.0.0", "description": "A client library for the IPFS HTTP API", "keywords": [ "ipfs" @@ -119,7 +119,6 @@ "Alan Shaw ", "Alan Shaw ", "Alex Mingoia ", - "Alex Potsides ", "Antonio Tenorio-Fornés ", "Bruno Barbieri ", "Clemo ", @@ -192,6 +191,7 @@ "Victor Bjelkholm ", "Volker Mische ", "Zhiyuan Lin ", + "achingbrain ", "dirkmc ", "dmitriy ryajov ", "elsehow ", From af6a5edbc76f9e393ec11cc3ca7a6fb9b9c42d0c Mon Sep 17 00:00:00 2001 From: achingbrain Date: Wed, 11 Sep 2019 10:54:33 +0100 Subject: [PATCH 117/233] chore: release version v36.0.0 --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index baffd2ddc..5b5c21cbc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ + +# [36.0.0](https://github.com/ipfs/js-ipfs-http-client/compare/v35.1.0...v36.0.0) (2019-09-11) + + + # [35.1.0](https://github.com/ipfs/js-ipfs-http-client/compare/v35.0.0...v35.1.0) (2019-09-04) From 9c9aac8631e1106cef1918d63ce458eee89b9804 Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Wed, 11 Sep 2019 14:05:38 +0100 Subject: [PATCH 118/233] fix: big downloads in electron License: MIT Signed-off-by: Alan Shaw --- src/lib/error-handler.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/error-handler.js b/src/lib/error-handler.js index 85e207831..88754e7aa 100644 --- a/src/lib/error-handler.js +++ b/src/lib/error-handler.js @@ -2,7 +2,7 @@ const { HTTPError } = require('ky-universal') const log = require('debug')('ipfs-http-client:lib:error-handler') -const { isNode } = require('ipfs-utils/src/env') +const { isNode, isElectron } = require('ipfs-utils/src/env') function isJsonResponse (res) { return (res.headers.get('Content-Type') || '').startsWith('application/json') @@ -18,7 +18,7 @@ module.exports = async function errorHandler (input, options, response) { // // If the body in the clone is not consumed or destroyed the highwater mark // will be reached (for large payloads) and stop the real body from flowing. - if (isNode) response.body.destroy() + if (isNode || isElectron) response.body.destroy() return } From a631a21a7587a28e7b3c8cf0216fdaba2e66ee85 Mon Sep 17 00:00:00 2001 From: Hugo Dias Date: Tue, 17 Sep 2019 12:44:31 +0100 Subject: [PATCH 119/233] fix: fix electron renderer tests and a couple more bugs (#1105) temp fix for electron renderer until ky-universal is fixed Blob can accept Buffer directly Buffer.buffer triggered a super weird bug in electron renderer enable a bunch of tests in the browser xvfb-run makes electron go crazy detect-node needs to be removed everywhere and ipfs-utils/src/env.js should be used If you mix promises and callbacks inside, call the callback with setImmediate --- .aegir.js | 24 +++++++- .travis.yml | 14 ++--- package.json | 10 ++-- src/add/form-data.browser.js | 7 +-- src/add/form-data.js | 8 +++ src/dht/findpeer.js | 2 +- src/id.js | 1 + test/get.spec.js | 14 +---- test/interface.spec.js | 78 +------------------------- test/utils/interface-common-factory.js | 53 +++++++++++++++-- 10 files changed, 98 insertions(+), 113 deletions(-) diff --git a/.aegir.js b/.aegir.js index d85e96ca8..9a75337d1 100644 --- a/.aegir.js +++ b/.aegir.js @@ -1,9 +1,13 @@ 'use strict' +const promisify = require('promisify-es6') const createServer = require('ipfsd-ctl').createServer - +const EchoServer = require('interface-ipfs-core/src/utils/echo-http-server') const server = createServer() +const echoServer = EchoServer.createServer() +const echoServerStart = promisify(echoServer.start) +const echoServerStop = promisify(echoServer.stop) module.exports = { bundlesize: { maxSize: '245kB' }, webpack: { @@ -22,9 +26,23 @@ module.exports = { singleRun: true }, hooks: { + node: { + pre: () => echoServerStart(), + post: () => echoServerStop() + }, browser: { - pre: () => server.start(), - post: () => server.stop() + pre: () => { + return Promise.all([ + server.start(), + echoServerStart() + ]) + }, + post: () => { + return Promise.all([ + server.stop(), + echoServerStop() + ]) + } } } } diff --git a/.travis.yml b/.travis.yml index 21dbade12..f435392ac 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,13 +1,14 @@ language: node_js cache: npm + stages: - check - test - cov node_js: - - '10' - '12' + - '10' os: - linux @@ -18,11 +19,6 @@ script: npx nyc -s npm run test:node -- --bail after_success: npx nyc report --reporter=text-lcov > coverage.lcov && npx codecov jobs: - allow_failures: - - name: electron-renderer - - fast_finish: true - include: - stage: check script: @@ -44,13 +40,15 @@ jobs: - stage: test name: electron-main + os: osx script: - - xvfb-run npx aegir test -t electron-main -- --bail + - npx aegir test -t electron-main --bail - stage: test name: electron-renderer + os: osx script: - - xvfb-run npx aegir test -t electron-renderer -- --bail + - npx aegir test -t electron-renderer --bail notifications: email: false diff --git a/package.json b/package.json index 3f410a087..b3c656c1c 100644 --- a/package.json +++ b/package.json @@ -51,6 +51,7 @@ "cids": "~0.7.1", "concat-stream": "github:hugomrdias/concat-stream#feat/smaller", "debug": "^4.1.0", + "delay": "^4.3.0", "detect-node": "^2.0.4", "end-of-stream": "^1.4.1", "err-code": "^2.0.0", @@ -77,6 +78,7 @@ "ky": "^0.13.0", "ky-universal": "^0.3.0", "lru-cache": "^5.1.1", + "merge-options": "^1.0.1", "multiaddr": "^7.1.0", "multibase": "~0.6.0", "multicodec": "~0.5.1", @@ -99,15 +101,15 @@ "through2": "^3.0.1" }, "devDependencies": { - "aegir": "^20.0.0", + "aegir": "^20.2.0", "browser-process-platform": "~0.1.1", "chai": "^4.2.0", "chai-as-promised": "^7.1.1", - "cross-env": "^5.2.0", + "cross-env": "^5.2.1", "dirty-chai": "^2.0.1", "go-ipfs-dep": "^0.4.22", - "interface-ipfs-core": "^0.112.0", - "ipfsd-ctl": "~0.45.0", + "interface-ipfs-core": "~0.114.0", + "ipfsd-ctl": "^0.46.2", "nock": "^11.3.2", "stream-equal": "^1.1.1" }, diff --git a/src/add/form-data.browser.js b/src/add/form-data.browser.js index 8e228c164..247396c42 100644 --- a/src/add/form-data.browser.js +++ b/src/add/form-data.browser.js @@ -1,7 +1,6 @@ 'use strict' /* eslint-env browser */ -const { Buffer } = require('buffer') const normaliseInput = require('ipfs-utils/src/files/normalise-input') exports.toFormData = async input => { @@ -16,12 +15,12 @@ exports.toFormData = async input => { // One day, this will be browser streams const bufs = [] for await (const chunk of file.content) { - bufs.push(Buffer.isBuffer(chunk) ? chunk.buffer : chunk) + bufs.push(chunk) } - formData.append(`file-${i}`, new Blob(bufs, { type: 'application/octet-stream' }), file.path) + formData.append(`file-${i}`, new Blob(bufs, { type: 'application/octet-stream' }), encodeURIComponent(file.path)) } else { - formData.append(`dir-${i}`, new Blob([], { type: 'application/x-directory' }), file.path) + formData.append(`dir-${i}`, new Blob([], { type: 'application/x-directory' }), encodeURIComponent(file.path)) } i++ diff --git a/src/add/form-data.js b/src/add/form-data.js index 2465ce2e3..96d55f672 100644 --- a/src/add/form-data.js +++ b/src/add/form-data.js @@ -4,6 +4,7 @@ const FormData = require('form-data') const { Buffer } = require('buffer') const toStream = require('it-to-stream') const normaliseInput = require('ipfs-utils/src/files/normalise-input') +const { isElectronRenderer } = require('ipfs-utils/src/env') exports.toFormData = async input => { const files = normaliseInput(input) @@ -40,3 +41,10 @@ exports.toFormData = async input => { return formData } + +// TODO remove this when upstream fix for ky-universal is merged +// https://github.com/sindresorhus/ky-universal/issues/9 +// also this should only be necessary when nodeIntegration is false in electron renderer +if (isElectronRenderer) { + exports.toFormData = require('./form-data.browser').toFormData +} diff --git a/src/dht/findpeer.js b/src/dht/findpeer.js index 046664bda..8bcc80fb5 100644 --- a/src/dht/findpeer.js +++ b/src/dht/findpeer.js @@ -32,7 +32,7 @@ module.exports = (send) => { // 2 = FinalPeer // https://github.com/libp2p/go-libp2p-core/blob/6e566d10f4a5447317a66d64c7459954b969bdab/routing/query.go#L18 if (!res || res.Type !== 2) { - const errMsg = `key was not found (type 4)` + const errMsg = 'key was not found (type 4)' return callback(errcode(new Error(errMsg), 'ERR_KEY_TYPE_4_NOT_FOUND')) } diff --git a/src/id.js b/src/id.js index 1db0f7a0c..b98be8443 100644 --- a/src/id.js +++ b/src/id.js @@ -11,6 +11,7 @@ module.exports = (arg) => { callback = opts opts = undefined } + send({ path: 'id', args: opts diff --git a/test/get.spec.js b/test/get.spec.js index acdcf833b..05a29ffab 100644 --- a/test/get.spec.js +++ b/test/get.spec.js @@ -9,7 +9,6 @@ const chaiAsPromised = require('chai-as-promised') const expect = chai.expect chai.use(dirtyChai) chai.use(chaiAsPromised) -const isNode = require('detect-node') const loadFixture = require('aegir/fixtures') const ipfsClient = require('../src') @@ -75,26 +74,19 @@ describe('.get (specific go-ipfs features)', function () { }) it('add path containing "+"s (for testing get)', async () => { - if (!isNode) { - return - } - const filename = 'ti,c64x+mega++mod-pic.txt' const subdir = 'tmp/c++files' const expectedCid = 'QmPkmARcqjo5fqK1V1o8cFsuaXxWYsnwCNLJUYS4KeZyff' + const path = `${subdir}/${filename}` const files = await ipfs.add([{ - path: subdir + '/' + filename, - content: Buffer.from(subdir + '/' + filename, 'utf-8') + path, + content: Buffer.from(path) }]) expect(files[2].hash).to.equal(expectedCid) }) it('get path containing "+"s', async () => { - if (!isNode) { - return - } - const cid = 'QmPkmARcqjo5fqK1V1o8cFsuaXxWYsnwCNLJUYS4KeZyff' let count = 0 const files = await ipfs.get(cid) diff --git a/test/interface.spec.js b/test/interface.spec.js index c51fc7e39..e3c8ffb19 100644 --- a/test/interface.spec.js +++ b/test/interface.spec.js @@ -4,7 +4,6 @@ const tests = require('interface-ipfs-core') const isNode = require('detect-node') const CommonFactory = require('./utils/interface-common-factory') -const ipfsClient = require('../src') const isWindows = process.platform && process.platform === 'win32' describe('interface-ipfs-core tests', () => { @@ -102,40 +101,11 @@ describe('interface-ipfs-core tests', () => { tests.filesRegular(defaultCommonFactory, { skip: [ - // .add - isNode ? null : { - name: 'should add a nested directory as array of tupples', - reason: 'FIXME https://github.com/ipfs/js-ipfs-http-client/issues/339' - }, - isNode ? null : { - name: 'should add a nested directory as array of tupples with progress', - reason: 'FIXME https://github.com/ipfs/js-ipfs-http-client/issues/339' - }, - // .addPullStream - isNode ? null : { - name: 'should add pull stream of valid files and dirs', - reason: 'FIXME https://github.com/ipfs/js-ipfs-http-client/issues/339' - }, - // .addReadableStream - isNode ? null : { - name: 'should add readable stream of valid files and dirs', - reason: 'FIXME https://github.com/ipfs/js-ipfs-http-client/issues/339' - }, // .addFromFs isNode ? null : { name: 'addFromFs', reason: 'Not designed to run in the browser' }, - // .addFromURL - isNode ? null : { - name: 'addFromURL', - reason: 'Not designed to run in the browser' - }, - // TODO: remove when interface-ipfs-core updated - isNode ? null : { - name: 'addFromUrl', - reason: 'Not designed to run in the browser' - }, // .catPullStream { name: 'should export a chunk of a file', @@ -148,26 +118,6 @@ describe('interface-ipfs-core tests', () => { { name: 'should export a chunk of a file in a Readable Stream', reason: 'TODO not implemented in go-ipfs yet' - }, - // .get - isNode ? null : { - name: 'should get a directory', - reason: 'FIXME https://github.com/ipfs/js-ipfs-http-client/issues/339' - }, - // .ls - isNode ? null : { - name: 'should ls with a base58 encoded CID', - reason: 'FIXME https://github.com/ipfs/js-ipfs-http-client/issues/339' - }, - // .lsPullStream - isNode ? null : { - name: 'should pull stream ls with a base58 encoded CID', - reason: 'FIXME https://github.com/ipfs/js-ipfs-http-client/issues/339' - }, - // .lsReadableStream - isNode ? null : { - name: 'should readable stream ls with a base58 encoded CID', - reason: 'FIXME https://github.com/ipfs/js-ipfs-http-client/issues/339' } ] }) @@ -277,31 +227,5 @@ describe('interface-ipfs-core tests', () => { tests.stats(defaultCommonFactory) - tests.swarm(CommonFactory.create({ - createSetup ({ ipfsFactory, nodes }) { - return callback => { - callback(null, { - spawnNode (repoPath, config, cb) { - if (typeof repoPath === 'function') { - cb = repoPath - repoPath = undefined - } - - if (typeof config === 'function') { - cb = config - config = undefined - } - - const spawnOptions = { repoPath, config, initOptions: { bits: 1024, profile: 'test' } } - - ipfsFactory.spawn(spawnOptions) - .then(ipfsd => { - nodes.push(ipfsd) - cb(null, ipfsClient(ipfsd.apiAddr)) - }, cb) - } - }) - } - } - })) + tests.swarm(CommonFactory.createAsync()) }) diff --git a/test/utils/interface-common-factory.js b/test/utils/interface-common-factory.js index 6f1cad7ca..4a47fda42 100644 --- a/test/utils/interface-common-factory.js +++ b/test/utils/interface-common-factory.js @@ -4,11 +4,12 @@ const each = require('async/each') const IPFSFactory = require('ipfsd-ctl') const ipfsClient = require('../../src') +const merge = require('merge-options') function createFactory (options) { options = options || {} - options.factoryOptions = options.factoryOptions || {} + options.factoryOptions = options.factoryOptions || { IpfsClient: ipfsClient } options.spawnOptions = options.spawnOptions || { initOptions: { bits: 1024, profile: 'test' } } const ipfsFactory = IPFSFactory.create(options.factoryOptions) @@ -26,8 +27,11 @@ function createFactory (options) { ipfsFactory.spawn(options.spawnOptions) .then((ipfsd) => { nodes.push(ipfsd) - cb(null, ipfsClient(ipfsd.apiAddr)) - }, cb) + setImmediate(() => cb(null, ipfsd.api)) + }) + .catch(err => { + setImmediate(() => cb(err)) + }) } }) } @@ -36,11 +40,50 @@ function createFactory (options) { if (options.createTeardown) { teardown = options.createTeardown({ ipfsFactory, nodes }, options) } else { - teardown = callback => each(nodes, (node, cb) => node.stop().then(cb, cb), callback) + teardown = callback => each(nodes, (node, cb) => { + node + .stop() + .then(() => setImmediate(() => cb())) + .catch(err => setImmediate(() => cb(err))) + }, callback) } return { setup, teardown } } } -exports.create = createFactory +function createAsync (createFactoryOptions, createSpawnOptions) { + return () => { + const nodes = [] + const setup = async (factoryOptions = {}, spawnOptions) => { + const ipfsFactory = IPFSFactory.create(merge( + { IpfsClient: ipfsClient }, + factoryOptions, + createFactoryOptions + )) + const node = await ipfsFactory.spawn(merge( + { initOptions: { profile: 'test' } }, + spawnOptions, + createSpawnOptions + )) + nodes.push(node) + + const id = await node.api.id() + node.api.peerId = id + + return node.api + } + + const teardown = () => { + return Promise.all(nodes.map(n => n.stop())) + } + return { + setup, + teardown + } + } +} +module.exports = { + createAsync, + create: createFactory +} From e09cb3c3438e7f629b3f1f890d67cf34955f0c26 Mon Sep 17 00:00:00 2001 From: Hugo Dias Date: Tue, 17 Sep 2019 15:54:08 +0100 Subject: [PATCH 120/233] chore: update contributors --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b3c656c1c..0732856d8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ipfs-http-client", - "version": "36.0.0", + "version": "36.1.0", "description": "A client library for the IPFS HTTP API", "keywords": [ "ipfs" From b89b487fdb93d6238220cdc80c0b2c701950de84 Mon Sep 17 00:00:00 2001 From: Hugo Dias Date: Tue, 17 Sep 2019 15:54:08 +0100 Subject: [PATCH 121/233] chore: release version v36.1.0 --- CHANGELOG.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5b5c21cbc..7d53c1940 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,13 @@ + +# [36.1.0](https://github.com/ipfs/js-ipfs-http-client/compare/v36.0.0...v36.1.0) (2019-09-17) + + +### Bug Fixes + +* fix electron renderer tests and a couple more bugs ([#1105](https://github.com/ipfs/js-ipfs-http-client/issues/1105)) ([a631a21](https://github.com/ipfs/js-ipfs-http-client/commit/a631a21)) + + + # [36.0.0](https://github.com/ipfs/js-ipfs-http-client/compare/v35.1.0...v36.0.0) (2019-09-11) From c1279ce8acfb99d621cc4eddee8f50f93c4ebe1e Mon Sep 17 00:00:00 2001 From: achingbrain Date: Tue, 17 Sep 2019 19:23:24 +0100 Subject: [PATCH 122/233] chore: revert multiaddr upgrade --- package.json | 2 +- test/constructor.spec.js | 18 +++++++++--------- test/node/swarm.js | 2 +- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/package.json b/package.json index 2baecc1c4..8c439c3a9 100644 --- a/package.json +++ b/package.json @@ -79,7 +79,7 @@ "ky-universal": "^0.3.0", "lru-cache": "^5.1.1", "merge-options": "^1.0.1", - "multiaddr": "^7.1.0", + "multiaddr": "^6.0.6", "multibase": "~0.6.0", "multicodec": "~0.5.1", "multihashes": "~0.4.14", diff --git a/test/constructor.spec.js b/test/constructor.spec.js index 2f2ded23d..cc6a250c2 100644 --- a/test/constructor.spec.js +++ b/test/constructor.spec.js @@ -24,7 +24,7 @@ describe('ipfs-http-client constructor tests', () => { it('opts', () => { const host = 'wizard.world' - const port = 999 + const port = '999' const protocol = 'https' const ipfs = ipfsClient({ host, port, protocol }) expectConfig(ipfs, { host, port, protocol }) @@ -32,7 +32,7 @@ describe('ipfs-http-client constructor tests', () => { it('multiaddr dns4 string (implicit http)', () => { const host = 'foo.com' - const port = 1001 + const port = '1001' const protocol = 'http' // default to http if not specified in multiaddr const addr = `/dns4/${host}/tcp/${port}` const ipfs = ipfsClient(addr) @@ -41,7 +41,7 @@ describe('ipfs-http-client constructor tests', () => { it('multiaddr dns4 string (explicit https)', () => { const host = 'foo.com' - const port = 1001 + const port = '1001' const protocol = 'https' const addr = `/dns4/${host}/tcp/${port}/${protocol}` const ipfs = ipfsClient(addr) @@ -50,7 +50,7 @@ describe('ipfs-http-client constructor tests', () => { it('multiaddr dns4 string, explicit https in opts', () => { const host = 'foo.com' - const port = 1001 + const port = '1001' const protocol = 'https' const addr = `/dns4/${host}/tcp/${port}` const ipfs = ipfsClient(addr, { protocol }) @@ -59,7 +59,7 @@ describe('ipfs-http-client constructor tests', () => { it('multiaddr ipv4 string (implicit http)', () => { const host = '101.101.101.101' - const port = 1001 + const port = '1001' const protocol = 'http' const addr = `/ip4/${host}/tcp/${port}` const ipfs = ipfsClient(addr) @@ -68,7 +68,7 @@ describe('ipfs-http-client constructor tests', () => { it('multiaddr ipv4 string (explicit https)', () => { const host = '101.101.101.101' - const port = 1001 + const port = '1001' const protocol = 'https' const addr = `/ip4/${host}/tcp/${port}/${protocol}` const ipfs = ipfsClient(addr) @@ -77,7 +77,7 @@ describe('ipfs-http-client constructor tests', () => { it('multiaddr instance', () => { const host = 'ace.place' - const port = 1001 + const port = '1001' const addr = multiaddr(`/dns4/${host}/tcp/${port}`) const ipfs = ipfsClient(addr) expectConfig(ipfs, { host, port }) @@ -85,14 +85,14 @@ describe('ipfs-http-client constructor tests', () => { it('host and port strings', () => { const host = '1.1.1.1' - const port = 9999 + const port = '9999' const ipfs = ipfsClient(host, port) expectConfig(ipfs, { host, port }) }) it('host, port and api path', () => { const host = '10.100.100.255' - const port = 9999 + const port = '9999' const apiPath = '/future/api/v1/' const ipfs = ipfsClient(host, port, { 'api-path': apiPath }) expectConfig(ipfs, { host, port, apiPath }) diff --git a/test/node/swarm.js b/test/node/swarm.js index 409f6c582..3ec634aea 100644 --- a/test/node/swarm.js +++ b/test/node/swarm.js @@ -48,7 +48,7 @@ describe('.swarm.peers', function () { expect(res).to.be.a('array') expect(res.length).to.equal(1) expect(res[0].error).to.not.exist() - expect(res[0].addr.toString()).to.equal('/ip4/73.109.217.59/tcp/49311/p2p/QmWjxEGC7BthJrCf7QTModrcsRweHbupdPTY4oGMVoDZXm') + expect(res[0].addr.toString()).to.equal('/ip4/73.109.217.59/tcp/49311/ipfs/QmWjxEGC7BthJrCf7QTModrcsRweHbupdPTY4oGMVoDZXm') expect(res[0].peer.toB58String()).to.equal('QmWjxEGC7BthJrCf7QTModrcsRweHbupdPTY4oGMVoDZXm') expect(scope.isDone()).to.equal(true) }) From 9715b21d47d8e0cf7e496db4a5dbcc3d2105d316 Mon Sep 17 00:00:00 2001 From: achingbrain Date: Tue, 17 Sep 2019 19:55:07 +0100 Subject: [PATCH 123/233] chore: update contributors --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 8c439c3a9..6a669ec12 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ipfs-http-client", - "version": "36.1.0", + "version": "37.0.0", "description": "A client library for the IPFS HTTP API", "keywords": [ "ipfs" From da7b606cb6bb8668ef5e86be2acdb4550c0401e3 Mon Sep 17 00:00:00 2001 From: achingbrain Date: Tue, 17 Sep 2019 19:55:07 +0100 Subject: [PATCH 124/233] chore: release version v37.0.0 --- CHANGELOG.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7d53c1940..b489a4b4b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,13 @@ + +# [37.0.0](https://github.com/ipfs/js-ipfs-http-client/compare/v36.1.0...v37.0.0) (2019-09-17) + + +### Bug Fixes + +* big downloads in electron ([9c9aac8](https://github.com/ipfs/js-ipfs-http-client/commit/9c9aac8)) + + + # [36.1.0](https://github.com/ipfs/js-ipfs-http-client/compare/v36.0.0...v36.1.0) (2019-09-17) From e75935fbfca607d2ac7c601b219315c56c6fbcc0 Mon Sep 17 00:00:00 2001 From: achingbrain Date: Tue, 17 Sep 2019 22:34:15 +0100 Subject: [PATCH 125/233] chore: dep update --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 6a669ec12..8b785924a 100644 --- a/package.json +++ b/package.json @@ -60,7 +60,7 @@ "fs-extra": "^8.1.0", "glob": "^7.1.3", "ipfs-block": "~0.8.1", - "ipfs-utils": "^0.1.0", + "ipfs-utils": "^0.3.0", "ipld-dag-cbor": "~0.15.0", "ipld-dag-pb": "~0.17.3", "ipld-raw": "^4.0.0", From d6d6c17017af4a23fa98d400f1e7cb8a7df0b423 Mon Sep 17 00:00:00 2001 From: achingbrain Date: Tue, 17 Sep 2019 22:52:39 +0100 Subject: [PATCH 126/233] chore: update contributors --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 8b785924a..921f6cb2c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ipfs-http-client", - "version": "37.0.0", + "version": "37.0.1", "description": "A client library for the IPFS HTTP API", "keywords": [ "ipfs" From 7934103ccf1cee4c92ebcb820b0c6860836d1cd1 Mon Sep 17 00:00:00 2001 From: achingbrain Date: Tue, 17 Sep 2019 22:52:40 +0100 Subject: [PATCH 127/233] chore: release version v37.0.1 --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b489a4b4b..7739c2d86 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ + +## [37.0.1](https://github.com/ipfs/js-ipfs-http-client/compare/v37.0.0...v37.0.1) (2019-09-17) + + + # [37.0.0](https://github.com/ipfs/js-ipfs-http-client/compare/v36.1.0...v37.0.0) (2019-09-17) From 077c997464b3d55b105cc3431fd6607c67f159c5 Mon Sep 17 00:00:00 2001 From: Hugo Dias Date: Thu, 19 Sep 2019 11:37:38 +0100 Subject: [PATCH 128/233] fix: only do the big file workaround in node and electron main --- package.json | 8 ++++---- src/lib/error-handler.js | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 921f6cb2c..65e1a650a 100644 --- a/package.json +++ b/package.json @@ -60,7 +60,7 @@ "fs-extra": "^8.1.0", "glob": "^7.1.3", "ipfs-block": "~0.8.1", - "ipfs-utils": "^0.3.0", + "ipfs-utils": "^0.4.0", "ipld-dag-cbor": "~0.15.0", "ipld-dag-pb": "~0.17.3", "ipld-raw": "^4.0.0", @@ -101,15 +101,15 @@ "through2": "^3.0.1" }, "devDependencies": { - "aegir": "^20.2.0", + "aegir": "^20.3.1", "browser-process-platform": "~0.1.1", "chai": "^4.2.0", "chai-as-promised": "^7.1.1", - "cross-env": "^5.2.1", + "cross-env": "^6.0.0", "dirty-chai": "^2.0.1", "go-ipfs-dep": "^0.4.22", "interface-ipfs-core": "~0.114.0", - "ipfsd-ctl": "^0.46.2", + "ipfsd-ctl": "^0.47.1", "nock": "^11.3.2", "stream-equal": "^1.1.1" }, diff --git a/src/lib/error-handler.js b/src/lib/error-handler.js index 88754e7aa..032a6acc8 100644 --- a/src/lib/error-handler.js +++ b/src/lib/error-handler.js @@ -2,7 +2,7 @@ const { HTTPError } = require('ky-universal') const log = require('debug')('ipfs-http-client:lib:error-handler') -const { isNode, isElectron } = require('ipfs-utils/src/env') +const { isNode, isElectronMain } = require('ipfs-utils/src/env') function isJsonResponse (res) { return (res.headers.get('Content-Type') || '').startsWith('application/json') @@ -18,7 +18,7 @@ module.exports = async function errorHandler (input, options, response) { // // If the body in the clone is not consumed or destroyed the highwater mark // will be reached (for large payloads) and stop the real body from flowing. - if (isNode || isElectron) response.body.destroy() + if (isNode || isElectronMain) response.body.destroy() return } From 15d87e08fd6f795de2932792b52d462224fc1b00 Mon Sep 17 00:00:00 2001 From: Hugo Dias Date: Fri, 20 Sep 2019 10:52:32 +0100 Subject: [PATCH 129/233] chore: update contributors --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 65e1a650a..b11e359f1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ipfs-http-client", - "version": "37.0.1", + "version": "37.0.2", "description": "A client library for the IPFS HTTP API", "keywords": [ "ipfs" From 641c28c12f848ed3f4f61c1dc75d149e8b4eef07 Mon Sep 17 00:00:00 2001 From: Hugo Dias Date: Fri, 20 Sep 2019 10:52:33 +0100 Subject: [PATCH 130/233] chore: release version v37.0.2 --- CHANGELOG.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7739c2d86..c2bb8748f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,13 @@ + +## [37.0.2](https://github.com/ipfs/js-ipfs-http-client/compare/v37.0.1...v37.0.2) (2019-09-20) + + +### Bug Fixes + +* only do the big file workaround in node and electron main ([077c997](https://github.com/ipfs/js-ipfs-http-client/commit/077c997)) + + + ## [37.0.1](https://github.com/ipfs/js-ipfs-http-client/compare/v37.0.0...v37.0.1) (2019-09-17) From a34313eb684f49e627dd3bdc5ca661215636802e Mon Sep 17 00:00:00 2001 From: phillmac Date: Sat, 21 Sep 2019 12:21:40 +1000 Subject: [PATCH 131/233] Add form-data dependency Depend on form-data ^2.5.1 --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index b11e359f1..bb32b9fe1 100644 --- a/package.json +++ b/package.json @@ -57,6 +57,7 @@ "err-code": "^2.0.0", "explain-error": "^1.0.4", "flatmap": "0.0.3", + "form-data": "^2.5.1", "fs-extra": "^8.1.0", "glob": "^7.1.3", "ipfs-block": "~0.8.1", From eedd1bc82244ad40346d1dc5f7ab00bdce352e97 Mon Sep 17 00:00:00 2001 From: achingbrain Date: Mon, 23 Sep 2019 15:13:09 +0100 Subject: [PATCH 132/233] chore: update ipld-dag-pb to the latest version --- package.json | 4 ++-- src/dag/put.js | 3 +-- src/object/get.js | 2 +- test/dag.spec.js | 2 +- 4 files changed, 5 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index b11e359f1..b2d77bb6a 100644 --- a/package.json +++ b/package.json @@ -62,7 +62,7 @@ "ipfs-block": "~0.8.1", "ipfs-utils": "^0.4.0", "ipld-dag-cbor": "~0.15.0", - "ipld-dag-pb": "~0.17.3", + "ipld-dag-pb": "^0.18.1", "ipld-raw": "^4.0.0", "is-ipfs": "~0.6.1", "is-pull-stream": "0.0.0", @@ -108,7 +108,7 @@ "cross-env": "^6.0.0", "dirty-chai": "^2.0.1", "go-ipfs-dep": "^0.4.22", - "interface-ipfs-core": "~0.114.0", + "interface-ipfs-core": "ipfs/interface-js-ipfs-core#update-dag-pb", "ipfsd-ctl": "^0.47.1", "nock": "^11.3.2", "stream-equal": "^1.1.1" diff --git a/src/dag/put.js b/src/dag/put.js index 6cfca99c0..36da9376a 100644 --- a/src/dag/put.js +++ b/src/dag/put.js @@ -1,6 +1,5 @@ 'use strict' -const dagPB = require('ipld-dag-pb') const dagCBOR = require('ipld-dag-cbor') const promisify = require('promisify-es6') const CID = require('cids') @@ -56,7 +55,7 @@ module.exports = (send) => { if (options.format === 'dag-cbor') { serialized = dagCBOR.util.serialize(dagNode) } else if (options.format === 'dag-pb') { - serialized = dagPB.util.serialize(dagNode) + serialized = dagNode.serialize() } else { // FIXME Hopefully already serialized...can we use IPLD to serialise instead? serialized = dagNode diff --git a/src/object/get.js b/src/object/get.js index 1450c3792..5052c8af3 100644 --- a/src/object/get.js +++ b/src/object/get.js @@ -48,7 +48,7 @@ module.exports = (send) => { } const links = result.Links.map(l => new DAGLink(l.Name, l.Size, l.Hash)) - const node = DAGNode.create(Buffer.from(result.Data, 'base64'), links) + const node = new DAGNode(Buffer.from(result.Data, 'base64'), links) cache.set(cidB58Str, node) callback(null, node) diff --git a/test/dag.spec.js b/test/dag.spec.js index 8796ba72b..37433836f 100644 --- a/test/dag.spec.js +++ b/test/dag.spec.js @@ -37,7 +37,7 @@ describe('.dag', function () { it('should be able to put and get a DAG node with format dag-pb', async () => { const data = Buffer.from('some data') - const node = DAGNode.create(data) + const node = new DAGNode(data) let cid = await ipfs.dag.put(node, { format: 'dag-pb', hashAlg: 'sha2-256' }) cid = cid.toV0() From 010e786116a1751ec1ce571e080b013d0f96d379 Mon Sep 17 00:00:00 2001 From: achingbrain Date: Wed, 25 Sep 2019 08:27:04 +0100 Subject: [PATCH 133/233] chore: fix aegir command name --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index f435392ac..a6e41ebdf 100644 --- a/.travis.yml +++ b/.travis.yml @@ -23,7 +23,7 @@ jobs: - stage: check script: - npx aegir build --bundlesize - - npx aegir dep-check + - npx aegir dependency-check - npm run lint - stage: test From 944e0de452fa7478d16630c21fbd8c49027fca5c Mon Sep 17 00:00:00 2001 From: achingbrain Date: Wed, 25 Sep 2019 08:57:33 +0100 Subject: [PATCH 134/233] chore: update contributors --- package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index bb32b9fe1..5ee691e82 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ipfs-http-client", - "version": "37.0.2", + "version": "37.0.3", "description": "A client library for the IPFS HTTP API", "keywords": [ "ipfs" @@ -206,6 +206,7 @@ "leekt216 ", "nginnever ", "noah the goodra ", + "phillmac ", "priecint ", "samuli ", "shunkin ", From c2bbfae9adb2bf2155adb75d15b6bd9f6a33e8d8 Mon Sep 17 00:00:00 2001 From: achingbrain Date: Wed, 25 Sep 2019 08:57:33 +0100 Subject: [PATCH 135/233] chore: release version v37.0.3 --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c2bb8748f..5a8e6c3b2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ + +## [37.0.3](https://github.com/ipfs/js-ipfs-http-client/compare/v37.0.2...v37.0.3) (2019-09-25) + + + ## [37.0.2](https://github.com/ipfs/js-ipfs-http-client/compare/v37.0.1...v37.0.2) (2019-09-20) From 4f6892f343d67faccbd83df0ce3864c2e717fb04 Mon Sep 17 00:00:00 2001 From: achingbrain Date: Wed, 25 Sep 2019 18:13:46 +0100 Subject: [PATCH 136/233] chore: update deps --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1dfbbb312..bad699c60 100644 --- a/package.json +++ b/package.json @@ -109,7 +109,7 @@ "cross-env": "^6.0.0", "dirty-chai": "^2.0.1", "go-ipfs-dep": "^0.4.22", - "interface-ipfs-core": "ipfs/interface-js-ipfs-core#update-dag-pb", + "interface-ipfs-core": "^0.115.0", "ipfsd-ctl": "^0.47.1", "nock": "^11.3.2", "stream-equal": "^1.1.1" From be39d7231c1ba95c875bba8d8f98afc7424e1ac5 Mon Sep 17 00:00:00 2001 From: achingbrain Date: Wed, 25 Sep 2019 18:29:31 +0100 Subject: [PATCH 137/233] chore: update contributors --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index bad699c60..3ded46610 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ipfs-http-client", - "version": "37.0.3", + "version": "38.0.0", "description": "A client library for the IPFS HTTP API", "keywords": [ "ipfs" From 55e64d43230030b65cb91aa39fc8b3ec1cea1c23 Mon Sep 17 00:00:00 2001 From: achingbrain Date: Wed, 25 Sep 2019 18:29:31 +0100 Subject: [PATCH 138/233] chore: release version v38.0.0 --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5a8e6c3b2..44331f9c4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ + +# [38.0.0](https://github.com/ipfs/js-ipfs-http-client/compare/v37.0.3...v38.0.0) (2019-09-25) + + + ## [37.0.3](https://github.com/ipfs/js-ipfs-http-client/compare/v37.0.2...v37.0.3) (2019-09-25) From 1c3d92a17c85fa11dc6fdcb1e37c1e33b34d51d0 Mon Sep 17 00:00:00 2001 From: achingbrain Date: Thu, 3 Oct 2019 07:56:43 +0100 Subject: [PATCH 139/233] feat: add methods for listing config profiles New method: ```javascript Promise> ipfs.config.profiles.list() ``` BREAKING CHANGE: ```javascript Promise<{oldCfg, newCfg}> ipfs.config.profile(name, opts) // is now Promise<{old, new}> ipfs.config.profiles.apply(name, opts) ``` Possibly contentious; Adds `callbackify` as a dependency, see https://github.com/ipfs/js-ipfs/issues/2506 for discussion. --- package.json | 3 ++- src/config/index.js | 11 ++++----- src/config/{profile.js => profiles/apply.js} | 2 +- src/config/profiles/list.js | 26 ++++++++++++++++++++ test/interface.spec.js | 4 +++ 5 files changed, 38 insertions(+), 8 deletions(-) rename src/config/{profile.js => profiles/apply.js} (91%) create mode 100644 src/config/profiles/list.js diff --git a/package.json b/package.json index 3ded46610..245a63fc4 100644 --- a/package.json +++ b/package.json @@ -48,6 +48,7 @@ "bl": "^3.0.0", "bs58": "^4.0.1", "buffer": "^5.4.2", + "callbackify": "^1.1.0", "cids": "~0.7.1", "concat-stream": "github:hugomrdias/concat-stream#feat/smaller", "debug": "^4.1.0", @@ -109,7 +110,7 @@ "cross-env": "^6.0.0", "dirty-chai": "^2.0.1", "go-ipfs-dep": "^0.4.22", - "interface-ipfs-core": "^0.115.0", + "interface-ipfs-core": "ipfs/interface-js-ipfs-core#add-listing-config-profiles", "ipfsd-ctl": "^0.47.1", "nock": "^11.3.2", "stream-equal": "^1.1.1" diff --git a/src/config/index.js b/src/config/index.js index d690d8099..731df5bcb 100644 --- a/src/config/index.js +++ b/src/config/index.js @@ -1,14 +1,13 @@ 'use strict' -const moduleConfig = require('../utils/module-config') - -module.exports = (arg) => { - const send = moduleConfig(arg) - +module.exports = (send, config) => { return { get: require('./get')(send), set: require('./set')(send), replace: require('./replace')(send), - profile: require('./profile')(send) + profiles: { + apply: require('./profiles/apply')(send), + list: require('./profiles/list')(config) + } } } diff --git a/src/config/profile.js b/src/config/profiles/apply.js similarity index 91% rename from src/config/profile.js rename to src/config/profiles/apply.js index 809adb5d4..b922bbe08 100644 --- a/src/config/profile.js +++ b/src/config/profiles/apply.js @@ -27,7 +27,7 @@ module.exports = (send) => { if (err) { return callback(err) } - callback(null, { oldCfg: response.OldCfg, newCfg: response.NewCfg }) + callback(null, { old: response.OldCfg, new: response.NewCfg }) }) }) } diff --git a/src/config/profiles/list.js b/src/config/profiles/list.js new file mode 100644 index 000000000..a77fc8af6 --- /dev/null +++ b/src/config/profiles/list.js @@ -0,0 +1,26 @@ +'use strict' + +const configure = require('../../lib/configure') +const callbackify = require('callbackify') +const toCamel = require('../../lib/object-to-camel') + +module.exports = configure(({ ky }) => { + return callbackify.variadic(async (options) => { + options = options || {} + + const searchParams = new URLSearchParams(options.searchParams) + searchParams.set('stream-channels', true) + + const res = await ky.get('config/profile/list', { + timeout: options.timeout, + signal: options.signal, + headers: options.headers, + searchParams + }) + + const parsed = await res.json() + + return parsed + .map(profile => toCamel(profile)) + }) +}) diff --git a/test/interface.spec.js b/test/interface.spec.js index e3c8ffb19..b6f00342e 100644 --- a/test/interface.spec.js +++ b/test/interface.spec.js @@ -48,6 +48,10 @@ describe('interface-ipfs-core tests', () => { { name: 'replace', reason: 'FIXME Waiting for fix on go-ipfs https://github.com/ipfs/js-ipfs-http-client/pull/307#discussion_r69281789 and https://github.com/ipfs/go-ipfs/issues/2927' + }, + { + name: 'should list config profiles', + reason: 'TODO: Not implemented in go-ipfs' } ] }) From 5b53e220f1d64f63e2bb23f76cda1e488c5b192b Mon Sep 17 00:00:00 2001 From: achingbrain Date: Thu, 3 Oct 2019 08:36:17 +0100 Subject: [PATCH 140/233] fix: get correct remote node config I noticed some calls would fail during tests when the daemon was listening on non-standard ports, this was because when commands `require` other commands that use `ky`, we are passing the `ky` instance in as the sole property of an object that usually contains the host and port number of the remote node's API server. --- src/add-from-fs/index.js | 7 +++---- src/add-from-url.js | 7 +++---- src/pubsub/subscribe.js | 5 +++-- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/src/add-from-fs/index.js b/src/add-from-fs/index.js index 01a82e166..7403f7e46 100644 --- a/src/add-from-fs/index.js +++ b/src/add-from-fs/index.js @@ -1,9 +1,8 @@ 'use strict' -const configure = require('../lib/configure') const globSource = require('ipfs-utils/src/files/glob-source') -module.exports = configure(({ ky }) => { - const add = require('../add')({ ky }) +module.exports = (config) => { + const add = require('../add')(config) return (path, options) => add(globSource(path, options), options) -}) +} diff --git a/src/add-from-url.js b/src/add-from-url.js index 336906ea1..388072984 100644 --- a/src/add-from-url.js +++ b/src/add-from-url.js @@ -1,11 +1,10 @@ 'use strict' const kyDefault = require('ky-universal').default -const configure = require('./lib/configure') const toIterable = require('./lib/stream-to-iterable') -module.exports = configure(({ ky }) => { - const add = require('./add')({ ky }) +module.exports = (config) => { + const add = require('./add')(config) return (url, options) => (async function * () { options = options || {} @@ -19,4 +18,4 @@ module.exports = configure(({ ky }) => { yield * add(input, options) })() -}) +} diff --git a/src/pubsub/subscribe.js b/src/pubsub/subscribe.js index ae95ec5c8..7950a274a 100644 --- a/src/pubsub/subscribe.js +++ b/src/pubsub/subscribe.js @@ -9,9 +9,10 @@ const configure = require('../lib/configure') const toIterable = require('../lib/stream-to-iterable') const SubscriptionTracker = require('./subscription-tracker') -module.exports = configure(({ ky }) => { +module.exports = configure((config) => { + const ky = config.ky const subsTracker = SubscriptionTracker.singleton() - const publish = require('./publish')({ ky }) + const publish = require('./publish')(config) return async (topic, handler, options) => { options = options || {} From 93765c155275d2218c43d6d11082579e8782c3d4 Mon Sep 17 00:00:00 2001 From: achingbrain Date: Thu, 3 Oct 2019 12:13:30 +0100 Subject: [PATCH 141/233] fix: pull in preconfigured chai from interface tests --- package.json | 3 --- test/commands.spec.js | 7 +------ test/constructor.spec.js | 6 +----- test/custom-headers.spec.js | 6 +----- test/dag.spec.js | 7 +------ test/diag.spec.js | 6 +----- test/endpoint-config.spec.js | 6 +----- test/exports.spec.js | 5 +---- test/files-mfs.spec.js | 7 +------ test/get.spec.js | 7 +------ test/key.spec.js | 6 +----- test/lib.configure.spec.js | 6 +----- test/lib.error-handler.spec.js | 5 +---- test/lib.stream-to-iterable.spec.js | 5 +---- test/log.spec.js | 6 +----- test/node/swarm.js | 8 +------- test/ping.spec.js | 7 +------ test/repo.spec.js | 6 +----- test/request-api.spec.js | 5 +---- test/stats.spec.js | 6 +----- test/sub-modules.spec.js | 10 ++++------ 21 files changed, 23 insertions(+), 107 deletions(-) diff --git a/package.json b/package.json index 245a63fc4..ab282dfee 100644 --- a/package.json +++ b/package.json @@ -105,10 +105,7 @@ "devDependencies": { "aegir": "^20.3.1", "browser-process-platform": "~0.1.1", - "chai": "^4.2.0", - "chai-as-promised": "^7.1.1", "cross-env": "^6.0.0", - "dirty-chai": "^2.0.1", "go-ipfs-dep": "^0.4.22", "interface-ipfs-core": "ipfs/interface-js-ipfs-core#add-listing-config-profiles", "ipfsd-ctl": "^0.47.1", diff --git a/test/commands.spec.js b/test/commands.spec.js index 66072c5f9..2f7b1f5e3 100644 --- a/test/commands.spec.js +++ b/test/commands.spec.js @@ -1,13 +1,8 @@ /* eslint-env mocha */ 'use strict' -const chai = require('chai') -const dirtyChai = require('dirty-chai') -const expect = chai.expect -chai.use(dirtyChai) - +const { expect } = require('interface-ipfs-core/src/utils/mocha') const ipfsClient = require('../src') - const f = require('./utils/factory') describe('.commands', function () { diff --git a/test/constructor.spec.js b/test/constructor.spec.js index cc6a250c2..e4a7eb1aa 100644 --- a/test/constructor.spec.js +++ b/test/constructor.spec.js @@ -2,11 +2,7 @@ 'use strict' const multiaddr = require('multiaddr') -const chai = require('chai') -const dirtyChai = require('dirty-chai') -const expect = chai.expect -chai.use(dirtyChai) - +const { expect } = require('interface-ipfs-core/src/utils/mocha') const f = require('./utils/factory') const ipfsClient = require('../src/index.js') diff --git a/test/custom-headers.spec.js b/test/custom-headers.spec.js index 8d05897a6..0780c23b9 100644 --- a/test/custom-headers.spec.js +++ b/test/custom-headers.spec.js @@ -2,11 +2,7 @@ 'use strict' const isNode = require('detect-node') -const chai = require('chai') -const dirtyChai = require('dirty-chai') -const expect = chai.expect -chai.use(dirtyChai) - +const { expect } = require('interface-ipfs-core/src/utils/mocha') const ipfsClient = require('../src') const f = require('./utils/factory') diff --git a/test/dag.spec.js b/test/dag.spec.js index 37433836f..cd58002ad 100644 --- a/test/dag.spec.js +++ b/test/dag.spec.js @@ -3,12 +3,7 @@ 'use strict' -const chai = require('chai') -const dirtyChai = require('dirty-chai') -const chaiAsPromised = require('chai-as-promised') -const expect = chai.expect -chai.use(dirtyChai) -chai.use(chaiAsPromised) +const { expect } = require('interface-ipfs-core/src/utils/mocha') const { DAGNode } = require('ipld-dag-pb') const CID = require('cids') const ipfsClient = require('../src') diff --git a/test/diag.spec.js b/test/diag.spec.js index 73efbb2de..e42716214 100644 --- a/test/diag.spec.js +++ b/test/diag.spec.js @@ -1,12 +1,8 @@ /* eslint-env mocha */ 'use strict' -const chai = require('chai') -const dirtyChai = require('dirty-chai') -const expect = chai.expect -chai.use(dirtyChai) +const { expect } = require('interface-ipfs-core/src/utils/mocha') const platform = require('browser-process-platform') - const ipfsClient = require('../src') const f = require('./utils/factory') diff --git a/test/endpoint-config.spec.js b/test/endpoint-config.spec.js index 4747df274..c867717b9 100644 --- a/test/endpoint-config.spec.js +++ b/test/endpoint-config.spec.js @@ -2,12 +2,8 @@ /* eslint max-nested-callbacks: ["error", 8] */ 'use strict' -const chai = require('chai') -const dirtyChai = require('dirty-chai') -const expect = chai.expect -chai.use(dirtyChai) +const { expect } = require('interface-ipfs-core/src/utils/mocha') const isNode = require('detect-node') - const ipfsClient = require('../src') const f = require('./utils/factory') diff --git a/test/exports.spec.js b/test/exports.spec.js index 44730c5cc..f97707e13 100644 --- a/test/exports.spec.js +++ b/test/exports.spec.js @@ -9,10 +9,7 @@ const multicodec = require('multicodec') const multihash = require('multihashes') const PeerId = require('peer-id') const PeerInfo = require('peer-info') -const chai = require('chai') -const dirtyChai = require('dirty-chai') -const expect = chai.expect -chai.use(dirtyChai) +const { expect } = require('interface-ipfs-core/src/utils/mocha') const IpfsHttpClient = require('../') diff --git a/test/files-mfs.spec.js b/test/files-mfs.spec.js index d1c2e0900..203fd6eb5 100644 --- a/test/files-mfs.spec.js +++ b/test/files-mfs.spec.js @@ -2,12 +2,7 @@ /* eslint max-nested-callbacks: ["error", 8] */ 'use strict' -const chai = require('chai') -const dirtyChai = require('dirty-chai') -const chaiAsPromised = require('chai-as-promised') -const expect = chai.expect -chai.use(dirtyChai) -chai.use(chaiAsPromised) +const { expect } = require('interface-ipfs-core/src/utils/mocha') const loadFixture = require('aegir/fixtures') const mh = require('multihashes') const CID = require('cids') diff --git a/test/get.spec.js b/test/get.spec.js index 05a29ffab..304875bc7 100644 --- a/test/get.spec.js +++ b/test/get.spec.js @@ -3,12 +3,7 @@ 'use strict' -const chai = require('chai') -const dirtyChai = require('dirty-chai') -const chaiAsPromised = require('chai-as-promised') -const expect = chai.expect -chai.use(dirtyChai) -chai.use(chaiAsPromised) +const { expect } = require('interface-ipfs-core/src/utils/mocha') const loadFixture = require('aegir/fixtures') const ipfsClient = require('../src') diff --git a/test/key.spec.js b/test/key.spec.js index b332b91ba..2e4e15714 100644 --- a/test/key.spec.js +++ b/test/key.spec.js @@ -2,11 +2,7 @@ /* eslint max-nested-callbacks: ["error", 8] */ 'use strict' -const chai = require('chai') -const dirtyChai = require('dirty-chai') -const expect = chai.expect -chai.use(dirtyChai) - +const { expect } = require('interface-ipfs-core/src/utils/mocha') const ipfsClient = require('../src') const f = require('./utils/factory') diff --git a/test/lib.configure.spec.js b/test/lib.configure.spec.js index f58ca4de7..8cb56be5f 100644 --- a/test/lib.configure.spec.js +++ b/test/lib.configure.spec.js @@ -1,13 +1,9 @@ /* eslint-env mocha, browser */ 'use strict' -const chai = require('chai') -const dirtyChai = require('dirty-chai') -const expect = chai.expect -chai.use(dirtyChai) +const { expect } = require('interface-ipfs-core/src/utils/mocha') const Multiaddr = require('multiaddr') const { isBrowser, isWebWorker } = require('ipfs-utils/src/env') - const configure = require('../src/lib/configure') describe('lib/configure', () => { diff --git a/test/lib.error-handler.spec.js b/test/lib.error-handler.spec.js index d1a17d147..bdc0fc8a3 100644 --- a/test/lib.error-handler.spec.js +++ b/test/lib.error-handler.spec.js @@ -1,11 +1,8 @@ /* eslint-env mocha */ 'use strict' -const chai = require('chai') -const dirtyChai = require('dirty-chai') +const { expect } = require('interface-ipfs-core/src/utils/mocha') const { HTTPError } = require('ky-universal') -const expect = chai.expect -chai.use(dirtyChai) const throwsAsync = require('./utils/throws-async') const errorHandler = require('../src/lib/error-handler') diff --git a/test/lib.stream-to-iterable.spec.js b/test/lib.stream-to-iterable.spec.js index 6c14cac94..3ad326480 100644 --- a/test/lib.stream-to-iterable.spec.js +++ b/test/lib.stream-to-iterable.spec.js @@ -1,10 +1,7 @@ /* eslint-env mocha */ 'use strict' -const chai = require('chai') -const dirtyChai = require('dirty-chai') -const expect = chai.expect -chai.use(dirtyChai) +const { expect } = require('interface-ipfs-core/src/utils/mocha') const toIterable = require('../src/lib/stream-to-iterable') describe('lib/stream-to-iterable', () => { diff --git a/test/log.spec.js b/test/log.spec.js index 73ff556e2..a9dbc0274 100644 --- a/test/log.spec.js +++ b/test/log.spec.js @@ -2,11 +2,7 @@ /* eslint max-nested-callbacks: ["error", 8] */ 'use strict' -const chai = require('chai') -const dirtyChai = require('dirty-chai') -const expect = chai.expect -chai.use(dirtyChai) - +const { expect } = require('interface-ipfs-core/src/utils/mocha') const ipfsClient = require('../src') const f = require('./utils/factory') diff --git a/test/node/swarm.js b/test/node/swarm.js index 3ec634aea..27d377904 100644 --- a/test/node/swarm.js +++ b/test/node/swarm.js @@ -1,14 +1,8 @@ /* eslint-env mocha */ 'use strict' +const { expect } = require('interface-ipfs-core/src/utils/mocha') const nock = require('nock') -const chai = require('chai') -const dirtyChai = require('dirty-chai') -const chaiAsPromised = require('chai-as-promised') -const expect = chai.expect -chai.use(dirtyChai) -chai.use(chaiAsPromised) - const ipfsClient = require('../../src') describe('.swarm.peers', function () { diff --git a/test/ping.spec.js b/test/ping.spec.js index da141702c..46c58c890 100644 --- a/test/ping.spec.js +++ b/test/ping.spec.js @@ -1,12 +1,7 @@ /* eslint-env mocha */ 'use strict' -const chai = require('chai') -const dirtyChai = require('dirty-chai') -const chaiAsPromised = require('chai-as-promised') -const expect = chai.expect -chai.use(dirtyChai) -chai.use(chaiAsPromised) +const { expect } = require('interface-ipfs-core/src/utils/mocha') const pull = require('pull-stream/pull') const collect = require('pull-stream/sinks/collect') diff --git a/test/repo.spec.js b/test/repo.spec.js index c6306f5af..84b5a42c3 100644 --- a/test/repo.spec.js +++ b/test/repo.spec.js @@ -1,11 +1,7 @@ /* eslint-env mocha */ 'use strict' -const chai = require('chai') -const dirtyChai = require('dirty-chai') -const expect = chai.expect -chai.use(dirtyChai) - +const { expect } = require('interface-ipfs-core/src/utils/mocha') const ipfsClient = require('../src') const f = require('./utils/factory') diff --git a/test/request-api.spec.js b/test/request-api.spec.js index a9b2fcf2e..1b0858786 100644 --- a/test/request-api.spec.js +++ b/test/request-api.spec.js @@ -1,10 +1,7 @@ /* eslint-env mocha */ 'use strict' -const chai = require('chai') -const dirtyChai = require('dirty-chai') -const expect = chai.expect -chai.use(dirtyChai) +const { expect } = require('interface-ipfs-core/src/utils/mocha') const isNode = require('detect-node') const ipfsClient = require('../src/index.js') const ndjson = require('ndjson') diff --git a/test/stats.spec.js b/test/stats.spec.js index 66b76b270..0b7084d0a 100644 --- a/test/stats.spec.js +++ b/test/stats.spec.js @@ -1,11 +1,7 @@ /* eslint-env mocha */ 'use strict' -const chai = require('chai') -const dirtyChai = require('dirty-chai') -const expect = chai.expect -chai.use(dirtyChai) - +const { expect } = require('interface-ipfs-core/src/utils/mocha') const ipfsClient = require('../src') const f = require('./utils/factory') diff --git a/test/sub-modules.spec.js b/test/sub-modules.spec.js index b066b6278..fbecfe637 100644 --- a/test/sub-modules.spec.js +++ b/test/sub-modules.spec.js @@ -1,11 +1,7 @@ /* eslint-env mocha */ 'use strict' -const chai = require('chai') -const dirtyChai = require('dirty-chai') -const expect = chai.expect -chai.use(dirtyChai) - +const { expect } = require('interface-ipfs-core/src/utils/mocha') const defaultConfig = require('../src/utils/default-config.js') const config = defaultConfig() config.host = 'test' @@ -42,7 +38,9 @@ describe('submodules', () => { expect(cfg.get).to.be.a('function') expect(cfg.set).to.be.a('function') expect(cfg.replace).to.be.a('function') - expect(cfg.profile).to.be.a('function') + expect(cfg).to.have.a.property('profiles') + expect(cfg.profiles.list).to.be.a('function') + expect(cfg.profiles.apply).to.be.a('function') }) it('dht', () => { From 024a1221a09afcc4ddcfe5c75335ea2f907a66ef Mon Sep 17 00:00:00 2001 From: achingbrain Date: Thu, 3 Oct 2019 12:46:18 +0100 Subject: [PATCH 142/233] chore: specify commit of dep --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ab282dfee..bcfac457f 100644 --- a/package.json +++ b/package.json @@ -107,7 +107,7 @@ "browser-process-platform": "~0.1.1", "cross-env": "^6.0.0", "go-ipfs-dep": "^0.4.22", - "interface-ipfs-core": "ipfs/interface-js-ipfs-core#add-listing-config-profiles", + "interface-ipfs-core": "ipfs/interface-js-ipfs-core#30118c715d95582eaf65fdf8cb0ee240c504cb1e", "ipfsd-ctl": "^0.47.1", "nock": "^11.3.2", "stream-equal": "^1.1.1" From 6a7eb8ab6f58edab022c3a887b2056293bcabe62 Mon Sep 17 00:00:00 2001 From: achingbrain Date: Thu, 3 Oct 2019 12:13:30 +0100 Subject: [PATCH 143/233] fix: pull in preconfigured chai from interface tests This is to work around https://github.com/chaijs/chai/issues/1298 Fundamentally we cannot pull in chai and add plugins to it without being careful of the order of those plugins as it's a singleton. All we're really interested in is the `expect` function to just get the preconfigured one from the interface tests. --- package.json | 3 --- test/commands.spec.js | 7 +------ test/constructor.spec.js | 6 +----- test/custom-headers.spec.js | 6 +----- test/dag.spec.js | 7 +------ test/diag.spec.js | 6 +----- test/endpoint-config.spec.js | 6 +----- test/exports.spec.js | 5 +---- test/files-mfs.spec.js | 7 +------ test/get.spec.js | 7 +------ test/key.spec.js | 6 +----- test/lib.configure.spec.js | 6 +----- test/lib.error-handler.spec.js | 5 +---- test/lib.stream-to-iterable.spec.js | 5 +---- test/log.spec.js | 6 +----- test/node/swarm.js | 8 +------- test/ping.spec.js | 7 +------ test/repo.spec.js | 6 +----- test/request-api.spec.js | 5 +---- test/stats.spec.js | 6 +----- test/sub-modules.spec.js | 6 +----- 21 files changed, 20 insertions(+), 106 deletions(-) diff --git a/package.json b/package.json index 3ded46610..77d0bd50c 100644 --- a/package.json +++ b/package.json @@ -104,10 +104,7 @@ "devDependencies": { "aegir": "^20.3.1", "browser-process-platform": "~0.1.1", - "chai": "^4.2.0", - "chai-as-promised": "^7.1.1", "cross-env": "^6.0.0", - "dirty-chai": "^2.0.1", "go-ipfs-dep": "^0.4.22", "interface-ipfs-core": "^0.115.0", "ipfsd-ctl": "^0.47.1", diff --git a/test/commands.spec.js b/test/commands.spec.js index 66072c5f9..2f7b1f5e3 100644 --- a/test/commands.spec.js +++ b/test/commands.spec.js @@ -1,13 +1,8 @@ /* eslint-env mocha */ 'use strict' -const chai = require('chai') -const dirtyChai = require('dirty-chai') -const expect = chai.expect -chai.use(dirtyChai) - +const { expect } = require('interface-ipfs-core/src/utils/mocha') const ipfsClient = require('../src') - const f = require('./utils/factory') describe('.commands', function () { diff --git a/test/constructor.spec.js b/test/constructor.spec.js index cc6a250c2..e4a7eb1aa 100644 --- a/test/constructor.spec.js +++ b/test/constructor.spec.js @@ -2,11 +2,7 @@ 'use strict' const multiaddr = require('multiaddr') -const chai = require('chai') -const dirtyChai = require('dirty-chai') -const expect = chai.expect -chai.use(dirtyChai) - +const { expect } = require('interface-ipfs-core/src/utils/mocha') const f = require('./utils/factory') const ipfsClient = require('../src/index.js') diff --git a/test/custom-headers.spec.js b/test/custom-headers.spec.js index 8d05897a6..0780c23b9 100644 --- a/test/custom-headers.spec.js +++ b/test/custom-headers.spec.js @@ -2,11 +2,7 @@ 'use strict' const isNode = require('detect-node') -const chai = require('chai') -const dirtyChai = require('dirty-chai') -const expect = chai.expect -chai.use(dirtyChai) - +const { expect } = require('interface-ipfs-core/src/utils/mocha') const ipfsClient = require('../src') const f = require('./utils/factory') diff --git a/test/dag.spec.js b/test/dag.spec.js index 37433836f..cd58002ad 100644 --- a/test/dag.spec.js +++ b/test/dag.spec.js @@ -3,12 +3,7 @@ 'use strict' -const chai = require('chai') -const dirtyChai = require('dirty-chai') -const chaiAsPromised = require('chai-as-promised') -const expect = chai.expect -chai.use(dirtyChai) -chai.use(chaiAsPromised) +const { expect } = require('interface-ipfs-core/src/utils/mocha') const { DAGNode } = require('ipld-dag-pb') const CID = require('cids') const ipfsClient = require('../src') diff --git a/test/diag.spec.js b/test/diag.spec.js index 73efbb2de..e42716214 100644 --- a/test/diag.spec.js +++ b/test/diag.spec.js @@ -1,12 +1,8 @@ /* eslint-env mocha */ 'use strict' -const chai = require('chai') -const dirtyChai = require('dirty-chai') -const expect = chai.expect -chai.use(dirtyChai) +const { expect } = require('interface-ipfs-core/src/utils/mocha') const platform = require('browser-process-platform') - const ipfsClient = require('../src') const f = require('./utils/factory') diff --git a/test/endpoint-config.spec.js b/test/endpoint-config.spec.js index 4747df274..c867717b9 100644 --- a/test/endpoint-config.spec.js +++ b/test/endpoint-config.spec.js @@ -2,12 +2,8 @@ /* eslint max-nested-callbacks: ["error", 8] */ 'use strict' -const chai = require('chai') -const dirtyChai = require('dirty-chai') -const expect = chai.expect -chai.use(dirtyChai) +const { expect } = require('interface-ipfs-core/src/utils/mocha') const isNode = require('detect-node') - const ipfsClient = require('../src') const f = require('./utils/factory') diff --git a/test/exports.spec.js b/test/exports.spec.js index 44730c5cc..f97707e13 100644 --- a/test/exports.spec.js +++ b/test/exports.spec.js @@ -9,10 +9,7 @@ const multicodec = require('multicodec') const multihash = require('multihashes') const PeerId = require('peer-id') const PeerInfo = require('peer-info') -const chai = require('chai') -const dirtyChai = require('dirty-chai') -const expect = chai.expect -chai.use(dirtyChai) +const { expect } = require('interface-ipfs-core/src/utils/mocha') const IpfsHttpClient = require('../') diff --git a/test/files-mfs.spec.js b/test/files-mfs.spec.js index d1c2e0900..203fd6eb5 100644 --- a/test/files-mfs.spec.js +++ b/test/files-mfs.spec.js @@ -2,12 +2,7 @@ /* eslint max-nested-callbacks: ["error", 8] */ 'use strict' -const chai = require('chai') -const dirtyChai = require('dirty-chai') -const chaiAsPromised = require('chai-as-promised') -const expect = chai.expect -chai.use(dirtyChai) -chai.use(chaiAsPromised) +const { expect } = require('interface-ipfs-core/src/utils/mocha') const loadFixture = require('aegir/fixtures') const mh = require('multihashes') const CID = require('cids') diff --git a/test/get.spec.js b/test/get.spec.js index 05a29ffab..304875bc7 100644 --- a/test/get.spec.js +++ b/test/get.spec.js @@ -3,12 +3,7 @@ 'use strict' -const chai = require('chai') -const dirtyChai = require('dirty-chai') -const chaiAsPromised = require('chai-as-promised') -const expect = chai.expect -chai.use(dirtyChai) -chai.use(chaiAsPromised) +const { expect } = require('interface-ipfs-core/src/utils/mocha') const loadFixture = require('aegir/fixtures') const ipfsClient = require('../src') diff --git a/test/key.spec.js b/test/key.spec.js index b332b91ba..2e4e15714 100644 --- a/test/key.spec.js +++ b/test/key.spec.js @@ -2,11 +2,7 @@ /* eslint max-nested-callbacks: ["error", 8] */ 'use strict' -const chai = require('chai') -const dirtyChai = require('dirty-chai') -const expect = chai.expect -chai.use(dirtyChai) - +const { expect } = require('interface-ipfs-core/src/utils/mocha') const ipfsClient = require('../src') const f = require('./utils/factory') diff --git a/test/lib.configure.spec.js b/test/lib.configure.spec.js index f58ca4de7..8cb56be5f 100644 --- a/test/lib.configure.spec.js +++ b/test/lib.configure.spec.js @@ -1,13 +1,9 @@ /* eslint-env mocha, browser */ 'use strict' -const chai = require('chai') -const dirtyChai = require('dirty-chai') -const expect = chai.expect -chai.use(dirtyChai) +const { expect } = require('interface-ipfs-core/src/utils/mocha') const Multiaddr = require('multiaddr') const { isBrowser, isWebWorker } = require('ipfs-utils/src/env') - const configure = require('../src/lib/configure') describe('lib/configure', () => { diff --git a/test/lib.error-handler.spec.js b/test/lib.error-handler.spec.js index d1a17d147..bdc0fc8a3 100644 --- a/test/lib.error-handler.spec.js +++ b/test/lib.error-handler.spec.js @@ -1,11 +1,8 @@ /* eslint-env mocha */ 'use strict' -const chai = require('chai') -const dirtyChai = require('dirty-chai') +const { expect } = require('interface-ipfs-core/src/utils/mocha') const { HTTPError } = require('ky-universal') -const expect = chai.expect -chai.use(dirtyChai) const throwsAsync = require('./utils/throws-async') const errorHandler = require('../src/lib/error-handler') diff --git a/test/lib.stream-to-iterable.spec.js b/test/lib.stream-to-iterable.spec.js index 6c14cac94..3ad326480 100644 --- a/test/lib.stream-to-iterable.spec.js +++ b/test/lib.stream-to-iterable.spec.js @@ -1,10 +1,7 @@ /* eslint-env mocha */ 'use strict' -const chai = require('chai') -const dirtyChai = require('dirty-chai') -const expect = chai.expect -chai.use(dirtyChai) +const { expect } = require('interface-ipfs-core/src/utils/mocha') const toIterable = require('../src/lib/stream-to-iterable') describe('lib/stream-to-iterable', () => { diff --git a/test/log.spec.js b/test/log.spec.js index 73ff556e2..a9dbc0274 100644 --- a/test/log.spec.js +++ b/test/log.spec.js @@ -2,11 +2,7 @@ /* eslint max-nested-callbacks: ["error", 8] */ 'use strict' -const chai = require('chai') -const dirtyChai = require('dirty-chai') -const expect = chai.expect -chai.use(dirtyChai) - +const { expect } = require('interface-ipfs-core/src/utils/mocha') const ipfsClient = require('../src') const f = require('./utils/factory') diff --git a/test/node/swarm.js b/test/node/swarm.js index 3ec634aea..27d377904 100644 --- a/test/node/swarm.js +++ b/test/node/swarm.js @@ -1,14 +1,8 @@ /* eslint-env mocha */ 'use strict' +const { expect } = require('interface-ipfs-core/src/utils/mocha') const nock = require('nock') -const chai = require('chai') -const dirtyChai = require('dirty-chai') -const chaiAsPromised = require('chai-as-promised') -const expect = chai.expect -chai.use(dirtyChai) -chai.use(chaiAsPromised) - const ipfsClient = require('../../src') describe('.swarm.peers', function () { diff --git a/test/ping.spec.js b/test/ping.spec.js index da141702c..46c58c890 100644 --- a/test/ping.spec.js +++ b/test/ping.spec.js @@ -1,12 +1,7 @@ /* eslint-env mocha */ 'use strict' -const chai = require('chai') -const dirtyChai = require('dirty-chai') -const chaiAsPromised = require('chai-as-promised') -const expect = chai.expect -chai.use(dirtyChai) -chai.use(chaiAsPromised) +const { expect } = require('interface-ipfs-core/src/utils/mocha') const pull = require('pull-stream/pull') const collect = require('pull-stream/sinks/collect') diff --git a/test/repo.spec.js b/test/repo.spec.js index c6306f5af..84b5a42c3 100644 --- a/test/repo.spec.js +++ b/test/repo.spec.js @@ -1,11 +1,7 @@ /* eslint-env mocha */ 'use strict' -const chai = require('chai') -const dirtyChai = require('dirty-chai') -const expect = chai.expect -chai.use(dirtyChai) - +const { expect } = require('interface-ipfs-core/src/utils/mocha') const ipfsClient = require('../src') const f = require('./utils/factory') diff --git a/test/request-api.spec.js b/test/request-api.spec.js index a9b2fcf2e..1b0858786 100644 --- a/test/request-api.spec.js +++ b/test/request-api.spec.js @@ -1,10 +1,7 @@ /* eslint-env mocha */ 'use strict' -const chai = require('chai') -const dirtyChai = require('dirty-chai') -const expect = chai.expect -chai.use(dirtyChai) +const { expect } = require('interface-ipfs-core/src/utils/mocha') const isNode = require('detect-node') const ipfsClient = require('../src/index.js') const ndjson = require('ndjson') diff --git a/test/stats.spec.js b/test/stats.spec.js index 66b76b270..0b7084d0a 100644 --- a/test/stats.spec.js +++ b/test/stats.spec.js @@ -1,11 +1,7 @@ /* eslint-env mocha */ 'use strict' -const chai = require('chai') -const dirtyChai = require('dirty-chai') -const expect = chai.expect -chai.use(dirtyChai) - +const { expect } = require('interface-ipfs-core/src/utils/mocha') const ipfsClient = require('../src') const f = require('./utils/factory') diff --git a/test/sub-modules.spec.js b/test/sub-modules.spec.js index b066b6278..036c0759f 100644 --- a/test/sub-modules.spec.js +++ b/test/sub-modules.spec.js @@ -1,11 +1,7 @@ /* eslint-env mocha */ 'use strict' -const chai = require('chai') -const dirtyChai = require('dirty-chai') -const expect = chai.expect -chai.use(dirtyChai) - +const { expect } = require('interface-ipfs-core/src/utils/mocha') const defaultConfig = require('../src/utils/default-config.js') const config = defaultConfig() config.host = 'test' From 784b2efe28bdbe7516d852b70ef1a2adda3a045d Mon Sep 17 00:00:00 2001 From: achingbrain Date: Fri, 4 Oct 2019 09:36:19 +0100 Subject: [PATCH 144/233] chore: udpate interface-ipfs-core version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 77d0bd50c..e722b0eb2 100644 --- a/package.json +++ b/package.json @@ -106,7 +106,7 @@ "browser-process-platform": "~0.1.1", "cross-env": "^6.0.0", "go-ipfs-dep": "^0.4.22", - "interface-ipfs-core": "^0.115.0", + "interface-ipfs-core": "^0.115.3", "ipfsd-ctl": "^0.47.1", "nock": "^11.3.2", "stream-equal": "^1.1.1" From 7b695d42be2024dd9fc2ad8cc3d34ae65e236c02 Mon Sep 17 00:00:00 2001 From: achingbrain Date: Fri, 4 Oct 2019 12:00:09 +0100 Subject: [PATCH 145/233] chore: update contributors --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e722b0eb2..283a330c5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ipfs-http-client", - "version": "38.0.0", + "version": "38.0.1", "description": "A client library for the IPFS HTTP API", "keywords": [ "ipfs" From 10060a6b3722f9117d6c30b89518b7e800844b16 Mon Sep 17 00:00:00 2001 From: achingbrain Date: Fri, 4 Oct 2019 12:00:09 +0100 Subject: [PATCH 146/233] chore: release version v38.0.1 --- CHANGELOG.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 44331f9c4..042d947d8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,13 @@ + +## [38.0.1](https://github.com/ipfs/js-ipfs-http-client/compare/v38.0.0...v38.0.1) (2019-10-04) + + +### Bug Fixes + +* pull in preconfigured chai from interface tests ([6a7eb8a](https://github.com/ipfs/js-ipfs-http-client/commit/6a7eb8a)) + + + # [38.0.0](https://github.com/ipfs/js-ipfs-http-client/compare/v37.0.3...v38.0.0) (2019-09-25) From e11190b9e60de9c4922d3e99f6673886dd28ac8d Mon Sep 17 00:00:00 2001 From: achingbrain Date: Fri, 4 Oct 2019 14:50:45 +0100 Subject: [PATCH 147/233] chore: address pr comments --- package.json | 2 +- src/config/index.js | 2 +- src/config/profiles/apply.js | 54 +++++++++++++----------------------- src/config/profiles/list.js | 8 ++---- 4 files changed, 24 insertions(+), 42 deletions(-) diff --git a/package.json b/package.json index bcfac457f..cd0673cad 100644 --- a/package.json +++ b/package.json @@ -107,7 +107,7 @@ "browser-process-platform": "~0.1.1", "cross-env": "^6.0.0", "go-ipfs-dep": "^0.4.22", - "interface-ipfs-core": "ipfs/interface-js-ipfs-core#30118c715d95582eaf65fdf8cb0ee240c504cb1e", + "interface-ipfs-core": "^0.117.0", "ipfsd-ctl": "^0.47.1", "nock": "^11.3.2", "stream-equal": "^1.1.1" diff --git a/src/config/index.js b/src/config/index.js index 731df5bcb..e88c195b5 100644 --- a/src/config/index.js +++ b/src/config/index.js @@ -6,7 +6,7 @@ module.exports = (send, config) => { set: require('./set')(send), replace: require('./replace')(send), profiles: { - apply: require('./profiles/apply')(send), + apply: require('./profiles/apply')(config), list: require('./profiles/list')(config) } } diff --git a/src/config/profiles/apply.js b/src/config/profiles/apply.js index b922bbe08..e4b05560b 100644 --- a/src/config/profiles/apply.js +++ b/src/config/profiles/apply.js @@ -1,41 +1,27 @@ 'use strict' -const promisify = require('promisify-es6') +const callbackify = require('callbackify') +const configure = require('../../lib/configure') -const toObject = function (res, callback) { - if (Buffer.isBuffer(res)) { - callback(null, JSON.parse(res.toString())) - } else { - callback(null, res) - } -} +module.exports = configure(({ ky }) => { + return callbackify.variadic(async (profile, options) => { + options = options || {} -module.exports = (send) => { - return promisify((profile, opts, callback) => { - if (typeof opts === 'function') { - callback = opts - opts = {} - } - - opts = normalizeOpts(opts) - - send.andTransform({ - path: 'config/profile/apply', - args: profile, - qs: opts - }, toObject, (err, response) => { - if (err) { - return callback(err) + const res = await ky.post('config/profile/apply', { + timeout: options.timeout, + signal: options.signal, + headers: options.headers, + searchParams: { + arg: profile, + // can only pass strings or numbers as values https://github.com/sindresorhus/ky/issues/182 + 'dry-run': options.dryRun ? 'true' : 'false' } - callback(null, { old: response.OldCfg, new: response.NewCfg }) }) - }) -} -function normalizeOpts (opts) { - opts = opts || {} - if (typeof opts.dryRun !== 'undefined') { - opts['dry-run'] = opts.dryRun - } - return opts -} + const parsed = await res.json() + + return { + original: parsed.OldCfg, updated: parsed.NewCfg + } + }) +}) diff --git a/src/config/profiles/list.js b/src/config/profiles/list.js index a77fc8af6..dbfa579cf 100644 --- a/src/config/profiles/list.js +++ b/src/config/profiles/list.js @@ -1,21 +1,17 @@ 'use strict' -const configure = require('../../lib/configure') const callbackify = require('callbackify') +const configure = require('../../lib/configure') const toCamel = require('../../lib/object-to-camel') module.exports = configure(({ ky }) => { return callbackify.variadic(async (options) => { options = options || {} - const searchParams = new URLSearchParams(options.searchParams) - searchParams.set('stream-channels', true) - const res = await ky.get('config/profile/list', { timeout: options.timeout, signal: options.signal, - headers: options.headers, - searchParams + headers: options.headers }) const parsed = await res.json() From c824410af84812f378a86bfb861bf0ba8b7279ed Mon Sep 17 00:00:00 2001 From: achingbrain Date: Fri, 4 Oct 2019 15:57:16 +0100 Subject: [PATCH 148/233] doc: readme update --- README.md | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index def4b05e5..4e27f3db3 100644 --- a/README.md +++ b/README.md @@ -34,17 +34,27 @@ ## Table of Contents +- [Lead Maintainer](#lead-maintainer) +- [Table of Contents](#table-of-contents) - [Install](#install) - [Running the daemon with the right port](#running-the-daemon-with-the-right-port) - [Importing the module and usage](#importing-the-module-and-usage) - [Importing a sub-module and usage](#importing-a-sub-module-and-usage) - - [In a web browser through Browserify](#in-a-web-browser-through-browserify) - - [In a web browser from CDN](#in-a-web-browser-from-cdn) + - [In a web browser](#in-a-web-browser) - [CORS](#cors) + - [Custom Headers](#custom-headers) - [Usage](#usage) - - [API Docs](#api) - - [Callbacks and promises](#callbacks-and-promises) + - [API](#api) + - [Files](#files) + - [Graph](#graph) + - [Network](#network) + - [Node Management](#node-management) + - [Instance utils](#instance-utils) + - [Static types and utils](#static-types-and-utils) +- [Development](#development) + - [Testing](#testing) - [Contribute](#contribute) +- [Historical context](#historical-context) - [License](#license) ## Install @@ -313,6 +323,8 @@ const ipfs = ipfsClient({ - [`ipfs.config.get([key], [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/CONFIG.md#configget) - [`ipfs.config.replace(config, [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/CONFIG.md#configreplace) - [`ipfs.config.set(key, value, [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/CONFIG.md#configset) + - [`ipfs.config.profiles.list([callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/CONFIG.md#configprofileslist) + - [`ipfs.config.profiles.apply(name, [options], [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/CONFIG.md#configprofilesapply) - [stats](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/STATS.md) - [`ipfs.stats.bitswap([callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/STATS.md#statsbitswap) From f32da455586d6f4d0ef513421bc9f5db37fa8938 Mon Sep 17 00:00:00 2001 From: achingbrain Date: Fri, 4 Oct 2019 16:20:01 +0100 Subject: [PATCH 149/233] chore: update contributors --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 15cfe30ee..88b31c865 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ipfs-http-client", - "version": "38.0.1", + "version": "38.1.0", "description": "A client library for the IPFS HTTP API", "keywords": [ "ipfs" From 8c6f2b958ce98a3418669f427be50d20266708ee Mon Sep 17 00:00:00 2001 From: achingbrain Date: Fri, 4 Oct 2019 16:20:01 +0100 Subject: [PATCH 150/233] chore: release version v38.1.0 --- CHANGELOG.md | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 042d947d8..fc29e0bab 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,34 @@ + +# [38.1.0](https://github.com/ipfs/js-ipfs-http-client/compare/v38.0.1...v38.1.0) (2019-10-04) + + +### Bug Fixes + +* get correct remote node config ([5b53e22](https://github.com/ipfs/js-ipfs-http-client/commit/5b53e22)) +* pull in preconfigured chai from interface tests ([93765c1](https://github.com/ipfs/js-ipfs-http-client/commit/93765c1)) + + +### Features + +* add methods for listing config profiles ([1c3d92a](https://github.com/ipfs/js-ipfs-http-client/commit/1c3d92a)) + + +### BREAKING CHANGES + +* ```javascript +Promise<{oldCfg, newCfg}> ipfs.config.profile(name, opts) + +// is now +Promise<{old, new}> ipfs.config.profiles.apply(name, opts) +``` + +Possibly contentious; + +Adds `callbackify` as a dependency, see https://github.com/ipfs/js-ipfs/issues/2506 +for discussion. + + + ## [38.0.1](https://github.com/ipfs/js-ipfs-http-client/compare/v38.0.0...v38.0.1) (2019-10-04) From 038c4d99946e9706b7bea6d22f454ec78504f199 Mon Sep 17 00:00:00 2001 From: achingbrain Date: Sat, 5 Oct 2019 12:48:37 +0100 Subject: [PATCH 151/233] chore: skip some tests because there is no go implementation --- test/interface.spec.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/test/interface.spec.js b/test/interface.spec.js index b6f00342e..090246822 100644 --- a/test/interface.spec.js +++ b/test/interface.spec.js @@ -52,6 +52,10 @@ describe('interface-ipfs-core tests', () => { { name: 'should list config profiles', reason: 'TODO: Not implemented in go-ipfs' + }, + { + name: 'should strip private key from diff output', + reason: 'TODO: Not implemented in go-ipfs' } ] }) @@ -131,6 +135,14 @@ describe('interface-ipfs-core tests', () => { { name: 'should ls directory with long option', reason: 'TODO unskip when go-ipfs supports --long https://github.com/ipfs/go-ipfs/pull/6528' + }, + { + name: 'should read from outside of mfs', + reason: 'TODO not implemented in go-ipfs yet' + }, + { + name: 'should ls from outside of mfs', + reason: 'TODO not implemented in go-ipfs yet' } ] }) From 2f0eff7103e16cdb8d8fda46e60d03cb61551f98 Mon Sep 17 00:00:00 2001 From: Alex Potsides Date: Sun, 6 Oct 2019 16:52:50 +0100 Subject: [PATCH 152/233] feat: adds ipfs.block.rm method (#1123) * feat: adds ipfs.block.rm method * chore: fix up interface tests --- package.json | 2 +- src/block/index.js | 15 ++++++++++++-- src/block/rm-async-iterator.js | 37 ++++++++++++++++++++++++++++++++++ 3 files changed, 51 insertions(+), 3 deletions(-) create mode 100644 src/block/rm-async-iterator.js diff --git a/package.json b/package.json index 88b31c865..6b710afb5 100644 --- a/package.json +++ b/package.json @@ -107,7 +107,7 @@ "browser-process-platform": "~0.1.1", "cross-env": "^6.0.0", "go-ipfs-dep": "^0.4.22", - "interface-ipfs-core": "^0.117.0", + "interface-ipfs-core": "^0.117.2", "ipfsd-ctl": "^0.47.1", "nock": "^11.3.2", "stream-equal": "^1.1.1" diff --git a/src/block/index.js b/src/block/index.js index f346aa454..645f47df6 100644 --- a/src/block/index.js +++ b/src/block/index.js @@ -1,13 +1,24 @@ 'use strict' +const nodeify = require('promise-nodeify') const moduleConfig = require('../utils/module-config') +const { collectify } = require('../lib/converters') -module.exports = (arg) => { +module.exports = (arg, config) => { const send = moduleConfig(arg) + const rm = require('./rm-async-iterator')(config) return { get: require('./get')(send), stat: require('./stat')(send), - put: require('./put')(send) + put: require('./put')(send), + rm: (input, options, callback) => { + if (typeof options === 'function') { + callback = options + options = {} + } + return nodeify(collectify(rm)(input, options), callback) + }, + _rmAsyncIterator: rm } } diff --git a/src/block/rm-async-iterator.js b/src/block/rm-async-iterator.js new file mode 100644 index 000000000..b934df32b --- /dev/null +++ b/src/block/rm-async-iterator.js @@ -0,0 +1,37 @@ +'use strict' + +const CID = require('cids') +const ndjson = require('iterable-ndjson') +const configure = require('../lib/configure') +const toIterable = require('../lib/stream-to-iterable') +const toCamel = require('../lib/object-to-camel') + +module.exports = configure(({ ky }) => { + return async function * removeBlock (cid, options) { + options = options || {} + + if (!Array.isArray(cid)) { + cid = [cid] + } + + const searchParams = new URLSearchParams() + searchParams.set('stream-channels', true) + searchParams.set('force', options.force || false) + searchParams.set('quiet', options.quiet || false) + + cid.forEach(cid => { + searchParams.append('arg', new CID(cid).toString()) + }) + + const res = await ky.post('block/rm', { + timeout: options.timeout, + signal: options.signal, + headers: options.headers, + searchParams + }) + + for await (const removed of ndjson(toIterable(res.body))) { + yield toCamel(removed) + } + } +}) From ed577c6034514d2d5faa1b150967f3c0ffbb9fc2 Mon Sep 17 00:00:00 2001 From: achingbrain Date: Sun, 6 Oct 2019 17:12:15 +0100 Subject: [PATCH 153/233] chore: update contributors --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 6b710afb5..7dfe6848a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ipfs-http-client", - "version": "38.1.0", + "version": "38.2.0", "description": "A client library for the IPFS HTTP API", "keywords": [ "ipfs" @@ -120,6 +120,7 @@ "Alan Shaw ", "Alan Shaw ", "Alex Mingoia ", + "Alex Potsides ", "Antonio Tenorio-Fornés ", "Bruno Barbieri ", "Clemo ", @@ -192,7 +193,6 @@ "Victor Bjelkholm ", "Volker Mische ", "Zhiyuan Lin ", - "achingbrain ", "dirkmc ", "dmitriy ryajov ", "elsehow ", From 191f414cf832070e5c7074ad45711fd1182ef14d Mon Sep 17 00:00:00 2001 From: achingbrain Date: Sun, 6 Oct 2019 17:12:16 +0100 Subject: [PATCH 154/233] chore: release version v38.2.0 --- CHANGELOG.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index fc29e0bab..4759581ee 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,13 @@ + +# [38.2.0](https://github.com/ipfs/js-ipfs-http-client/compare/v38.1.0...v38.2.0) (2019-10-06) + + +### Features + +* adds ipfs.block.rm method ([#1123](https://github.com/ipfs/js-ipfs-http-client/issues/1123)) ([2f0eff7](https://github.com/ipfs/js-ipfs-http-client/commit/2f0eff7)) + + + # [38.1.0](https://github.com/ipfs/js-ipfs-http-client/compare/v38.0.1...v38.1.0) (2019-10-04) From d087b7276d8cafa8763675b644f8cc819911f8b1 Mon Sep 17 00:00:00 2001 From: Alex Potsides Date: Tue, 15 Oct 2019 12:19:44 +0100 Subject: [PATCH 155/233] chore: converts remaining files api to async iterators (#1124) --- package.json | 1 + src/files-regular/get-pull-stream.js | 44 --------- src/files-regular/get-readable-stream.js | 34 ------- src/files-regular/get.js | 70 +++++++------ src/files-regular/index.js | 83 +++++++++++----- src/files-regular/ls-pull-stream.js | 74 -------------- src/files-regular/ls-readable-stream.js | 72 -------------- src/files-regular/ls.js | 90 +++++++++-------- src/files-regular/refs-local-pull-stream.js | 27 ----- .../refs-local-readable-stream.js | 25 ----- src/files-regular/refs-local.js | 42 +++----- src/files-regular/refs-pull-stream.js | 34 ------- src/files-regular/refs-readable-stream.js | 32 ------ src/files-regular/refs.js | 98 ++++++++---------- src/utils/tar-stream-to-objects.js | 99 +++++++++++++------ test/get.spec.js | 17 +--- 16 files changed, 274 insertions(+), 568 deletions(-) delete mode 100644 src/files-regular/get-pull-stream.js delete mode 100644 src/files-regular/get-readable-stream.js delete mode 100644 src/files-regular/ls-pull-stream.js delete mode 100644 src/files-regular/ls-readable-stream.js delete mode 100644 src/files-regular/refs-local-pull-stream.js delete mode 100644 src/files-regular/refs-local-readable-stream.js delete mode 100644 src/files-regular/refs-pull-stream.js delete mode 100644 src/files-regular/refs-readable-stream.js diff --git a/package.json b/package.json index 7dfe6848a..4251789de 100644 --- a/package.json +++ b/package.json @@ -56,6 +56,7 @@ "detect-node": "^2.0.4", "end-of-stream": "^1.4.1", "err-code": "^2.0.0", + "event-iterator": "^1.2.0", "explain-error": "^1.0.4", "flatmap": "0.0.3", "form-data": "^2.5.1", diff --git a/src/files-regular/get-pull-stream.js b/src/files-regular/get-pull-stream.js deleted file mode 100644 index 4b2ede770..000000000 --- a/src/files-regular/get-pull-stream.js +++ /dev/null @@ -1,44 +0,0 @@ -'use strict' - -const cleanCID = require('../utils/clean-cid') -const TarStreamToObjects = require('../utils/tar-stream-to-objects') -const v = require('is-ipfs') -const pull = require('pull-stream/pull') -const map = require('pull-stream/throughs/map') -const toPull = require('stream-to-pull-stream') -const deferred = require('pull-defer') - -module.exports = (send) => { - return (path, opts) => { - opts = opts || {} - - const p = deferred.source() - - try { - path = cleanCID(path) - } catch (err) { - if (!v.ipfsPath(path)) { - return p.end(err) - } - } - - const request = { path: 'get', args: path, qs: opts } - - // Convert the response stream to TarStream objects - send.andTransform(request, TarStreamToObjects, (err, stream) => { - if (err) { return p.end(err) } - - p.resolve( - pull( - toPull.source(stream), - map(file => { - const { path, content } = file - return content ? { path, content: toPull.source(content) } : file - }) - ) - ) - }) - - return p - } -} diff --git a/src/files-regular/get-readable-stream.js b/src/files-regular/get-readable-stream.js deleted file mode 100644 index 0bace519f..000000000 --- a/src/files-regular/get-readable-stream.js +++ /dev/null @@ -1,34 +0,0 @@ -'use strict' - -const cleanCID = require('../utils/clean-cid') -const TarStreamToObjects = require('../utils/tar-stream-to-objects') -const v = require('is-ipfs') -const Stream = require('readable-stream') -const pump = require('pump') - -module.exports = (send) => { - return (path, opts) => { - opts = opts || {} - - const pt = new Stream.PassThrough({ objectMode: true }) - - try { - path = cleanCID(path) - } catch (err) { - if (!v.ipfsPath(path)) { - return pt.destroy(err) - } - } - - const request = { path: 'get', args: path, qs: opts } - - // Convert the response stream to TarStream objects - send.andTransform(request, TarStreamToObjects, (err, stream) => { - if (err) { return pt.destroy(err) } - - pump(stream, pt) - }) - - return pt - } -} diff --git a/src/files-regular/get.js b/src/files-regular/get.js index 045158d88..6c942648b 100644 --- a/src/files-regular/get.js +++ b/src/files-regular/get.js @@ -1,52 +1,48 @@ 'use strict' -const promisify = require('promisify-es6') +const configure = require('../lib/configure') +const tarStreamToObjects = require('../utils/tar-stream-to-objects') +const IsIpfs = require('is-ipfs') const cleanCID = require('../utils/clean-cid') -const TarStreamToObjects = require('../utils/tar-stream-to-objects') -const concat = require('concat-stream') -const through = require('through2') -const v = require('is-ipfs') - -module.exports = (send) => { - return promisify((path, opts, callback) => { - if (typeof opts === 'function' && !callback) { - callback = opts - opts = {} - } - // opts is the real callback -- - // 'callback' is being injected by promisify - if (typeof opts === 'function' && typeof callback === 'function') { - callback = opts - opts = {} - } +module.exports = configure(({ ky }) => { + return async function * get (path, options) { + options = options || {} try { path = cleanCID(path) } catch (err) { - if (!v.ipfsPath(path)) { - return callback(err) + if (!IsIpfs.ipfsPath(path)) { + throw err } } - const request = { path: 'get', args: path, qs: opts } + const searchParams = new URLSearchParams() + searchParams.set('arg', path.toString()) - // Convert the response stream to TarStream objects - send.andTransform(request, TarStreamToObjects, (err, stream) => { - if (err) { return callback(err) } + if (options.compress !== undefined) { + searchParams.set('compress', options.compress) + } - const files = [] + if (options.compressionLevel !== undefined) { + searchParams.set('compression-level', options.compressionLevel) + } - stream.pipe(through.obj((file, enc, next) => { - if (file.content) { - file.content.pipe(concat((content) => { - files.push({ path: file.path, content: content }) - })) - } else { - files.push(file) - } - next() - }, () => callback(null, files))) + if (options.offset) { + searchParams.set('offset', options.offset) + } + + if (options.length) { + searchParams.set('length', options.length) + } + + const res = await ky.get('get', { + timeout: options.timeout, + signal: options.signal, + headers: options.headers, + searchParams }) - }) -} + + yield * tarStreamToObjects(res.body) + } +}) diff --git a/src/files-regular/index.js b/src/files-regular/index.js index 9bfe10a5d..3381102d5 100644 --- a/src/files-regular/index.js +++ b/src/files-regular/index.js @@ -1,17 +1,24 @@ 'use strict' const nodeify = require('promise-nodeify') -const moduleConfig = require('../utils/module-config') +const callbackify = require('callbackify') +const all = require('async-iterator-all') const { concatify, collectify, pullify, streamify } = require('../lib/converters') +const toPullStream = require('async-iterator-to-pull-stream') +const pull = require('pull-stream/pull') +const map = require('pull-stream/throughs/map') -module.exports = (arg) => { - const send = moduleConfig(arg) - const add = require('../add')(arg) - const addFromFs = require('../add-from-fs')(arg) - const addFromURL = require('../add-from-url')(arg) - const cat = require('../cat')(arg) +module.exports = (config) => { + const add = require('../add')(config) + const addFromFs = require('../add-from-fs')(config) + const addFromURL = require('../add-from-url')(config) + const cat = require('../cat')(config) + const get = require('./get')(config) + const ls = require('./ls')(config) + const refs = require('./refs')(config) + const refsLocal = require('./refs-local')(config) - return { + const api = { add: (input, options, callback) => { if (typeof options === 'function') { callback = options @@ -43,23 +50,51 @@ module.exports = (arg) => { return nodeify(collectify(add)(input, options), callback) }, _addAsyncIterator: add, - cat: (path, options, callback) => { - if (typeof options === 'function') { - callback = options - options = {} - } - return nodeify(concatify(cat)(path, options), callback) - }, + cat: callbackify.variadic((path, options) => concatify(cat)(path, options)), catReadableStream: streamify.readable(cat), catPullStream: pullify.source(cat), - get: require('../files-regular/get')(send), - getReadableStream: require('../files-regular/get-readable-stream')(send), - getPullStream: require('../files-regular/get-pull-stream')(send), - ls: require('../files-regular/ls')(send), - lsReadableStream: require('../files-regular/ls-readable-stream')(send), - lsPullStream: require('../files-regular/ls-pull-stream')(send), - refs: require('../files-regular/refs')(send), - refsReadableStream: require('../files-regular/refs-readable-stream')(send), - refsPullStream: require('../files-regular/refs-pull-stream')(send) + _catAsyncIterator: cat, + get: callbackify.variadic(async (path, options) => { + const output = [] + + for await (const entry of get(path, options)) { + if (entry.content) { + entry.content = Buffer.concat(await all(entry.content)) + } + + output.push(entry) + } + + return output + }), + getReadableStream: streamify.readable(get), + getPullStream: (path, options) => { + return pull( + toPullStream(get(path, options)), + map(file => { + if (file.content) { + file.content = toPullStream(file.content) + } + + return file + }) + ) + }, + _getAsyncIterator: get, + ls: callbackify.variadic((path, options) => collectify(ls)(path, options)), + lsReadableStream: streamify.readable(ls), + lsPullStream: pullify.source(ls), + _lsAsyncIterator: ls, + refs: callbackify.variadic((path, options) => collectify(refs)(path, options)), + refsReadableStream: streamify.readable(refs), + refsPullStream: pullify.source(refs), + _refsAsyncIterator: refs } + + api.refs.local = callbackify.variadic((options) => collectify(refsLocal)(options)) + api.refs.localReadableStream = streamify.readable(refsLocal) + api.refs.localPullStream = pullify.source(refsLocal) + api.refs._localAsyncIterator = refsLocal + + return api } diff --git a/src/files-regular/ls-pull-stream.js b/src/files-regular/ls-pull-stream.js deleted file mode 100644 index d1e238df0..000000000 --- a/src/files-regular/ls-pull-stream.js +++ /dev/null @@ -1,74 +0,0 @@ -'use strict' - -const moduleConfig = require('../utils/module-config') -const values = require('pull-stream/sources/values') -const deferred = require('pull-defer') -const IsIpfs = require('is-ipfs') -const cleanCID = require('../utils/clean-cid') - -module.exports = (arg) => { - const send = moduleConfig(arg) - - return (args, opts, callback) => { - if (typeof (opts) === 'function') { - callback = opts - opts = {} - } - - try { - args = cleanCID(args) - } catch (err) { - if (!IsIpfs.ipfsPath(args)) { - return callback(err) - } - } - - const p = deferred.source() - - send({ path: 'ls', args: args, qs: opts }, (err, results) => { - if (err) { - return callback(err) - } - - let result = results.Objects - if (!result) { - return callback(new Error('expected .Objects in results')) - } - - result = result[0] - if (!result) { - return callback(new Error('expected one array in results.Objects')) - } - - result = result.Links - if (!Array.isArray(result)) { - return callback(new Error('expected one array in results.Objects[0].Links')) - } - - result = result.map((link) => ({ - depth: 1, - name: link.Name, - path: args + '/' + link.Name, - size: link.Size, - hash: link.Hash, - type: typeOf(link) - })) - - p.resolve(values(result)) - }) - - return p - } -} - -function typeOf (link) { - switch (link.Type) { - case 1: - case 5: - return 'dir' - case 2: - return 'file' - default: - return 'unknown' - } -} diff --git a/src/files-regular/ls-readable-stream.js b/src/files-regular/ls-readable-stream.js deleted file mode 100644 index 7ee980e31..000000000 --- a/src/files-regular/ls-readable-stream.js +++ /dev/null @@ -1,72 +0,0 @@ -'use strict' - -const moduleConfig = require('../utils/module-config') -const Stream = require('readable-stream') -const IsIpfs = require('is-ipfs') -const cleanCID = require('../utils/clean-cid') - -module.exports = (arg) => { - const send = moduleConfig(arg) - - return (args, opts, callback) => { - if (typeof (opts) === 'function') { - callback = opts - opts = {} - } - - try { - args = cleanCID(args) - } catch (err) { - if (!IsIpfs.ipfsPath(args)) { - return callback(err) - } - } - - const pt = new Stream.PassThrough({ objectMode: true }) - - send({ path: 'ls', args: args, qs: opts }, (err, results) => { - if (err) { return callback(err) } - - let result = results.Objects - if (!result) { - return callback(new Error('expected .Objects in results')) - } - - result = result[0] - if (!result) { - return callback(new Error('expected one array in results.Objects')) - } - - result = result.Links - if (!Array.isArray(result)) { - return callback(new Error('expected one array in results.Objects[0].Links')) - } - - result = result.map((link) => ({ - depth: 1, - name: link.Name, - path: args + '/' + link.Name, - size: link.Size, - hash: link.Hash, - type: typeOf(link) - })) - - result.forEach((item) => pt.write(item)) - pt.end() - }) - - return pt - } -} - -function typeOf (link) { - switch (link.Type) { - case 1: - case 5: - return 'dir' - case 2: - return 'file' - default: - return 'unknown' - } -} diff --git a/src/files-regular/ls.js b/src/files-regular/ls.js index 8fbc2d16e..0f13f556d 100644 --- a/src/files-regular/ls.js +++ b/src/files-regular/ls.js @@ -1,64 +1,72 @@ 'use strict' -const promisify = require('promisify-es6') const IsIpfs = require('is-ipfs') -const moduleConfig = require('../utils/module-config') const cleanCID = require('../utils/clean-cid') +const configure = require('../lib/configure') -module.exports = (arg) => { - const send = moduleConfig(arg) - - return promisify((args, opts, callback) => { - if (typeof (opts) === 'function') { - callback = opts - opts = {} - } +module.exports = configure(({ ky }) => { + return async function * ls (path, options) { + options = options || {} try { - args = cleanCID(args) + path = cleanCID(path) } catch (err) { - if (!IsIpfs.ipfsPath(args)) { - return callback(err) + if (!IsIpfs.ipfsPath(path)) { + throw err } } - send({ - path: 'ls', - args: args, - qs: opts - }, (err, results) => { - if (err) { - return callback(err) - } + const searchParams = new URLSearchParams() + searchParams.set('arg', path.toString()) - let result = results.Objects - if (!result) { - return callback(new Error('expected .Objects in results')) - } + if (options.long !== undefined) { + searchParams.set('long', options.long) + } - result = result[0] - if (!result) { - return callback(new Error('expected one array in results.Objects')) - } + if (options.unsorted !== undefined) { + searchParams.set('unsorted', options.unsorted) + } - result = result.Links - if (!Array.isArray(result)) { - return callback(new Error('expected one array in results.Objects[0].Links')) - } + if (options.recursive !== undefined) { + searchParams.set('recursive', options.recursive) + } + + const res = await ky.get('ls', { + timeout: options.timeout, + signal: options.signal, + headers: options.headers, + searchParams + }) + + let result = await res.json() - result = result.map((link) => ({ + result = result.Objects + if (!result) { + throw new Error('expected .Objects in results') + } + + result = result[0] + if (!result) { + throw new Error('expected one array in results.Objects') + } + + result = result.Links + if (!Array.isArray(result)) { + throw new Error('expected one array in results.Objects[0].Links') + } + + for (const link of result) { + yield { name: link.Name, - path: args + '/' + link.Name, + path: path + '/' + link.Name, size: link.Size, hash: link.Hash, type: typeOf(link), depth: link.Depth || 1 - })) - - callback(null, result) - }) - }) -} + } + } + } +}) function typeOf (link) { switch (link.Type) { diff --git a/src/files-regular/refs-local-pull-stream.js b/src/files-regular/refs-local-pull-stream.js deleted file mode 100644 index c4452b116..000000000 --- a/src/files-regular/refs-local-pull-stream.js +++ /dev/null @@ -1,27 +0,0 @@ -'use strict' - -const pull = require('pull-stream') -const toPull = require('stream-to-pull-stream') -const deferred = require('pull-defer') -const moduleConfig = require('../utils/module-config') - -module.exports = (send) => { - send = moduleConfig(send) - - return (opts) => { - opts = opts || {} - - const p = deferred.source() - - send({ path: 'refs/local', qs: opts }, (err, stream) => { - if (err) { return p.resolve(pull.error(err)) } - - p.resolve(pull( - toPull.source(stream), - pull.map(r => ({ ref: r.Ref, err: r.Err })) - )) - }) - - return p - } -} diff --git a/src/files-regular/refs-local-readable-stream.js b/src/files-regular/refs-local-readable-stream.js deleted file mode 100644 index 09fddde1d..000000000 --- a/src/files-regular/refs-local-readable-stream.js +++ /dev/null @@ -1,25 +0,0 @@ -'use strict' - -const Stream = require('readable-stream') -const pump = require('pump') -const through = require('through2') - -module.exports = (send) => { - return (opts) => { - opts = opts || {} - - const pt = new Stream.PassThrough({ objectMode: true }) - - send({ path: 'refs/local', qs: opts }, (err, stream) => { - if (err) { return pt.destroy(err) } - - stream.once('error', (err) => pt.destroy(err)) - - pump(stream, through.obj(function (r, enc, cb) { - cb(null, { ref: r.Ref, err: r.Err }) - }), pt) - }) - - return pt - } -} diff --git a/src/files-regular/refs-local.js b/src/files-regular/refs-local.js index 680e51000..efb8d32d2 100644 --- a/src/files-regular/refs-local.js +++ b/src/files-regular/refs-local.js @@ -1,32 +1,22 @@ 'use strict' -const promisify = require('promisify-es6') -const streamToValueWithTransformer = require('../utils/stream-to-value-with-transformer') -const moduleConfig = require('../utils/module-config') +const configure = require('../lib/configure') +const ndjson = require('iterable-ndjson') +const toIterable = require('../lib/stream-to-iterable') +const toCamel = require('../lib/object-to-camel') -module.exports = (arg) => { - const send = moduleConfig(arg) +module.exports = configure(({ ky }) => { + return async function * refsLocal (options) { + options = options || {} - return promisify((opts, callback) => { - if (typeof (opts) === 'function') { - callback = opts - opts = {} - } - - const transform = (res, cb) => { - cb(null, res.map(r => ({ ref: r.Ref, err: r.Err }))) - } + const res = await ky.get('refs/local', { + timeout: options.timeout, + signal: options.signal, + headers: options.headers + }) - const request = { - path: 'refs/local', - qs: opts + for await (const file of ndjson(toIterable(res.body))) { + yield toCamel(file) } - send(request, (err, result) => { - if (err) { - return callback(err) - } - - streamToValueWithTransformer(result, transform, callback) - }) - }) -} + } +}) diff --git a/src/files-regular/refs-pull-stream.js b/src/files-regular/refs-pull-stream.js deleted file mode 100644 index e3c1b113a..000000000 --- a/src/files-regular/refs-pull-stream.js +++ /dev/null @@ -1,34 +0,0 @@ -'use strict' - -const pull = require('pull-stream') -const toPull = require('stream-to-pull-stream') -const deferred = require('pull-defer') -const moduleConfig = require('../utils/module-config') -const { checkArgs, normalizeOpts } = require('./refs') - -module.exports = (send) => { - send = moduleConfig(send) - - return (args, opts) => { - opts = normalizeOpts(opts) - - const p = deferred.source() - - try { - args = checkArgs(args) - } catch (err) { - return p.end(err) - } - - send({ path: 'refs', args, qs: opts }, (err, stream) => { - if (err) { return p.resolve(pull.error(err)) } - - p.resolve(pull( - toPull.source(stream), - pull.map(r => ({ ref: r.Ref, err: r.Err })) - )) - }) - - return p - } -} diff --git a/src/files-regular/refs-readable-stream.js b/src/files-regular/refs-readable-stream.js deleted file mode 100644 index b5cf69c48..000000000 --- a/src/files-regular/refs-readable-stream.js +++ /dev/null @@ -1,32 +0,0 @@ -'use strict' - -const Stream = require('readable-stream') -const pump = require('pump') -const through = require('through2') -const { checkArgs, normalizeOpts } = require('./refs') - -module.exports = (send) => { - return (args, opts) => { - opts = normalizeOpts(opts) - - const pt = new Stream.PassThrough({ objectMode: true }) - - try { - args = checkArgs(args) - } catch (err) { - return pt.destroy(err) - } - - send({ path: 'refs', args, qs: opts }, (err, stream) => { - if (err) { return pt.destroy(err) } - - stream.once('error', (err) => pt.destroy(err)) - - pump(stream, through.obj(function (r, enc, cb) { - cb(null, { ref: r.Ref, err: r.Err }) - }), pt) - }) - - return pt - } -} diff --git a/src/files-regular/refs.js b/src/files-regular/refs.js index 986a6f6cc..c6136ede5 100644 --- a/src/files-regular/refs.js +++ b/src/files-regular/refs.js @@ -1,75 +1,63 @@ 'use strict' -const IsIpfs = require('is-ipfs') -const promisify = require('promisify-es6') -const streamToValueWithTransformer = require('../utils/stream-to-value-with-transformer') -const moduleConfig = require('../utils/module-config') +const configure = require('../lib/configure') const cleanCID = require('../utils/clean-cid') +const IsIpfs = require('is-ipfs') +const ndjson = require('iterable-ndjson') +const toIterable = require('../lib/stream-to-iterable') +const toCamel = require('../lib/object-to-camel') -module.exports = (arg) => { - const send = moduleConfig(arg) +module.exports = configure(({ ky }) => { + return async function * refs (args, options) { + options = options || {} - const refs = promisify((args, opts, callback) => { - if (typeof (opts) === 'function') { - callback = opts - opts = {} - } - opts = module.exports.normalizeOpts(opts) + const searchParams = new URLSearchParams() - try { - args = module.exports.checkArgs(args) - } catch (err) { - return callback(err) + if (options.format !== undefined) { + searchParams.set('format', options.format) } - const transform = (res, cb) => { - cb(null, res.map(r => ({ ref: r.Ref, err: r.Err }))) + if (options.edges !== undefined) { + searchParams.set('edges', options.edges) } - const request = { - args, - path: 'refs', - qs: opts + if (options.unique !== undefined) { + searchParams.set('unique', options.unique) } - send(request, (err, result) => { - if (err) { - return callback(err) - } - streamToValueWithTransformer(result, transform, callback) - }) - }) - - refs.local = require('./refs-local')(arg) - refs.localReadableStream = require('./refs-local-readable-stream')(arg) - refs.localPullStream = require('./refs-local-pull-stream')(arg) + if (options.recursive !== undefined) { + searchParams.set('recursive', options.recursive) + } - return refs -} + if (options.maxDepth !== undefined) { + searchParams.set('max-depth', options.maxDepth) + } -module.exports.checkArgs = (args) => { - const isArray = Array.isArray(args) - args = isArray ? args : [args] + if (!Array.isArray(args)) { + args = [args] + } - const res = [] - for (let arg of args) { - try { - arg = cleanCID(arg) - } catch (err) { - if (!IsIpfs.ipfsPath(arg)) { - throw err + for (let arg of args) { + try { + arg = cleanCID(arg) + } catch (err) { + if (!IsIpfs.ipfsPath(arg)) { + throw err + } } + + searchParams.append('arg', arg.toString()) } - res.push(arg) - } - return isArray ? res : res[0] -} + const res = await ky.get('refs', { + timeout: options.timeout, + signal: options.signal, + headers: options.headers, + searchParams + }) -module.exports.normalizeOpts = (opts) => { - opts = opts || {} - if (typeof opts.maxDepth === 'number') { - opts['max-depth'] = opts.maxDepth + for await (const file of ndjson(toIterable(res.body))) { + yield toCamel(file) + } } - return opts -} +}) diff --git a/src/utils/tar-stream-to-objects.js b/src/utils/tar-stream-to-objects.js index 724544583..7241b3445 100644 --- a/src/utils/tar-stream-to-objects.js +++ b/src/utils/tar-stream-to-objects.js @@ -1,48 +1,85 @@ 'use strict' -const pump = require('pump') const tar = require('tar-stream') -const ReadableStream = require('readable-stream').Readable +const { EventIterator } = require('event-iterator') -class ObjectsStreams extends ReadableStream { - constructor (options) { - const opts = Object.assign(options || {}, { objectMode: true }) - super(opts) - } +function pipe (reader, writable) { + reader.read() + .then(({ done, value }) => { + if (done) { + writable.end() + + return + } + + if (value) { + const beneathHighWaterMark = writable.write(value) - _read () {} + if (beneathHighWaterMark) { + pipe(reader, writable) + } else { + writable.once('drain', () => { + pipe(reader, writable) + }) + } + } + }, (err) => { + writable.emit('error', err) + }) } /* - Transform a tar stream into a stream of objects: + Transform a tar readable stream into an async iterator of objects: Output format: - { path: 'string', content: Stream } + { path: 'string', content: AsyncIterator } */ -const TarStreamToObjects = (inputStream, callback) => { - const outputStream = new ObjectsStreams() +async function * tarStreamToObjects (inputStream) { const extractStream = tar.extract() + let onEntry + + const tarStream = new EventIterator( + (push, stop, fail) => { + onEntry = (header, stream, next) => { + push({ header, stream }) - extractStream - .on('entry', (header, stream, next) => { - stream.on('end', next) - - if (header.type !== 'directory') { - outputStream.push({ - path: header.name, - content: stream - }) - } else { - outputStream.push({ - path: header.name - }) - stream.resume() + next() } - }) - .on('finish', () => outputStream.push(null)) - pump(inputStream, extractStream) - callback(null, outputStream) + extractStream.addListener('entry', onEntry) + extractStream.addListener('finish', stop) + extractStream.addListener('error', fail) + }, + (push, stop, fail) => { + extractStream.removeListener('entry', onEntry) + extractStream.removeListener('finish', stop) + extractStream.removeListener('error', fail) + extractStream.destroy() + } + ) + + if (inputStream.pipe) { + // node stream + inputStream.pipe(extractStream) + } else if (inputStream.getReader) { + // browser readable stream + pipe(inputStream.getReader(), extractStream) + } else { + throw new Error('Unknown stream type') + } + + for await (const { header, stream } of tarStream) { + if (header.type === 'directory') { + yield { + path: header.name + } + } else { + yield { + path: header.name, + content: stream + } + } + } } -module.exports = TarStreamToObjects +module.exports = tarStreamToObjects diff --git a/test/get.spec.js b/test/get.spec.js index 304875bc7..7c1a63e74 100644 --- a/test/get.spec.js +++ b/test/get.spec.js @@ -59,7 +59,7 @@ describe('.get (specific go-ipfs features)', function () { it('err with out of range compression level', async () => { await expect(ipfs.get(smallFile.cid, { compress: true, - 'compression-level': 10 + compressionLevel: 10 })).to.be.rejectedWith('compression level must be between 1 and 9') }) @@ -83,18 +83,11 @@ describe('.get (specific go-ipfs features)', function () { it('get path containing "+"s', async () => { const cid = 'QmPkmARcqjo5fqK1V1o8cFsuaXxWYsnwCNLJUYS4KeZyff' - let count = 0 const files = await ipfs.get(cid) - files.forEach((file) => { - if (file.path !== cid) { - count++ - expect(file.path).to.contain('+') - - if (count === 2) { - // done() - } - } - }) + expect(files).to.be.an('array').with.lengthOf(3) + expect(files[0]).to.have.property('path', cid) + expect(files[1]).to.have.property('path', `${cid}/c++files`) + expect(files[2]).to.have.property('path', `${cid}/c++files/ti,c64x+mega++mod-pic.txt`) }) }) From df3d1809e8e22fd5e8bf4fca587bd0ff413b9bd2 Mon Sep 17 00:00:00 2001 From: achingbrain Date: Tue, 15 Oct 2019 13:05:01 +0100 Subject: [PATCH 156/233] chore: update deps --- package.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 4251789de..85056de5c 100644 --- a/package.json +++ b/package.json @@ -45,7 +45,7 @@ "async-iterator-all": "^1.0.0", "async-iterator-to-pull-stream": "^1.3.0", "bignumber.js": "^9.0.0", - "bl": "^3.0.0", + "bl": "^4.0.0", "bs58": "^4.0.1", "buffer": "^5.4.2", "callbackify": "^1.1.0", @@ -72,13 +72,13 @@ "is-stream": "^2.0.0", "iso-stream-http": "~0.1.2", "iso-url": "~0.4.6", - "it-glob": "0.0.4", + "it-glob": "0.0.6", "it-to-stream": "^0.1.1", "iterable-ndjson": "^1.1.0", "just-kebab-case": "^1.1.0", "just-map-keys": "^1.1.0", "kind-of": "^6.0.2", - "ky": "^0.14.0", + "ky": "^0.15.0", "ky-universal": "^0.3.0", "lru-cache": "^5.1.1", "merge-options": "^1.0.1", From 3dccc1ce1b8788451d1d6dfe196c2fe17c797ae5 Mon Sep 17 00:00:00 2001 From: achingbrain Date: Tue, 15 Oct 2019 14:01:27 +0100 Subject: [PATCH 157/233] chore: update contributors --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 85056de5c..1c446e65f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ipfs-http-client", - "version": "38.2.0", + "version": "39.0.0", "description": "A client library for the IPFS HTTP API", "keywords": [ "ipfs" @@ -121,7 +121,6 @@ "Alan Shaw ", "Alan Shaw ", "Alex Mingoia ", - "Alex Potsides ", "Antonio Tenorio-Fornés ", "Bruno Barbieri ", "Clemo ", @@ -194,6 +193,7 @@ "Victor Bjelkholm ", "Volker Mische ", "Zhiyuan Lin ", + "achingbrain ", "dirkmc ", "dmitriy ryajov ", "elsehow ", From a5aa1392d01418a9618eee65328a74713bbae94d Mon Sep 17 00:00:00 2001 From: achingbrain Date: Tue, 15 Oct 2019 14:01:28 +0100 Subject: [PATCH 158/233] chore: release version v39.0.0 --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4759581ee..98ae6bc31 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ + +# [39.0.0](https://github.com/ipfs/js-ipfs-http-client/compare/v38.2.0...v39.0.0) (2019-10-15) + + + # [38.2.0](https://github.com/ipfs/js-ipfs-http-client/compare/v38.1.0...v38.2.0) (2019-10-06) From c82b03193184f87404bb8663e6ffd2cf00be1b08 Mon Sep 17 00:00:00 2001 From: Alex Potsides Date: Thu, 17 Oct 2019 11:25:11 +0100 Subject: [PATCH 159/233] fix: expose preload argument (#1129) --- src/add/index.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/add/index.js b/src/add/index.js index 34a5d33bd..ea85a6a0b 100644 --- a/src/add/index.js +++ b/src/add/index.js @@ -28,6 +28,7 @@ module.exports = configure(({ ky }) => { if (options.silent) searchParams.set('silent', options.silent) if (options.trickle != null) searchParams.set('trickle', options.trickle) if (options.wrapWithDirectory != null) searchParams.set('wrap-with-directory', options.wrapWithDirectory) + if (options.preload !== null) searchParams.set('preload', options.preload) const res = await ky.post('add', { timeout: options.timeout, From 25b6043b409f2d5eaa5da8f58a998fc556465e9a Mon Sep 17 00:00:00 2001 From: Alex Potsides Date: Mon, 21 Oct 2019 15:30:16 +0100 Subject: [PATCH 160/233] fix: increase default timeout and respect value passed to `ky.extend` (#1130) * fix: disable timeout if not set Some of our operations take a really long time, if we don't set a timeout for `ky` we get the default of 10 seconds. This PR sets the timeout to `false` if one is not explicitly passed which disables it. Nb. I had to add the default to `false` to every invocation. Looking at the code it should be enough to do it in `src/lib/configure.js` but it doesn't seem to be. * fix: use `ignoreUndefined` merge-options option * chore: update bundle size * chore: remove git url --- .aegir.js | 2 +- package.json | 2 +- src/lib/configure.js | 38 ++++++++++++++++++++++++++++---------- 3 files changed, 30 insertions(+), 12 deletions(-) diff --git a/.aegir.js b/.aegir.js index 9a75337d1..847d73a9b 100644 --- a/.aegir.js +++ b/.aegir.js @@ -9,7 +9,7 @@ const echoServer = EchoServer.createServer() const echoServerStart = promisify(echoServer.start) const echoServerStop = promisify(echoServer.stop) module.exports = { - bundlesize: { maxSize: '245kB' }, + bundlesize: { maxSize: '246kB' }, webpack: { resolve: { mainFields: ['browser', 'main'] diff --git a/package.json b/package.json index 1c446e65f..4c608ba11 100644 --- a/package.json +++ b/package.json @@ -81,7 +81,7 @@ "ky": "^0.15.0", "ky-universal": "^0.3.0", "lru-cache": "^5.1.1", - "merge-options": "^1.0.1", + "merge-options": "^2.0.0", "multiaddr": "^6.0.6", "multibase": "~0.6.0", "multicodec": "~0.5.1", diff --git a/src/lib/configure.js b/src/lib/configure.js index a9036d1cd..8401683f9 100644 --- a/src/lib/configure.js +++ b/src/lib/configure.js @@ -5,6 +5,7 @@ const ky = require('ky-universal').default const { isBrowser, isWebWorker } = require('ipfs-utils/src/env') const { toUri } = require('./multiaddr') const errorHandler = require('./error-handler') +const mergeOptions = require('merge-options').bind({ ignoreUndefined: true }) // Set default configuration and call create function with them module.exports = create => config => { @@ -22,17 +23,26 @@ module.exports = create => config => { config.apiAddr = config.apiAddr.startsWith('/') ? toUri(config.apiAddr) : config.apiAddr config.apiPath = config.apiPath || config['api-path'] || '/api/v0' + // TODO configure ky to use config.fetch when this is released: + // https://github.com/sindresorhus/ky/pull/153 + const defaults = { + prefixUrl: config.apiAddr + config.apiPath, + timeout: config.timeout || 60000 * 20, + headers: config.headers, + hooks: { + afterResponse: [errorHandler] + } + } + const k = ky.extend(defaults) + const client = ['get', 'post', 'put', 'delete', 'patch', 'head'] + .reduce((client, key) => { + client[key] = wrap(k[key], defaults) + + return client + }, wrap(k, defaults)) + return create({ - // TODO configure ky to use config.fetch when this is released: - // https://github.com/sindresorhus/ky/pull/153 - ky: ky.extend({ - prefixUrl: config.apiAddr + config.apiPath, - timeout: config.timeout || 60 * 1000, - headers: config.headers, - hooks: { - afterResponse: [errorHandler] - } - }), + ky: client, ...config }) } @@ -57,3 +67,11 @@ function getDefaultApiAddr ({ protocol, host, port }) { return `${protocol || 'http'}://${host || 'localhost'}:${port || 5001}` } + +// returns the passed function wrapped in a function that ignores +// undefined values in the passed `options` object +function wrap (fn, defaults) { + return (input, options) => { + return fn(input, mergeOptions(defaults, options)) + } +} From 62a196db7edea468713870095b3373767c8cf599 Mon Sep 17 00:00:00 2001 From: achingbrain Date: Mon, 21 Oct 2019 15:54:37 +0100 Subject: [PATCH 161/233] chore: update contributors --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 4c608ba11..702e159a8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ipfs-http-client", - "version": "39.0.0", + "version": "39.0.1", "description": "A client library for the IPFS HTTP API", "keywords": [ "ipfs" @@ -121,6 +121,7 @@ "Alan Shaw ", "Alan Shaw ", "Alex Mingoia ", + "Alex Potsides ", "Antonio Tenorio-Fornés ", "Bruno Barbieri ", "Clemo ", @@ -193,7 +194,6 @@ "Victor Bjelkholm ", "Volker Mische ", "Zhiyuan Lin ", - "achingbrain ", "dirkmc ", "dmitriy ryajov ", "elsehow ", From 91ee5b3aaab538680c0442d54a98c6f6a1c66e97 Mon Sep 17 00:00:00 2001 From: achingbrain Date: Mon, 21 Oct 2019 15:54:37 +0100 Subject: [PATCH 162/233] chore: release version v39.0.1 --- CHANGELOG.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 98ae6bc31..73faad621 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,14 @@ + +## [39.0.1](https://github.com/ipfs/js-ipfs-http-client/compare/v39.0.0...v39.0.1) (2019-10-21) + + +### Bug Fixes + +* expose preload argument ([#1129](https://github.com/ipfs/js-ipfs-http-client/issues/1129)) ([c82b031](https://github.com/ipfs/js-ipfs-http-client/commit/c82b031)) +* increase default timeout and respect value passed to `ky.extend` ([#1130](https://github.com/ipfs/js-ipfs-http-client/issues/1130)) ([25b6043](https://github.com/ipfs/js-ipfs-http-client/commit/25b6043)) + + + # [39.0.0](https://github.com/ipfs/js-ipfs-http-client/compare/v38.2.0...v39.0.0) (2019-10-15) From 2d8361a1322d0c5c108a861981e931da13864d05 Mon Sep 17 00:00:00 2001 From: Alex Potsides Date: Tue, 22 Oct 2019 15:20:37 +0100 Subject: [PATCH 163/233] chore: avoid double travis build for PRs (#1133) Disable building branches that aren't master - builds will happen for all PRs anyway, so this change means we don't get a branch build and a PR build on each PR. --- .travis.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.travis.yml b/.travis.yml index a6e41ebdf..802efe943 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,11 @@ language: node_js cache: npm +branches: + only: + - master + - /^release\/.*$/ + stages: - check - test From 432e1e823e076ed926fb51fbe826bc8ec240b945 Mon Sep 17 00:00:00 2001 From: Alex Potsides Date: Wed, 23 Oct 2019 07:02:02 +0100 Subject: [PATCH 164/233] fix: use non-strict equivalence for options.preload (#1134) --- src/add/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/add/index.js b/src/add/index.js index ea85a6a0b..8b8ba7690 100644 --- a/src/add/index.js +++ b/src/add/index.js @@ -28,7 +28,7 @@ module.exports = configure(({ ky }) => { if (options.silent) searchParams.set('silent', options.silent) if (options.trickle != null) searchParams.set('trickle', options.trickle) if (options.wrapWithDirectory != null) searchParams.set('wrap-with-directory', options.wrapWithDirectory) - if (options.preload !== null) searchParams.set('preload', options.preload) + if (options.preload != null) searchParams.set('preload', options.preload) const res = await ky.post('add', { timeout: options.timeout, From eb6cb94fcdf45f630805a65ebcaa887ecf5098d5 Mon Sep 17 00:00:00 2001 From: achingbrain Date: Wed, 23 Oct 2019 07:22:47 +0100 Subject: [PATCH 165/233] chore: update contributors --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 702e159a8..5bd10d59b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ipfs-http-client", - "version": "39.0.1", + "version": "39.0.2", "description": "A client library for the IPFS HTTP API", "keywords": [ "ipfs" From c5edccd83ac8a72737c5b13d5a81ad0c64a6619e Mon Sep 17 00:00:00 2001 From: achingbrain Date: Wed, 23 Oct 2019 07:22:47 +0100 Subject: [PATCH 166/233] chore: release version v39.0.2 --- CHANGELOG.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 73faad621..3634fa56d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,13 @@ + +## [39.0.2](https://github.com/ipfs/js-ipfs-http-client/compare/v39.0.1...v39.0.2) (2019-10-23) + + +### Bug Fixes + +* use non-strict equivalence for options.preload ([#1134](https://github.com/ipfs/js-ipfs-http-client/issues/1134)) ([432e1e8](https://github.com/ipfs/js-ipfs-http-client/commit/432e1e8)) + + + ## [39.0.1](https://github.com/ipfs/js-ipfs-http-client/compare/v39.0.0...v39.0.1) (2019-10-21) From 9c2920d3abe12f319382e56764f8c29f63c820ee Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" <23040076+greenkeeper[bot]@users.noreply.github.com> Date: Thu, 31 Oct 2019 11:59:10 +0000 Subject: [PATCH 167/233] chore: update merge-options to version 2.0.0 (#1131) From 7007e5a3349f5b67398335c64b0c86f4d14733f0 Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" <23040076+greenkeeper[bot]@users.noreply.github.com> Date: Thu, 31 Oct 2019 11:59:45 +0000 Subject: [PATCH 168/233] chore: update ky to version 0.15.0 (#1118) From c9a0e57f983e34f017a21c96b88c2600d2b9cd27 Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Tue, 5 Nov 2019 09:44:16 +0000 Subject: [PATCH 169/233] docs: add kebab case breaking change (#1138) resolves #1137 --- CHANGELOG.md | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3634fa56d..049e2b123 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -51,16 +51,15 @@ ### BREAKING CHANGES -* ```javascript -Promise<{oldCfg, newCfg}> ipfs.config.profile(name, opts) +* Configuration profiles API has changed: + ```javascript + Promise<{oldCfg, newCfg}> ipfs.config.profile(name, opts) -// is now -Promise<{old, new}> ipfs.config.profiles.apply(name, opts) -``` - -Possibly contentious; + // is now + Promise<{old, new}> ipfs.config.profiles.apply(name, opts) + ``` -Adds `callbackify` as a dependency, see https://github.com/ipfs/js-ipfs/issues/2506 +* Possibly contentious; Adds `callbackify` as a dependency, see https://github.com/ipfs/js-ipfs/issues/2506 for discussion. @@ -138,7 +137,9 @@ for discussion. # [35.0.0](https://github.com/ipfs/js-ipfs-http-client/compare/v34.0.0...v35.0.0) (2019-09-04) +### BREAKING CHANGES +Kebab case options (e.g. `wrap-with-directory`) are no longer supported in `ipfs.add`. Use camel case instead (e.g. `wrapWithDirectory`). # [34.0.0](https://github.com/ipfs/js-ipfs-http-client/compare/v33.1.1...v34.0.0) (2019-08-29) From da7dae73e08a7ef929fd9580714b6aeee5c60fc0 Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Tue, 5 Nov 2019 10:10:06 +0000 Subject: [PATCH 170/233] chore(package): update aegir to version 20.4.1 (#1140) --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5bd10d59b..b1d65cf42 100644 --- a/package.json +++ b/package.json @@ -104,7 +104,7 @@ "through2": "^3.0.1" }, "devDependencies": { - "aegir": "^20.3.1", + "aegir": "^20.4.1", "browser-process-platform": "~0.1.1", "cross-env": "^6.0.0", "go-ipfs-dep": "^0.4.22", From 57bdc394c8cb92be675845f50ea593f149d18214 Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Tue, 5 Nov 2019 10:30:09 +0000 Subject: [PATCH 171/233] chore(package): update nock to version 11.4.0 (#1141) --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b1d65cf42..2b7a24ba9 100644 --- a/package.json +++ b/package.json @@ -110,7 +110,7 @@ "go-ipfs-dep": "^0.4.22", "interface-ipfs-core": "^0.117.2", "ipfsd-ctl": "^0.47.1", - "nock": "^11.3.2", + "nock": "^11.4.0", "stream-equal": "^1.1.1" }, "engines": { From 29b3b4d387ea4e56b53bb1bbf984486d1593bcfd Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Tue, 5 Nov 2019 11:26:41 +0000 Subject: [PATCH 172/233] chore(package): update it-glob to version 0.0.6 (#1142) Closes #1108 From 9b1589c23946ace07483e5004d35880114bde729 Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" <23040076+greenkeeper[bot]@users.noreply.github.com> Date: Tue, 5 Nov 2019 12:16:17 +0000 Subject: [PATCH 173/233] chore: update multiaddr to version 7.2.0 (#1136) * fix(package): update multiaddr to version 7.2.0 * fix: tests --- package.json | 2 +- test/constructor.spec.js | 2 +- test/node/swarm.js | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 2b7a24ba9..a45e2e32e 100644 --- a/package.json +++ b/package.json @@ -82,7 +82,7 @@ "ky-universal": "^0.3.0", "lru-cache": "^5.1.1", "merge-options": "^2.0.0", - "multiaddr": "^6.0.6", + "multiaddr": "^7.2.0", "multibase": "~0.6.0", "multicodec": "~0.5.1", "multihashes": "~0.4.14", diff --git a/test/constructor.spec.js b/test/constructor.spec.js index e4a7eb1aa..c728c94c1 100644 --- a/test/constructor.spec.js +++ b/test/constructor.spec.js @@ -134,7 +134,7 @@ async function clientWorks (client) { function expectConfig (ipfs, { host, port, protocol, apiPath }) { const conf = ipfs.getEndpointConfig() expect(conf.host).to.be.oneOf([host, 'localhost', '']) - expect(conf.port).to.be.oneOf([port, '5001', 80]) + expect(conf.port.toString()).to.be.oneOf([port, '5001', '80']) expect(conf.protocol).to.equal(protocol || 'http') expect(conf['api-path']).to.equal(apiPath || '/api/v0/') } diff --git a/test/node/swarm.js b/test/node/swarm.js index 27d377904..b54690dc0 100644 --- a/test/node/swarm.js +++ b/test/node/swarm.js @@ -30,7 +30,7 @@ describe('.swarm.peers', function () { }) it('handles a go-ipfs <= 0.4.4 peer response', async () => { - const response = { Strings: ['/ip4/73.109.217.59/tcp/49311/ipfs/QmWjxEGC7BthJrCf7QTModrcsRweHbupdPTY4oGMVoDZXm'] } + const response = { Strings: ['/ip4/73.109.217.59/tcp/49311/p2p/QmWjxEGC7BthJrCf7QTModrcsRweHbupdPTY4oGMVoDZXm'] } const scope = nock(apiUrl) .post('/api/v0/swarm/peers') @@ -42,7 +42,7 @@ describe('.swarm.peers', function () { expect(res).to.be.a('array') expect(res.length).to.equal(1) expect(res[0].error).to.not.exist() - expect(res[0].addr.toString()).to.equal('/ip4/73.109.217.59/tcp/49311/ipfs/QmWjxEGC7BthJrCf7QTModrcsRweHbupdPTY4oGMVoDZXm') + expect(res[0].addr.toString()).to.equal('/ip4/73.109.217.59/tcp/49311/p2p/QmWjxEGC7BthJrCf7QTModrcsRweHbupdPTY4oGMVoDZXm') expect(res[0].peer.toB58String()).to.equal('QmWjxEGC7BthJrCf7QTModrcsRweHbupdPTY4oGMVoDZXm') expect(scope.isDone()).to.equal(true) }) From 4131d09f9734e7d477aabb8a0873a2d3a40d18b1 Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Wed, 6 Nov 2019 12:36:33 +0000 Subject: [PATCH 174/233] revert: chore: update multiaddr to version 7.2.0 (#1136) (#1143) This reverts commit 9b1589c23946ace07483e5004d35880114bde729. License: MIT Signed-off-by: Alan Shaw --- package.json | 2 +- test/constructor.spec.js | 2 +- test/node/swarm.js | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index a45e2e32e..2b7a24ba9 100644 --- a/package.json +++ b/package.json @@ -82,7 +82,7 @@ "ky-universal": "^0.3.0", "lru-cache": "^5.1.1", "merge-options": "^2.0.0", - "multiaddr": "^7.2.0", + "multiaddr": "^6.0.6", "multibase": "~0.6.0", "multicodec": "~0.5.1", "multihashes": "~0.4.14", diff --git a/test/constructor.spec.js b/test/constructor.spec.js index c728c94c1..e4a7eb1aa 100644 --- a/test/constructor.spec.js +++ b/test/constructor.spec.js @@ -134,7 +134,7 @@ async function clientWorks (client) { function expectConfig (ipfs, { host, port, protocol, apiPath }) { const conf = ipfs.getEndpointConfig() expect(conf.host).to.be.oneOf([host, 'localhost', '']) - expect(conf.port.toString()).to.be.oneOf([port, '5001', '80']) + expect(conf.port).to.be.oneOf([port, '5001', 80]) expect(conf.protocol).to.equal(protocol || 'http') expect(conf['api-path']).to.equal(apiPath || '/api/v0/') } diff --git a/test/node/swarm.js b/test/node/swarm.js index b54690dc0..27d377904 100644 --- a/test/node/swarm.js +++ b/test/node/swarm.js @@ -30,7 +30,7 @@ describe('.swarm.peers', function () { }) it('handles a go-ipfs <= 0.4.4 peer response', async () => { - const response = { Strings: ['/ip4/73.109.217.59/tcp/49311/p2p/QmWjxEGC7BthJrCf7QTModrcsRweHbupdPTY4oGMVoDZXm'] } + const response = { Strings: ['/ip4/73.109.217.59/tcp/49311/ipfs/QmWjxEGC7BthJrCf7QTModrcsRweHbupdPTY4oGMVoDZXm'] } const scope = nock(apiUrl) .post('/api/v0/swarm/peers') @@ -42,7 +42,7 @@ describe('.swarm.peers', function () { expect(res).to.be.a('array') expect(res.length).to.equal(1) expect(res[0].error).to.not.exist() - expect(res[0].addr.toString()).to.equal('/ip4/73.109.217.59/tcp/49311/p2p/QmWjxEGC7BthJrCf7QTModrcsRweHbupdPTY4oGMVoDZXm') + expect(res[0].addr.toString()).to.equal('/ip4/73.109.217.59/tcp/49311/ipfs/QmWjxEGC7BthJrCf7QTModrcsRweHbupdPTY4oGMVoDZXm') expect(res[0].peer.toB58String()).to.equal('QmWjxEGC7BthJrCf7QTModrcsRweHbupdPTY4oGMVoDZXm') expect(scope.isDone()).to.equal(true) }) From 4acd43ecd58964eb505b0043b97f6c66324285ab Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" <23040076+greenkeeper[bot]@users.noreply.github.com> Date: Thu, 7 Nov 2019 15:14:49 +0000 Subject: [PATCH 175/233] chore(package): update form-data to version 3.0.0 (#1146) --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2b7a24ba9..bbcb012b7 100644 --- a/package.json +++ b/package.json @@ -59,7 +59,7 @@ "event-iterator": "^1.2.0", "explain-error": "^1.0.4", "flatmap": "0.0.3", - "form-data": "^2.5.1", + "form-data": "^3.0.0", "fs-extra": "^8.1.0", "glob": "^7.1.3", "ipfs-block": "~0.8.1", From 2d9afc8ce8487b340ece5d5f1091300b1f5278b4 Mon Sep 17 00:00:00 2001 From: Marcin Rataj Date: Thu, 7 Nov 2019 23:53:36 +0100 Subject: [PATCH 176/233] feat: support name.resolve of peerid as cid (#1145) * feat: support name.resolve of peerid as cid This is a hacky way to support CIDs when API is go-ipfs 0.4.22 or older (convert toBase58btc before sending) License: MIT Signed-off-by: Marcin Rataj --- package.json | 2 +- test/interface.spec.js | 10 +++++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index bbcb012b7..70cee49f2 100644 --- a/package.json +++ b/package.json @@ -108,7 +108,7 @@ "browser-process-platform": "~0.1.1", "cross-env": "^6.0.0", "go-ipfs-dep": "^0.4.22", - "interface-ipfs-core": "^0.117.2", + "interface-ipfs-core": "^0.118.0", "ipfsd-ctl": "^0.47.1", "nock": "^11.4.0", "stream-equal": "^1.1.1" diff --git a/test/interface.spec.js b/test/interface.spec.js index 090246822..760962b38 100644 --- a/test/interface.spec.js +++ b/test/interface.spec.js @@ -176,7 +176,15 @@ describe('interface-ipfs-core tests', () => { spawnOptions: { args: ['--offline'] } - })) + }), { + skip: [ + // stop + { + name: 'should resolve a record from peerid as cidv1 in base32', + reason: 'TODO not implemented in go-ipfs yet: https://github.com/ipfs/go-ipfs/issues/5287' + } + ] + }) // TODO: uncomment after https://github.com/ipfs/interface-ipfs-core/pull/361 being merged and a new release tests.namePubsub(CommonFactory.create({ From c05c5ec407a43b4b0594720a16c6148b51cac017 Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Fri, 8 Nov 2019 15:38:19 +0000 Subject: [PATCH 177/233] refactor: convert bitswap to async/await (#1149) --- src/bitswap/index.js | 16 ++++++--------- src/bitswap/stat.js | 31 +++++++++++++++++----------- src/bitswap/unwant.js | 38 ++++++++++++++++++----------------- src/bitswap/wantlist.js | 41 +++++++++++++++++++------------------- src/utils/load-commands.js | 4 ++-- 5 files changed, 67 insertions(+), 63 deletions(-) diff --git a/src/bitswap/index.js b/src/bitswap/index.js index 62f9fb58a..fb47d4da0 100644 --- a/src/bitswap/index.js +++ b/src/bitswap/index.js @@ -1,13 +1,9 @@ 'use strict' -const moduleConfig = require('../utils/module-config') +const callbackify = require('callbackify') -module.exports = (arg) => { - const send = moduleConfig(arg) - - return { - wantlist: require('./wantlist')(send), - stat: require('./stat')(send), - unwant: require('./unwant')(send) - } -} +module.exports = (config) => ({ + wantlist: callbackify.variadic(require('./wantlist')(config)), + stat: callbackify.variadic(require('./stat')(config)), + unwant: callbackify.variadic(require('./unwant')(config)) +}) diff --git a/src/bitswap/stat.js b/src/bitswap/stat.js index f0770d47d..3795327bb 100644 --- a/src/bitswap/stat.js +++ b/src/bitswap/stat.js @@ -1,10 +1,25 @@ 'use strict' -const promisify = require('promisify-es6') +const configure = require('../lib/configure') const Big = require('bignumber.js') -const transform = function (res, callback) { - callback(null, { +module.exports = configure(({ ky }) => { + return async (options) => { + options = options || {} + + const res = await ky.get('bitswap/stat', { + timeout: options.timeout, + signal: options.signal, + headers: options.headers, + searchParams: options.searchParams + }).json() + + return toCoreInterface(res) + } +}) + +function toCoreInterface (res) { + return { provideBufLen: res.ProvideBufLen, wantlist: res.Wantlist || [], peers: res.Peers || [], @@ -14,13 +29,5 @@ const transform = function (res, callback) { dataSent: new Big(res.DataSent), dupBlksReceived: new Big(res.DupBlksReceived), dupDataReceived: new Big(res.DupDataReceived) - }) -} - -module.exports = (send) => { - return promisify((callback) => { - send.andTransform({ - path: 'bitswap/stat' - }, transform, callback) - }) + } } diff --git a/src/bitswap/unwant.js b/src/bitswap/unwant.js index 865fbc27b..9b2044d00 100644 --- a/src/bitswap/unwant.js +++ b/src/bitswap/unwant.js @@ -1,25 +1,27 @@ 'use strict' -const promisify = require('promisify-es6') const CID = require('cids') +const configure = require('../lib/configure') -module.exports = (send) => { - return promisify((cid, opts, callback) => { - if (typeof (opts) === 'function') { - callback = opts - opts = {} - } +module.exports = configure(({ ky }) => { + return async (cid, options) => { + options = options || {} + + const searchParams = new URLSearchParams(options.searchParams) - try { - cid = new CID(cid) - } catch (err) { - return callback(err) + if (typeof cid === 'string') { + searchParams.set('arg', cid) + } else { + searchParams.set('arg', new CID(cid).toString()) } - send({ - path: 'bitswap/unwant', - args: cid.toBaseEncodedString(), - qs: opts - }, callback) - }) -} + const res = await ky.get('bitswap/unwant', { + timeout: options.timeout, + signal: options.signal, + headers: options.headers, + searchParams + }).json() + + return res + } +}) diff --git a/src/bitswap/wantlist.js b/src/bitswap/wantlist.js index 6cd1e3868..3235de8a9 100644 --- a/src/bitswap/wantlist.js +++ b/src/bitswap/wantlist.js @@ -1,30 +1,29 @@ 'use strict' -const promisify = require('promisify-es6') const CID = require('cids') +const configure = require('../lib/configure') -module.exports = (send) => { - return promisify((peerId, opts, callback) => { - if (typeof (peerId) === 'function') { - callback = peerId - opts = {} - peerId = null - } else if (typeof (opts) === 'function') { - callback = opts - opts = {} - } +module.exports = configure(({ ky }) => { + return async (peerId, options) => { + options = options || {} + + const searchParams = new URLSearchParams(options.searchParams) if (peerId) { - try { - opts.peer = new CID(peerId).toBaseEncodedString() - } catch (err) { - return callback(err) + if (typeof peerId === 'string') { + searchParams.set('peer', peerId) + } else { + searchParams.set('peer', new CID(peerId).toString()) } } - send({ - path: 'bitswap/wantlist', - qs: opts - }, callback) - }) -} + const res = await ky.get('bitswap/wantlist', { + timeout: options.timeout, + signal: options.signal, + headers: options.headers, + searchParams + }).json() + + return res + } +}) diff --git a/src/utils/load-commands.js b/src/utils/load-commands.js index 710b8396f..81948a54e 100644 --- a/src/utils/load-commands.js +++ b/src/utils/load-commands.js @@ -3,7 +3,8 @@ function requireCommands (send, config) { const cmds = { ...require('../files-regular')(config), - getEndpointConfig: require('../get-endpoint-config')(config) + getEndpointConfig: require('../get-endpoint-config')(config), + bitswap: require('../bitswap')(config) } const subCmds = { @@ -12,7 +13,6 @@ function requireCommands (send, config) { // Block block: require('../block'), - bitswap: require('../bitswap'), // Graph dag: require('../dag'), From 2275c2a09e6317f366d31a1ef54036d326bb50fb Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" <23040076+greenkeeper[bot]@users.noreply.github.com> Date: Mon, 11 Nov 2019 09:59:57 +0000 Subject: [PATCH 178/233] chore(package): update interface-ipfs-core to version 0.119.0 (#1151) --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 70cee49f2..1908c7de1 100644 --- a/package.json +++ b/package.json @@ -108,7 +108,7 @@ "browser-process-platform": "~0.1.1", "cross-env": "^6.0.0", "go-ipfs-dep": "^0.4.22", - "interface-ipfs-core": "^0.118.0", + "interface-ipfs-core": "^0.119.0", "ipfsd-ctl": "^0.47.1", "nock": "^11.4.0", "stream-equal": "^1.1.1" From 559a97d89b84e6bbb7d1c5cf41a7b8bf853a68da Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Tue, 12 Nov 2019 11:15:10 +0000 Subject: [PATCH 179/233] refactor: move files to root level (#1150) Moves remaining files that contain root level commands to the root of the src directory. This makes it easier for new contributors to find things. It also renames the `files-mfs` dir to `files` to reflect the fact that it lives in the "files" namespace currently. BREAKING CHANGE: files in `src/files-regular` have moved to `src`. The `src/files-mfs` directory has been renamed to `src/files`. If you were previously requiring files from these directories e.g. `require('ipfs-http-client/src/files-regular/add')` then please be aware that they have moved. License: MIT Signed-off-by: Alan Shaw --- src/files-regular/index.js | 100 ------------------ src/files-regular/refs.js | 63 ----------- src/{files-mfs => files}/cp.js | 0 src/{files-mfs => files}/flush.js | 0 src/{files-mfs => files}/index.js | 0 src/{files-mfs => files}/ls-pull-stream.js | 0 .../ls-readable-stream.js | 0 src/{files-mfs => files}/ls.js | 0 src/{files-mfs => files}/mkdir.js | 0 src/{files-mfs => files}/mv.js | 0 src/{files-mfs => files}/read-pull-stream.js | 0 .../read-readable-stream.js | 0 src/{files-mfs => files}/read.js | 0 src/{files-mfs => files}/rm.js | 0 src/{files-mfs => files}/stat.js | 0 src/{files-mfs => files}/write.js | 0 src/{files-regular => }/get.js | 6 +- src/{files-regular => }/ls.js | 4 +- src/refs/index.js | 69 ++++++++++++ .../refs-local.js => refs/local.js} | 0 src/utils/load-commands.js | 96 ++++++++++++++++- test/sub-modules.spec.js | 22 ++-- 22 files changed, 179 insertions(+), 181 deletions(-) delete mode 100644 src/files-regular/index.js delete mode 100644 src/files-regular/refs.js rename src/{files-mfs => files}/cp.js (100%) rename src/{files-mfs => files}/flush.js (100%) rename src/{files-mfs => files}/index.js (100%) rename src/{files-mfs => files}/ls-pull-stream.js (100%) rename src/{files-mfs => files}/ls-readable-stream.js (100%) rename src/{files-mfs => files}/ls.js (100%) rename src/{files-mfs => files}/mkdir.js (100%) rename src/{files-mfs => files}/mv.js (100%) rename src/{files-mfs => files}/read-pull-stream.js (100%) rename src/{files-mfs => files}/read-readable-stream.js (100%) rename src/{files-mfs => files}/read.js (100%) rename src/{files-mfs => files}/rm.js (100%) rename src/{files-mfs => files}/stat.js (100%) rename src/{files-mfs => files}/write.js (100%) rename src/{files-regular => }/get.js (85%) rename src/{files-regular => }/ls.js (94%) create mode 100644 src/refs/index.js rename src/{files-regular/refs-local.js => refs/local.js} (100%) diff --git a/src/files-regular/index.js b/src/files-regular/index.js deleted file mode 100644 index 3381102d5..000000000 --- a/src/files-regular/index.js +++ /dev/null @@ -1,100 +0,0 @@ -'use strict' - -const nodeify = require('promise-nodeify') -const callbackify = require('callbackify') -const all = require('async-iterator-all') -const { concatify, collectify, pullify, streamify } = require('../lib/converters') -const toPullStream = require('async-iterator-to-pull-stream') -const pull = require('pull-stream/pull') -const map = require('pull-stream/throughs/map') - -module.exports = (config) => { - const add = require('../add')(config) - const addFromFs = require('../add-from-fs')(config) - const addFromURL = require('../add-from-url')(config) - const cat = require('../cat')(config) - const get = require('./get')(config) - const ls = require('./ls')(config) - const refs = require('./refs')(config) - const refsLocal = require('./refs-local')(config) - - const api = { - add: (input, options, callback) => { - if (typeof options === 'function') { - callback = options - options = {} - } - return nodeify(collectify(add)(input, options), callback) - }, - addReadableStream: streamify.transform(add), - addPullStream: pullify.transform(add), - addFromFs: (path, options, callback) => { - if (typeof options === 'function') { - callback = options - options = {} - } - return nodeify(collectify(addFromFs)(path, options), callback) - }, - addFromURL: (url, options, callback) => { - if (typeof options === 'function') { - callback = options - options = {} - } - return nodeify(collectify(addFromURL)(url, options), callback) - }, - addFromStream: (input, options, callback) => { - if (typeof options === 'function') { - callback = options - options = {} - } - return nodeify(collectify(add)(input, options), callback) - }, - _addAsyncIterator: add, - cat: callbackify.variadic((path, options) => concatify(cat)(path, options)), - catReadableStream: streamify.readable(cat), - catPullStream: pullify.source(cat), - _catAsyncIterator: cat, - get: callbackify.variadic(async (path, options) => { - const output = [] - - for await (const entry of get(path, options)) { - if (entry.content) { - entry.content = Buffer.concat(await all(entry.content)) - } - - output.push(entry) - } - - return output - }), - getReadableStream: streamify.readable(get), - getPullStream: (path, options) => { - return pull( - toPullStream(get(path, options)), - map(file => { - if (file.content) { - file.content = toPullStream(file.content) - } - - return file - }) - ) - }, - _getAsyncIterator: get, - ls: callbackify.variadic((path, options) => collectify(ls)(path, options)), - lsReadableStream: streamify.readable(ls), - lsPullStream: pullify.source(ls), - _lsAsyncIterator: ls, - refs: callbackify.variadic((path, options) => collectify(refs)(path, options)), - refsReadableStream: streamify.readable(refs), - refsPullStream: pullify.source(refs), - _refsAsyncIterator: refs - } - - api.refs.local = callbackify.variadic((options) => collectify(refsLocal)(options)) - api.refs.localReadableStream = streamify.readable(refsLocal) - api.refs.localPullStream = pullify.source(refsLocal) - api.refs._localAsyncIterator = refsLocal - - return api -} diff --git a/src/files-regular/refs.js b/src/files-regular/refs.js deleted file mode 100644 index c6136ede5..000000000 --- a/src/files-regular/refs.js +++ /dev/null @@ -1,63 +0,0 @@ -'use strict' - -const configure = require('../lib/configure') -const cleanCID = require('../utils/clean-cid') -const IsIpfs = require('is-ipfs') -const ndjson = require('iterable-ndjson') -const toIterable = require('../lib/stream-to-iterable') -const toCamel = require('../lib/object-to-camel') - -module.exports = configure(({ ky }) => { - return async function * refs (args, options) { - options = options || {} - - const searchParams = new URLSearchParams() - - if (options.format !== undefined) { - searchParams.set('format', options.format) - } - - if (options.edges !== undefined) { - searchParams.set('edges', options.edges) - } - - if (options.unique !== undefined) { - searchParams.set('unique', options.unique) - } - - if (options.recursive !== undefined) { - searchParams.set('recursive', options.recursive) - } - - if (options.maxDepth !== undefined) { - searchParams.set('max-depth', options.maxDepth) - } - - if (!Array.isArray(args)) { - args = [args] - } - - for (let arg of args) { - try { - arg = cleanCID(arg) - } catch (err) { - if (!IsIpfs.ipfsPath(arg)) { - throw err - } - } - - searchParams.append('arg', arg.toString()) - } - - const res = await ky.get('refs', { - timeout: options.timeout, - signal: options.signal, - headers: options.headers, - searchParams - }) - - for await (const file of ndjson(toIterable(res.body))) { - yield toCamel(file) - } - } -}) diff --git a/src/files-mfs/cp.js b/src/files/cp.js similarity index 100% rename from src/files-mfs/cp.js rename to src/files/cp.js diff --git a/src/files-mfs/flush.js b/src/files/flush.js similarity index 100% rename from src/files-mfs/flush.js rename to src/files/flush.js diff --git a/src/files-mfs/index.js b/src/files/index.js similarity index 100% rename from src/files-mfs/index.js rename to src/files/index.js diff --git a/src/files-mfs/ls-pull-stream.js b/src/files/ls-pull-stream.js similarity index 100% rename from src/files-mfs/ls-pull-stream.js rename to src/files/ls-pull-stream.js diff --git a/src/files-mfs/ls-readable-stream.js b/src/files/ls-readable-stream.js similarity index 100% rename from src/files-mfs/ls-readable-stream.js rename to src/files/ls-readable-stream.js diff --git a/src/files-mfs/ls.js b/src/files/ls.js similarity index 100% rename from src/files-mfs/ls.js rename to src/files/ls.js diff --git a/src/files-mfs/mkdir.js b/src/files/mkdir.js similarity index 100% rename from src/files-mfs/mkdir.js rename to src/files/mkdir.js diff --git a/src/files-mfs/mv.js b/src/files/mv.js similarity index 100% rename from src/files-mfs/mv.js rename to src/files/mv.js diff --git a/src/files-mfs/read-pull-stream.js b/src/files/read-pull-stream.js similarity index 100% rename from src/files-mfs/read-pull-stream.js rename to src/files/read-pull-stream.js diff --git a/src/files-mfs/read-readable-stream.js b/src/files/read-readable-stream.js similarity index 100% rename from src/files-mfs/read-readable-stream.js rename to src/files/read-readable-stream.js diff --git a/src/files-mfs/read.js b/src/files/read.js similarity index 100% rename from src/files-mfs/read.js rename to src/files/read.js diff --git a/src/files-mfs/rm.js b/src/files/rm.js similarity index 100% rename from src/files-mfs/rm.js rename to src/files/rm.js diff --git a/src/files-mfs/stat.js b/src/files/stat.js similarity index 100% rename from src/files-mfs/stat.js rename to src/files/stat.js diff --git a/src/files-mfs/write.js b/src/files/write.js similarity index 100% rename from src/files-mfs/write.js rename to src/files/write.js diff --git a/src/files-regular/get.js b/src/get.js similarity index 85% rename from src/files-regular/get.js rename to src/get.js index 6c942648b..62adfd1e9 100644 --- a/src/files-regular/get.js +++ b/src/get.js @@ -1,9 +1,9 @@ 'use strict' -const configure = require('../lib/configure') -const tarStreamToObjects = require('../utils/tar-stream-to-objects') +const configure = require('./lib/configure') +const tarStreamToObjects = require('./utils/tar-stream-to-objects') const IsIpfs = require('is-ipfs') -const cleanCID = require('../utils/clean-cid') +const cleanCID = require('./utils/clean-cid') module.exports = configure(({ ky }) => { return async function * get (path, options) { diff --git a/src/files-regular/ls.js b/src/ls.js similarity index 94% rename from src/files-regular/ls.js rename to src/ls.js index 0f13f556d..fc9921963 100644 --- a/src/files-regular/ls.js +++ b/src/ls.js @@ -1,8 +1,8 @@ 'use strict' const IsIpfs = require('is-ipfs') -const cleanCID = require('../utils/clean-cid') -const configure = require('../lib/configure') +const cleanCID = require('./utils/clean-cid') +const configure = require('./lib/configure') module.exports = configure(({ ky }) => { return async function * ls (path, options) { diff --git a/src/refs/index.js b/src/refs/index.js new file mode 100644 index 000000000..d86944eb2 --- /dev/null +++ b/src/refs/index.js @@ -0,0 +1,69 @@ +'use strict' + +const configure = require('../lib/configure') +const cleanCID = require('../utils/clean-cid') +const IsIpfs = require('is-ipfs') +const ndjson = require('iterable-ndjson') +const toIterable = require('../lib/stream-to-iterable') +const toCamel = require('../lib/object-to-camel') + +module.exports = config => { + const refs = (configure(({ ky }) => { + return async function * refs (args, options) { + options = options || {} + + const searchParams = new URLSearchParams() + + if (options.format !== undefined) { + searchParams.set('format', options.format) + } + + if (options.edges !== undefined) { + searchParams.set('edges', options.edges) + } + + if (options.unique !== undefined) { + searchParams.set('unique', options.unique) + } + + if (options.recursive !== undefined) { + searchParams.set('recursive', options.recursive) + } + + if (options.maxDepth !== undefined) { + searchParams.set('max-depth', options.maxDepth) + } + + if (!Array.isArray(args)) { + args = [args] + } + + for (let arg of args) { + try { + arg = cleanCID(arg) + } catch (err) { + if (!IsIpfs.ipfsPath(arg)) { + throw err + } + } + + searchParams.append('arg', arg.toString()) + } + + const res = await ky.get('refs', { + timeout: options.timeout, + signal: options.signal, + headers: options.headers, + searchParams + }) + + for await (const file of ndjson(toIterable(res.body))) { + yield toCamel(file) + } + } + }))(config) + + refs.local = require('./local')(config) + + return refs +} diff --git a/src/files-regular/refs-local.js b/src/refs/local.js similarity index 100% rename from src/files-regular/refs-local.js rename to src/refs/local.js diff --git a/src/utils/load-commands.js b/src/utils/load-commands.js index 81948a54e..d4295205c 100644 --- a/src/utils/load-commands.js +++ b/src/utils/load-commands.js @@ -1,15 +1,107 @@ 'use strict' +const nodeify = require('promise-nodeify') +const callbackify = require('callbackify') +const all = require('async-iterator-all') +const { concatify, collectify, pullify, streamify } = require('../lib/converters') +const toPullStream = require('async-iterator-to-pull-stream') +const pull = require('pull-stream/pull') +const map = require('pull-stream/throughs/map') + function requireCommands (send, config) { + const add = require('../add')(config) + const addFromFs = require('../add-from-fs')(config) + const addFromURL = require('../add-from-url')(config) + const cat = require('../cat')(config) + const get = require('../get')(config) + const ls = require('../ls')(config) + const refs = require('../refs')(config) + const cmds = { - ...require('../files-regular')(config), + add: (input, options, callback) => { + if (typeof options === 'function') { + callback = options + options = {} + } + return nodeify(collectify(add)(input, options), callback) + }, + addReadableStream: streamify.transform(add), + addPullStream: pullify.transform(add), + addFromFs: (path, options, callback) => { + if (typeof options === 'function') { + callback = options + options = {} + } + return nodeify(collectify(addFromFs)(path, options), callback) + }, + addFromURL: (url, options, callback) => { + if (typeof options === 'function') { + callback = options + options = {} + } + return nodeify(collectify(addFromURL)(url, options), callback) + }, + addFromStream: (input, options, callback) => { + if (typeof options === 'function') { + callback = options + options = {} + } + return nodeify(collectify(add)(input, options), callback) + }, + _addAsyncIterator: add, + cat: callbackify.variadic((path, options) => concatify(cat)(path, options)), + catReadableStream: streamify.readable(cat), + catPullStream: pullify.source(cat), + _catAsyncIterator: cat, + get: callbackify.variadic(async (path, options) => { + const output = [] + + for await (const entry of get(path, options)) { + if (entry.content) { + entry.content = Buffer.concat(await all(entry.content)) + } + + output.push(entry) + } + + return output + }), + getReadableStream: streamify.readable(get), + getPullStream: (path, options) => { + return pull( + toPullStream(get(path, options)), + map(file => { + if (file.content) { + file.content = toPullStream(file.content) + } + + return file + }) + ) + }, + _getAsyncIterator: get, + ls: callbackify.variadic((path, options) => collectify(ls)(path, options)), + lsReadableStream: streamify.readable(ls), + lsPullStream: pullify.source(ls), + _lsAsyncIterator: ls, + refs: callbackify.variadic((path, options) => collectify(refs)(path, options)), + refsReadableStream: streamify.readable(refs), + refsPullStream: pullify.source(refs), + _refsAsyncIterator: refs, getEndpointConfig: require('../get-endpoint-config')(config), bitswap: require('../bitswap')(config) } + Object.assign(cmds.refs, { + local: callbackify.variadic(options => collectify(refs.local)(options)), + localReadableStream: streamify.readable(refs.local), + localPullStream: pullify.source(refs.local), + _localAsyncIterator: refs.local + }) + const subCmds = { // Files MFS (Mutable Filesystem) - files: require('../files-mfs'), + files: require('../files'), // Block block: require('../block'), diff --git a/test/sub-modules.spec.js b/test/sub-modules.spec.js index fbecfe637..62d05ce8e 100644 --- a/test/sub-modules.spec.js +++ b/test/sub-modules.spec.js @@ -165,7 +165,7 @@ describe('submodules', () => { }) it('files regular API', () => { - const filesRegular = require('../src/files-regular')(config) + const filesRegular = require('../src')(config) expect(filesRegular.add).to.be.a('function') expect(filesRegular.addReadableStream).to.be.a('function') @@ -191,16 +191,16 @@ describe('submodules', () => { }) it('files MFS API', () => { - const filesMFS = require('../src/files-mfs')(config) - - expect(filesMFS.cp).to.be.a('function') - expect(filesMFS.ls).to.be.a('function') - expect(filesMFS.mkdir).to.be.a('function') - expect(filesMFS.stat).to.be.a('function') - expect(filesMFS.rm).to.be.a('function') - expect(filesMFS.read).to.be.a('function') - expect(filesMFS.write).to.be.a('function') - expect(filesMFS.mv).to.be.a('function') + const files = require('../src/files')(config) + + expect(files.cp).to.be.a('function') + expect(files.ls).to.be.a('function') + expect(files.mkdir).to.be.a('function') + expect(files.stat).to.be.a('function') + expect(files.rm).to.be.a('function') + expect(files.read).to.be.a('function') + expect(files.write).to.be.a('function') + expect(files.mv).to.be.a('function') }) it('commands', () => { From 72fdc8c6b6130ef40acdaacf64f784bd038b4e90 Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Tue, 12 Nov 2019 19:57:26 +0000 Subject: [PATCH 180/233] refactor: convert block API to async await (#1153) * refactor: convert block API to async/await depends on: * [ ] https://github.com/ipfs/js-ipfs-http-client/pull/1150 License: MIT Signed-off-by: Alan Shaw * feat: support the version param License: MIT Signed-off-by: Alan Shaw * refactor: convert DAG API to async/await License: MIT Signed-off-by: Alan Shaw * fix: add util to convert a single buffer to a form data object License: MIT Signed-off-by: Alan Shaw * fix: exported function --- package.json | 3 +- src/block/get.js | 71 ++++------------ src/block/index.js | 11 ++- src/block/put.js | 110 ++++++++++++------------- src/block/stat.js | 45 +++++----- src/dag/get.js | 74 ++++++----------- src/dag/index.js | 15 ++-- src/dag/put.js | 92 +++++++++------------ src/dag/resolve.js | 31 +++++++ src/lib/buffer-to-form-data.browser.js | 8 ++ src/lib/buffer-to-form-data.js | 17 ++++ src/utils/load-commands.js | 8 +- 12 files changed, 220 insertions(+), 265 deletions(-) create mode 100644 src/dag/resolve.js create mode 100644 src/lib/buffer-to-form-data.browser.js create mode 100644 src/lib/buffer-to-form-data.js diff --git a/package.json b/package.json index 1908c7de1..acd90bb63 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,8 @@ "stream": "readable-stream", "ky-universal": "ky/umd", "./src/add/form-data.js": "./src/add/form-data.browser.js", - "./src/add-from-fs/index.js": "./src/add-from-fs/index.browser.js" + "./src/add-from-fs/index.js": "./src/add-from-fs/index.browser.js", + "./src/lib/buffer-to-form-data.js": "./src/lib/buffer-to-form-data.browser.js" }, "repository": "github:ipfs/js-ipfs-http-client", "scripts": { diff --git a/src/block/get.js b/src/block/get.js index 327b9e7ff..6e28643f3 100644 --- a/src/block/get.js +++ b/src/block/get.js @@ -1,62 +1,25 @@ 'use strict' -const promisify = require('promisify-es6') const Block = require('ipfs-block') const CID = require('cids') -const streamToValue = require('../utils/stream-to-value') +const { Buffer } = require('buffer') +const configure = require('../lib/configure') -module.exports = (send) => { - return promisify((args, opts, callback) => { - if (typeof opts === 'function') { - callback = opts - opts = {} - } +module.exports = configure(({ ky }) => { + return async (cid, options) => { + cid = new CID(cid) + options = options || {} - // TODO this needs to be adjusted with the new go-ipfs http-api - let cid - try { - if (CID.isCID(args)) { - cid = args - args = cid.toBaseEncodedString() - } else if (Buffer.isBuffer(args)) { - cid = new CID(args) - args = cid.toBaseEncodedString() - } else if (typeof args === 'string') { - cid = new CID(args) - } else { - return callback(new Error('invalid argument')) - } - } catch (err) { - return callback(err) - } + const searchParams = new URLSearchParams(options.searchParams) + searchParams.set('arg', `${cid}`) - // Transform the response from Buffer or a Stream to a Block - const transform = (res, callback) => { - if (Buffer.isBuffer(res)) { - callback(null, new Block(res, cid)) - // For empty blocks, concat-stream can't infer the encoding so we are - // passed back an empty array - } else if (Array.isArray(res) && res.length === 0) { - callback(null, new Block(Buffer.alloc(0), cid)) - } else { - streamToValue(res, (err, data) => { - if (err) { - return callback(err) - } - // For empty blocks, concat-stream can't infer the encoding so we are - // passed back an empty array - if (!data.length) data = Buffer.alloc(0) - callback(null, new Block(data, cid)) - }) - } - } + const data = await ky.get('block/get', { + timeout: options.timeout, + signal: options.signal, + headers: options.headers, + searchParams + }).arrayBuffer() - const request = { - path: 'block/get', - args: args, - qs: opts - } - - send.andTransform(request, transform, callback) - }) -} + return new Block(Buffer.from(data), cid) + } +}) diff --git a/src/block/index.js b/src/block/index.js index 645f47df6..8c683dd83 100644 --- a/src/block/index.js +++ b/src/block/index.js @@ -1,17 +1,16 @@ 'use strict' const nodeify = require('promise-nodeify') -const moduleConfig = require('../utils/module-config') +const callbackify = require('callbackify') const { collectify } = require('../lib/converters') -module.exports = (arg, config) => { - const send = moduleConfig(arg) +module.exports = config => { const rm = require('./rm-async-iterator')(config) return { - get: require('./get')(send), - stat: require('./stat')(send), - put: require('./put')(send), + get: callbackify.variadic(require('./get')(config)), + stat: callbackify.variadic(require('./stat')(config)), + put: callbackify.variadic(require('./put')(config)), rm: (input, options, callback) => { if (typeof options === 'function') { callback = options diff --git a/src/block/put.js b/src/block/put.js index 03f6824db..39e3b6f1a 100644 --- a/src/block/put.js +++ b/src/block/put.js @@ -1,74 +1,68 @@ 'use strict' -const promisify = require('promisify-es6') const Block = require('ipfs-block') const CID = require('cids') const multihash = require('multihashes') -const SendOneFile = require('../utils/send-one-file') - -module.exports = (send) => { - const sendOneFile = SendOneFile(send, 'block/put') - - return promisify((block, options, callback) => { - if (typeof options === 'function') { - callback = options - options = {} - } +const configure = require('../lib/configure') +const toFormData = require('../lib/buffer-to-form-data') +module.exports = configure(({ ky }) => { + async function put (data, options) { options = options || {} - if (Array.isArray(block)) { - return callback(new Error('block.put accepts only one block')) - } - - if (Buffer.isBuffer(block)) { - block = { data: block } - } - - if (!block || !block.data) { - return callback(new Error('invalid block arg')) + if (Block.isBlock(data)) { + const { name, length } = multihash.decode(data.cid.multihash) + options = { + ...options, + format: data.cid.codec, + mhtype: name, + mhlen: length, + version: data.cid.version + } + data = data.data + } else if (options.cid) { + const cid = new CID(options.cid) + const { name, length } = multihash.decode(cid.multihash) + options = { + ...options, + format: cid.codec, + mhtype: name, + mhlen: length, + version: cid.version + } + delete options.cid } - const qs = {} + const searchParams = new URLSearchParams(options.searchParams) + if (options.format) searchParams.set('format', options.format) + if (options.mhtype) searchParams.set('mhtype', options.mhtype) + if (options.mhlen) searchParams.set('mhlen', options.mhlen) + if (options.pin != null) searchParams.set('pin', options.pin) + if (options.version != null) searchParams.set('version', options.version) - if (block.cid || options.cid) { - let cid - - try { - cid = new CID(block.cid || options.cid) - } catch (err) { - return callback(err) + let res + try { + res = await ky.post('block/put', { + timeout: options.timeout, + signal: options.signal, + headers: options.headers, + searchParams, + body: toFormData(data) + }).json() + } catch (err) { + // Retry with "protobuf"/"cbor" format for go-ipfs + // TODO: remove when https://github.com/ipfs/go-cid/issues/75 resolved + if (options.format === 'dag-pb') { + return put(data, { ...options, format: 'protobuf' }) + } else if (options.format === 'dag-cbor') { + return put(data, { ...options, format: 'cbor' }) } - const { name, length } = multihash.decode(cid.multihash) - - qs.format = cid.codec - qs.mhtype = name - qs.mhlen = length - qs.version = cid.version - } else { - if (options.format) qs.format = options.format - if (options.mhtype) qs.mhtype = options.mhtype - if (options.mhlen) qs.mhlen = options.mhlen - if (options.version != null) qs.version = options.version + throw err } - sendOneFile(block.data, { qs }, (err, result) => { - if (err) { - // Retry with "protobuf"/"cbor" format for go-ipfs - // TODO: remove when https://github.com/ipfs/go-cid/issues/75 resolved - if (qs.format === 'dag-pb' || qs.format === 'dag-cbor') { - qs.format = qs.format === 'dag-pb' ? 'protobuf' : 'cbor' - return sendOneFile(block.data, { qs }, (err, result) => { - if (err) return callback(err) - callback(null, new Block(block.data, new CID(result.Key))) - }) - } - - return callback(err) - } + return new Block(data, new CID(res.Key)) + } - callback(null, new Block(block.data, new CID(result.Key))) - }) - }) -} + return put +}) diff --git a/src/block/stat.js b/src/block/stat.js index 9d44ac9f8..4d0b82787 100644 --- a/src/block/stat.js +++ b/src/block/stat.js @@ -1,35 +1,28 @@ 'use strict' -const promisify = require('promisify-es6') const CID = require('cids') -const multihash = require('multihashes') +const { Buffer } = require('buffer') +const configure = require('../lib/configure') +const toCamel = require('../lib/object-to-camel') -module.exports = (send) => { - return promisify((args, opts, callback) => { - // TODO this needs to be adjusted with the new go-ipfs http-api - if (args && CID.isCID(args)) { - args = multihash.toB58String(args.multihash) - } +module.exports = configure(({ ky }) => { + return async (cid, options) => { + options = options || {} - if (typeof (opts) === 'function') { - callback = opts - opts = {} + if (Buffer.isBuffer(cid)) { + cid = new CID(cid) } - const request = { - path: 'block/stat', - args: args, - qs: opts - } + const searchParams = new URLSearchParams(options.searchParams) + searchParams.set('arg', `${cid}`) - // Transform the response from { Key, Size } objects to { key, size } objects - const transform = (stats, callback) => { - callback(null, { - key: stats.Key, - size: stats.Size - }) - } + const res = await ky.get('block/stat', { + timeout: options.timeout, + signal: options.signal, + headers: options.headers, + searchParams + }).json() - send.andTransform(request, transform, callback) - }) -} + return toCamel(res) + } +}) diff --git a/src/dag/get.js b/src/dag/get.js index 771c38bf4..93847b2e6 100644 --- a/src/dag/get.js +++ b/src/dag/get.js @@ -3,10 +3,7 @@ const dagPB = require('ipld-dag-pb') const dagCBOR = require('ipld-dag-cbor') const raw = require('ipld-raw') -const promisify = require('promisify-es6') -const CID = require('cids') -const waterfall = require('async/waterfall') -const block = require('../block') +const configure = require('../lib/configure') const resolvers = { 'dag-cbor': dagCBOR.resolver, @@ -14,56 +11,31 @@ const resolvers = { raw: raw.resolver } -module.exports = (send) => { - return promisify((cid, path, options, callback) => { - if (typeof path === 'function') { - callback = path - path = undefined - } - - if (typeof options === 'function') { - callback = options - options = {} - } +module.exports = config => { + const getBlock = require('../block/get')(config) + const dagResolve = require('./resolve')(config) - options = options || {} - path = path || '' - - if (CID.isCID(cid)) { - cid = cid.toBaseEncodedString() - } - - waterfall([ - cb => { - send({ - path: 'dag/resolve', - args: cid + '/' + path, - qs: options - }, cb) - }, - (resolved, cb) => { - block(send).get(new CID(resolved.Cid['/']), (err, ipfsBlock) => { - cb(err, ipfsBlock, resolved.RemPath) - }) - }, - (ipfsBlock, path, cb) => { - const dagResolver = resolvers[ipfsBlock.cid.codec] + return configure(({ ky }) => { + return async (cid, path, options) => { + if (typeof path === 'object') { + options = path + path = null + } - if (!dagResolver) { - const error = new Error(`Missing IPLD format "${ipfsBlock.cid.codec}"`) - error.missingMulticodec = ipfsBlock.cid.codec - return cb(error) - } + options = options || {} - let res - try { - res = dagResolver.resolve(ipfsBlock.data, path) - } catch (err) { - return cb(err) - } + const resolved = await dagResolve(cid, path, options) + const block = await getBlock(resolved.cid, options) + const dagResolver = resolvers[block.cid.codec] - cb(null, res) + if (!dagResolver) { + throw Object.assign( + new Error(`Missing IPLD format "${block.cid.codec}"`), + { missingMulticodec: cid.codec } + ) } - ], callback) - }) + + return dagResolver.resolve(block.data, resolved.remPath) + } + })(config) } diff --git a/src/dag/index.js b/src/dag/index.js index bb6b1333c..06194e4a8 100644 --- a/src/dag/index.js +++ b/src/dag/index.js @@ -1,12 +1,9 @@ 'use strict' -const moduleConfig = require('../utils/module-config') +const callbackify = require('callbackify') -module.exports = (arg) => { - const send = moduleConfig(arg) - - return { - get: require('./get')(send), - put: require('./put')(send) - } -} +module.exports = config => ({ + get: callbackify.variadic(require('./get')(config)), + put: callbackify.variadic(require('./put')(config)), + resolve: callbackify.variadic(require('./resolve')(config)) +}) diff --git a/src/dag/put.js b/src/dag/put.js index 36da9376a..d26f8ba9e 100644 --- a/src/dag/put.js +++ b/src/dag/put.js @@ -1,19 +1,13 @@ 'use strict' const dagCBOR = require('ipld-dag-cbor') -const promisify = require('promisify-es6') const CID = require('cids') const multihash = require('multihashes') -const SendOneFile = require('../utils/send-one-file') - -module.exports = (send) => { - const sendOneFile = SendOneFile(send, 'dag/put') - - return promisify((dagNode, options, callback) => { - if (typeof options === 'function') { - callback = options - } +const configure = require('../lib/configure') +const toFormData = require('../lib/buffer-to-form-data') +module.exports = configure(({ ky }) => { + return async (dagNode, options) => { options = options || {} if (options.hash) { @@ -22,65 +16,53 @@ module.exports = (send) => { } if (options.cid && (options.format || options.hashAlg)) { - return callback(new Error('Can\'t put dag node. Please provide either `cid` OR `format` and `hash` options.')) + throw new Error('Failed to put DAG node. Provide either `cid` OR `format` and `hashAlg` options') } else if ((options.format && !options.hashAlg) || (!options.format && options.hashAlg)) { - return callback(new Error('Can\'t put dag node. Please provide `format` AND `hash` options.')) + throw new Error('Failed to put DAG node. Provide `format` AND `hashAlg` options') } if (options.cid) { - let cid - - try { - cid = new CID(options.cid) - } catch (err) { - return callback(err) + const cid = new CID(options.cid) + options = { + ...options, + format: cid.codec, + hashAlg: multihash.decode(cid.multihash).name } - - options.format = cid.codec - options.hashAlg = multihash.decode(cid.multihash).name delete options.cid } - const optionDefaults = { + options = { format: 'dag-cbor', hashAlg: 'sha2-256', - inputEnc: 'raw' + inputEnc: 'raw', + ...options } - options = Object.assign(optionDefaults, options) - let serialized - try { - if (options.format === 'dag-cbor') { - serialized = dagCBOR.util.serialize(dagNode) - } else if (options.format === 'dag-pb') { - serialized = dagNode.serialize() - } else { - // FIXME Hopefully already serialized...can we use IPLD to serialise instead? - serialized = dagNode - } - } catch (err) { - return callback(err) + if (options.format === 'dag-cbor') { + serialized = dagCBOR.util.serialize(dagNode) + } else if (options.format === 'dag-pb') { + serialized = dagNode.serialize() + } else { + // FIXME Hopefully already serialized...can we use IPLD to serialise instead? + serialized = dagNode } - const sendOptions = { - qs: { - hash: options.hashAlg, - format: options.format, - 'input-enc': options.inputEnc - } - } + const searchParams = new URLSearchParams(options.searchParams) + searchParams.set('format', options.format) + searchParams.set('hash', options.hashAlg) + searchParams.set('input-enc', options.inputEnc) + if (options.pin != null) searchParams.set('pin', options.pin) - sendOneFile(serialized, sendOptions, (err, result) => { - if (err) { - return callback(err) - } - if (result.Cid) { - return callback(null, new CID(result.Cid['/'])) - } else { - return callback(result) - } - }) - }) -} + const res = await ky.post('dag/put', { + timeout: options.timeout, + signal: options.signal, + headers: options.headers, + searchParams, + body: toFormData(serialized) + }).json() + + return new CID(res.Cid['/']) + } +}) diff --git a/src/dag/resolve.js b/src/dag/resolve.js new file mode 100644 index 000000000..f0a83d69d --- /dev/null +++ b/src/dag/resolve.js @@ -0,0 +1,31 @@ +'use strict' + +const CID = require('cids') +const configure = require('../lib/configure') + +module.exports = configure(({ ky }) => { + return async (cid, path, options) => { + if (typeof path === 'object') { + options = path + path = null + } + + options = options || {} + + const cidPath = path + ? [cid, path].join(path.startsWith('/') ? '' : '/') + : `${cid}` + + const searchParams = new URLSearchParams(options.searchParams) + searchParams.set('arg', cidPath) + + const res = await ky.get('dag/resolve', { + timeout: options.timeout, + signal: options.signal, + headers: options.headers, + searchParams + }).json() + + return { cid: new CID(res.Cid['/']), remPath: res.RemPath } + } +}) diff --git a/src/lib/buffer-to-form-data.browser.js b/src/lib/buffer-to-form-data.browser.js new file mode 100644 index 000000000..dab8da9ce --- /dev/null +++ b/src/lib/buffer-to-form-data.browser.js @@ -0,0 +1,8 @@ +'use strict' +/* eslint-env browser */ + +module.exports = buf => { + const formData = new FormData() + formData.append('file', new Blob([buf], { type: 'application/octet-stream' })) + return formData +} diff --git a/src/lib/buffer-to-form-data.js b/src/lib/buffer-to-form-data.js new file mode 100644 index 000000000..41f03383e --- /dev/null +++ b/src/lib/buffer-to-form-data.js @@ -0,0 +1,17 @@ +'use strict' + +const FormData = require('form-data') +const { isElectronRenderer } = require('ipfs-utils/src/env') + +module.exports = buf => { + const formData = new FormData() + formData.append('file', buf) + return formData +} + +// TODO remove this when upstream fix for ky-universal is merged +// https://github.com/sindresorhus/ky-universal/issues/9 +// also this should only be necessary when nodeIntegration is false in electron renderer +if (isElectronRenderer) { + module.exports = require('./buffer-to-form-data.browser') +} diff --git a/src/utils/load-commands.js b/src/utils/load-commands.js index d4295205c..242b52463 100644 --- a/src/utils/load-commands.js +++ b/src/utils/load-commands.js @@ -89,7 +89,9 @@ function requireCommands (send, config) { refsPullStream: pullify.source(refs), _refsAsyncIterator: refs, getEndpointConfig: require('../get-endpoint-config')(config), - bitswap: require('../bitswap')(config) + bitswap: require('../bitswap')(config), + block: require('../block')(config), + dag: require('../dag')(config) } Object.assign(cmds.refs, { @@ -103,11 +105,7 @@ function requireCommands (send, config) { // Files MFS (Mutable Filesystem) files: require('../files'), - // Block - block: require('../block'), - // Graph - dag: require('../dag'), object: require('../object'), pin: require('../pin'), From 14c5b9efdc1ba1dd08f2ce4e6bc3f4210648fdc5 Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Thu, 14 Nov 2019 13:24:42 +0000 Subject: [PATCH 181/233] refactor: convert bootstrap API to async/await (#1154) License: MIT Signed-off-by: Alan Shaw --- src/bootstrap/add.js | 46 +++++++++++++++++--------------------- src/bootstrap/index.js | 16 +++++-------- src/bootstrap/list.js | 28 ++++++++++++----------- src/bootstrap/rm.js | 46 +++++++++++++++++--------------------- src/utils/load-commands.js | 2 +- 5 files changed, 64 insertions(+), 74 deletions(-) diff --git a/src/bootstrap/add.js b/src/bootstrap/add.js index 978a3eeda..29dd46cc3 100644 --- a/src/bootstrap/add.js +++ b/src/bootstrap/add.js @@ -1,32 +1,28 @@ 'use strict' -const promisify = require('promisify-es6') +const Multiaddr = require('multiaddr') +const configure = require('../lib/configure') -module.exports = (send) => { - return promisify((args, opts, callback) => { - if (typeof opts === 'function' && - !callback) { - callback = opts - opts = {} +module.exports = configure(({ ky }) => { + return async (addr, options) => { + if (addr && typeof addr === 'object' && !Multiaddr.isMultiaddr(addr)) { + options = addr + addr = null } - // opts is the real callback -- - // 'callback' is being injected by promisify - if (typeof opts === 'function' && - typeof callback === 'function') { - callback = opts - opts = {} - } + options = options || {} - if (args && typeof args === 'object') { - opts = args - args = undefined - } + const searchParams = new URLSearchParams(options.searchParams) + if (addr) searchParams.set('arg', `${addr}`) + if (options.default != null) searchParams.set('default', options.default) + + const res = await ky.post('bootstrap/add', { + timeout: options.timeout, + signal: options.signal, + headers: options.headers, + searchParams + }).json() - send({ - path: 'bootstrap/add', - args: args, - qs: opts - }, callback) - }) -} + return res + } +}) diff --git a/src/bootstrap/index.js b/src/bootstrap/index.js index 31cb3fa2f..032265803 100644 --- a/src/bootstrap/index.js +++ b/src/bootstrap/index.js @@ -1,13 +1,9 @@ 'use strict' -const moduleConfig = require('../utils/module-config') +const callbackify = require('callbackify') -module.exports = (arg) => { - const send = moduleConfig(arg) - - return { - add: require('./add')(send), - rm: require('./rm')(send), - list: require('./list')(send) - } -} +module.exports = config => ({ + add: callbackify.variadic(require('./add')(config)), + rm: callbackify.variadic(require('./rm')(config)), + list: callbackify.variadic(require('./list')(config)) +}) diff --git a/src/bootstrap/list.js b/src/bootstrap/list.js index 79690ef19..2a20f5d05 100644 --- a/src/bootstrap/list.js +++ b/src/bootstrap/list.js @@ -1,16 +1,18 @@ 'use strict' -const promisify = require('promisify-es6') +const configure = require('../lib/configure') -module.exports = (send) => { - return promisify((opts, callback) => { - if (typeof (opts) === 'function') { - callback = opts - opts = {} - } - send({ - path: 'bootstrap/list', - qs: opts - }, callback) - }) -} +module.exports = configure(({ ky }) => { + return async (options) => { + options = options || {} + + const res = await ky.get('bootstrap/list', { + timeout: options.timeout, + signal: options.signal, + headers: options.headers, + searchParams: options.searchParams + }).json() + + return res + } +}) diff --git a/src/bootstrap/rm.js b/src/bootstrap/rm.js index c7f55368b..4c2597d1d 100644 --- a/src/bootstrap/rm.js +++ b/src/bootstrap/rm.js @@ -1,32 +1,28 @@ 'use strict' -const promisify = require('promisify-es6') +const Multiaddr = require('multiaddr') +const configure = require('../lib/configure') -module.exports = (send) => { - return promisify((args, opts, callback) => { - if (typeof opts === 'function' && - !callback) { - callback = opts - opts = {} +module.exports = configure(({ ky }) => { + return async (addr, options) => { + if (addr && typeof addr === 'object' && !Multiaddr.isMultiaddr(addr)) { + options = addr + addr = null } - // opts is the real callback -- - // 'callback' is being injected by promisify - if (typeof opts === 'function' && - typeof callback === 'function') { - callback = opts - opts = {} - } + options = options || {} - if (args && typeof args === 'object') { - opts = args - args = undefined - } + const searchParams = new URLSearchParams(options.searchParams) + if (addr) searchParams.set('arg', `${addr}`) + if (options.all != null) searchParams.set('all', options.all) + + const res = await ky.post('bootstrap/rm', { + timeout: options.timeout, + signal: options.signal, + headers: options.headers, + searchParams + }).json() - send({ - path: 'bootstrap/rm', - args: args, - qs: opts - }, callback) - }) -} + return res + } +}) diff --git a/src/utils/load-commands.js b/src/utils/load-commands.js index 242b52463..9e9db2cf5 100644 --- a/src/utils/load-commands.js +++ b/src/utils/load-commands.js @@ -91,6 +91,7 @@ function requireCommands (send, config) { getEndpointConfig: require('../get-endpoint-config')(config), bitswap: require('../bitswap')(config), block: require('../block')(config), + bootstrap: require('../bootstrap')(config), dag: require('../dag')(config) } @@ -110,7 +111,6 @@ function requireCommands (send, config) { pin: require('../pin'), // Network - bootstrap: require('../bootstrap'), dht: require('../dht'), name: require('../name'), ping: require('../ping'), From 621973c99916b4829e59aaf0fb67101284facfae Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Thu, 14 Nov 2019 13:48:17 +0000 Subject: [PATCH 182/233] refactor: convert config API to async await (#1155) BREAKING CHANGE: Errors returned from request failures are now all [`HTTPError`](https://github.com/sindresorhus/ky/blob/c0d9d2bb07e4c122a08f019b39e9c55a4c9324f3/index.js#L117-L123)s which carry a `response` property. This is a [`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response) that can be used to inspect _all_ information relating to the HTTP response. This means that the `err.status` or `err.statusCode` property should now be accessed via `err.response.status`. License: MIT Signed-off-by: Alan Shaw --- src/config/get.js | 54 +++++++++++++--------------------- src/config/index.js | 19 +++++------- src/config/profiles/apply.js | 21 ++++++------- src/config/profiles/index.js | 8 +++++ src/config/profiles/list.js | 15 ++++------ src/config/replace.js | 36 ++++++++++------------- src/config/set.js | 45 ++++++++++++++-------------- src/lib/error-handler.js | 12 ++++++-- src/utils/load-commands.js | 2 +- test/lib.error-handler.spec.js | 3 +- test/request-api.spec.js | 7 ++--- 11 files changed, 106 insertions(+), 116 deletions(-) create mode 100644 src/config/profiles/index.js diff --git a/src/config/get.js b/src/config/get.js index 882efe3df..b8a42a2e3 100644 --- a/src/config/get.js +++ b/src/config/get.js @@ -1,39 +1,27 @@ 'use strict' -const promisify = require('promisify-es6') +const configure = require('../lib/configure') -const toObject = function (res, callback) { - if (Buffer.isBuffer(res)) { - callback(null, JSON.parse(res.toString())) - } else { - callback(null, res) - } -} - -module.exports = (send) => { - return promisify((key, callback) => { - if (typeof key === 'function') { - callback = key - key = undefined +module.exports = configure(({ ky }) => { + return async (key, options) => { + if (key && typeof key === 'object') { + options = key + key = null } - if (!key) { - send.andTransform({ - path: 'config/show', - buffer: true - }, toObject, callback) - return - } + options = options || {} - send.andTransform({ - path: 'config', - args: key, - buffer: true - }, toObject, (err, response) => { - if (err) { - return callback(err) - } - callback(null, response.Value) - }) - }) -} + const searchParams = new URLSearchParams(options.searchParams) + if (key) searchParams.set('arg', key) + + const url = key ? 'config' : 'config/show' + const data = await ky.get(url, { + timeout: options.timeout, + signal: options.signal, + headers: options.headers, + searchParams + }).json() + + return key ? data.Value : data + } +}) diff --git a/src/config/index.js b/src/config/index.js index e88c195b5..36621fd39 100644 --- a/src/config/index.js +++ b/src/config/index.js @@ -1,13 +1,10 @@ 'use strict' -module.exports = (send, config) => { - return { - get: require('./get')(send), - set: require('./set')(send), - replace: require('./replace')(send), - profiles: { - apply: require('./profiles/apply')(config), - list: require('./profiles/list')(config) - } - } -} +const callbackify = require('callbackify') + +module.exports = config => ({ + get: callbackify.variadic(require('./get')(config)), + set: callbackify.variadic(require('./set')(config)), + replace: callbackify.variadic(require('./replace')(config)), + profiles: require('./profiles')(config) +}) diff --git a/src/config/profiles/apply.js b/src/config/profiles/apply.js index e4b05560b..deac884fe 100644 --- a/src/config/profiles/apply.js +++ b/src/config/profiles/apply.js @@ -1,27 +1,24 @@ 'use strict' -const callbackify = require('callbackify') const configure = require('../../lib/configure') module.exports = configure(({ ky }) => { - return callbackify.variadic(async (profile, options) => { + return async (profile, options) => { options = options || {} + const searchParams = new URLSearchParams(options.searchParams) + searchParams.set('arg', profile) + if (options.dryRun != null) searchParams.set('dry-run', options.dryRun) + const res = await ky.post('config/profile/apply', { timeout: options.timeout, signal: options.signal, headers: options.headers, - searchParams: { - arg: profile, - // can only pass strings or numbers as values https://github.com/sindresorhus/ky/issues/182 - 'dry-run': options.dryRun ? 'true' : 'false' - } - }) - - const parsed = await res.json() + searchParams + }).json() return { - original: parsed.OldCfg, updated: parsed.NewCfg + original: res.OldCfg, updated: res.NewCfg } - }) + } }) diff --git a/src/config/profiles/index.js b/src/config/profiles/index.js new file mode 100644 index 000000000..57cd1ad7f --- /dev/null +++ b/src/config/profiles/index.js @@ -0,0 +1,8 @@ +'use strict' + +const callbackify = require('callbackify') + +module.exports = config => ({ + apply: callbackify.variadic(require('./apply')(config)), + list: callbackify.variadic(require('./list')(config)) +}) diff --git a/src/config/profiles/list.js b/src/config/profiles/list.js index dbfa579cf..1e3f44308 100644 --- a/src/config/profiles/list.js +++ b/src/config/profiles/list.js @@ -1,22 +1,19 @@ 'use strict' -const callbackify = require('callbackify') const configure = require('../../lib/configure') const toCamel = require('../../lib/object-to-camel') module.exports = configure(({ ky }) => { - return callbackify.variadic(async (options) => { + return async (options) => { options = options || {} const res = await ky.get('config/profile/list', { timeout: options.timeout, signal: options.signal, - headers: options.headers - }) + headers: options.headers, + searchParams: options.searchParams + }).json() - const parsed = await res.json() - - return parsed - .map(profile => toCamel(profile)) - }) + return res.map(profile => toCamel(profile)) + } }) diff --git a/src/config/replace.js b/src/config/replace.js index 971c61ee0..ccca80beb 100644 --- a/src/config/replace.js +++ b/src/config/replace.js @@ -1,25 +1,21 @@ 'use strict' -const { Readable } = require('readable-stream') -const promisify = require('promisify-es6') -const SendOneFile = require('../utils/send-one-file') +const { Buffer } = require('buffer') +const configure = require('../lib/configure') +const toFormData = require('../lib/buffer-to-form-data') -function toStream (input) { - return new Readable({ - read () { - this.push(input) - this.push(null) - } - }) -} +module.exports = configure(({ ky }) => { + return async (config, options) => { + options = options || {} -module.exports = (send) => { - const sendOneFile = SendOneFile(send, 'config/replace') - return promisify((config, callback) => { - if (typeof config === 'object') { - config = toStream(Buffer.from(JSON.stringify(config))) - } + const res = await ky.post('config/replace', { + timeout: options.timeout, + signal: options.signal, + headers: options.headers, + searchParams: options.searchParams, + body: toFormData(Buffer.from(JSON.stringify(config))) + }).text() - sendOneFile(config, {}, callback) - }) -} + return res + } +}) diff --git a/src/config/set.js b/src/config/set.js index 0fa933565..f9e3309f2 100644 --- a/src/config/set.js +++ b/src/config/set.js @@ -1,35 +1,36 @@ 'use strict' -const promisify = require('promisify-es6') +const configure = require('../lib/configure') +const toCamel = require('../lib/object-to-camel') + +module.exports = configure(({ ky }) => { + return async (key, value, options) => { + options = options || {} -module.exports = (send) => { - return promisify((key, value, opts, callback) => { - if (typeof opts === 'function') { - callback = opts - opts = {} - } if (typeof key !== 'string') { - return callback(new Error('Invalid key type')) + throw new Error('Invalid key type') } - if (value === undefined || Buffer.isBuffer(value)) { - return callback(new Error('Invalid value type')) - } + const searchParams = new URLSearchParams(options.searchParams) if (typeof value === 'boolean') { + searchParams.set('bool', true) value = value.toString() - opts = { bool: true } } else if (typeof value !== 'string') { + searchParams.set('json', true) value = JSON.stringify(value) - opts = { json: true } } - send({ - path: 'config', - args: [key, value], - qs: opts, - files: undefined, - buffer: true - }, callback) - }) -} + searchParams.set('arg', key) + searchParams.append('arg', value) + + const res = await ky.post('config', { + timeout: options.timeout, + signal: options.signal, + headers: options.headers, + searchParams + }).json() + + return toCamel(res) + } +}) diff --git a/src/lib/error-handler.js b/src/lib/error-handler.js index 032a6acc8..3aae8a41c 100644 --- a/src/lib/error-handler.js +++ b/src/lib/error-handler.js @@ -35,9 +35,15 @@ module.exports = async function errorHandler (input, options, response) { } catch (err) { log('Failed to parse error response', err) // Failed to extract/parse error message from response - throw new HTTPError(response) + msg = err.message } - if (!msg) throw new HTTPError(response) - throw Object.assign(new Error(msg), { status: response.status }) + const error = new HTTPError(response) + + // If we managed to extract a message from the response, use it + if (msg) { + error.message = msg + } + + throw error } diff --git a/src/utils/load-commands.js b/src/utils/load-commands.js index 9e9db2cf5..34a7591e5 100644 --- a/src/utils/load-commands.js +++ b/src/utils/load-commands.js @@ -92,6 +92,7 @@ function requireCommands (send, config) { bitswap: require('../bitswap')(config), block: require('../block')(config), bootstrap: require('../bootstrap')(config), + config: require('../config')(config), dag: require('../dag')(config) } @@ -122,7 +123,6 @@ function requireCommands (send, config) { // Miscellaneous commands: require('../commands'), - config: require('../config'), diag: require('../diag'), id: require('../id'), key: require('../key'), diff --git a/test/lib.error-handler.spec.js b/test/lib.error-handler.spec.js index bdc0fc8a3..c39e3040d 100644 --- a/test/lib.error-handler.spec.js +++ b/test/lib.error-handler.spec.js @@ -21,8 +21,9 @@ describe('lib/error-handler', () => { const err = await throwsAsync(errorHandler(null, null, res)) + expect(err instanceof HTTPError).to.be.true() expect(err.message).to.eql('boom') - expect(err.status).to.eql(500) + expect(err.response.status).to.eql(500) }) it('should gracefully fail on parse json', async () => { diff --git a/test/request-api.spec.js b/test/request-api.spec.js index 1b0858786..c213193bb 100644 --- a/test/request-api.spec.js +++ b/test/request-api.spec.js @@ -81,7 +81,7 @@ describe('error handling', () => { server.listen(6001, () => { ipfsClient('/ip4/127.0.0.1/tcp/6001').config.replace('test/fixtures/r-config.json', (err) => { expect(err).to.exist() - expect(err.statusCode).to.equal(403) + expect(err.response.status).to.equal(403) expect(err.message).to.equal('ipfs method not allowed') server.close(done) }) @@ -105,9 +105,8 @@ describe('error handling', () => { server.listen(6001, () => { ipfsClient('/ip4/127.0.0.1/tcp/6001').config.replace('test/fixtures/r-config.json', (err) => { expect(err).to.exist() - expect(err.statusCode).to.equal(400) + expect(err.response.status).to.equal(400) expect(err.message).to.equal('client error') - expect(err.code).to.equal(1) server.close(done) }) }) @@ -130,7 +129,7 @@ describe('error handling', () => { server.listen(6001, () => { ipfsClient('/ip4/127.0.0.1/tcp/6001').config.replace('test/fixtures/r-config.json', (err) => { expect(err).to.exist() - expect(err.message).to.include('Invalid JSON') + expect(err.message).to.include('Unexpected token M in JSON at position 2') server.close(done) }) }) From 5110423663f19eb8259de9718be909e2f3921de4 Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Thu, 14 Nov 2019 18:57:34 +0000 Subject: [PATCH 183/233] refactor: convert dht API to async/await (#1156) --- src/dht/find-peer.js | 37 +++++++++++++++ src/dht/find-provs.js | 38 ++++++++++++++++ src/dht/findpeer.js | 63 -------------------------- src/dht/findprovs.js | 63 -------------------------- src/dht/get.js | 62 +++++++++---------------- src/dht/index.js | 31 +++++++++---- src/dht/provide.js | 63 ++++++++++++++------------ src/dht/put.js | 56 +++++++++++++++-------- src/dht/query.js | 57 +++++++++-------------- src/lib/encode-buffer-uri-component.js | 25 ++++++++++ src/pubsub/publish.js | 24 +--------- src/utils/load-commands.js | 4 +- 12 files changed, 238 insertions(+), 285 deletions(-) create mode 100644 src/dht/find-peer.js create mode 100644 src/dht/find-provs.js delete mode 100644 src/dht/findpeer.js delete mode 100644 src/dht/findprovs.js create mode 100644 src/lib/encode-buffer-uri-component.js diff --git a/src/dht/find-peer.js b/src/dht/find-peer.js new file mode 100644 index 000000000..953e9fc78 --- /dev/null +++ b/src/dht/find-peer.js @@ -0,0 +1,37 @@ +'use strict' + +const PeerId = require('peer-id') +const PeerInfo = require('peer-info') +const multiaddr = require('multiaddr') +const ndjson = require('iterable-ndjson') +const configure = require('../lib/configure') +const toIterable = require('../lib/stream-to-iterable') + +module.exports = configure(({ ky }) => { + return (peerId, options) => (async function * () { + options = options || {} + + const searchParams = new URLSearchParams(options.searchParams) + searchParams.set('arg', `${peerId}`) + if (options.verbose != null) searchParams.set('verbose', options.verbose) + + const res = await ky.get('dht/findpeer', { + timeout: options.timeout, + signal: options.signal, + headers: options.headers, + searchParams + }) + + for await (const message of ndjson(toIterable(res.body))) { + // 2 = FinalPeer + // https://github.com/libp2p/go-libp2p-core/blob/6e566d10f4a5447317a66d64c7459954b969bdab/routing/query.go#L18 + if (message.Type === 2 && message.Responses) { + for (const { ID, Addrs } of message.Responses) { + const peerInfo = new PeerInfo(PeerId.createFromB58String(ID)) + if (Addrs) Addrs.forEach(a => peerInfo.multiaddrs.add(multiaddr(a))) + yield peerInfo + } + } + } + })() +}) diff --git a/src/dht/find-provs.js b/src/dht/find-provs.js new file mode 100644 index 000000000..b04d001d8 --- /dev/null +++ b/src/dht/find-provs.js @@ -0,0 +1,38 @@ +'use strict' + +const PeerId = require('peer-id') +const PeerInfo = require('peer-info') +const multiaddr = require('multiaddr') +const ndjson = require('iterable-ndjson') +const configure = require('../lib/configure') +const toIterable = require('../lib/stream-to-iterable') + +module.exports = configure(({ ky }) => { + return (cid, options) => (async function * () { + options = options || {} + + const searchParams = new URLSearchParams(options.searchParams) + searchParams.set('arg', `${cid}`) + if (options.numProviders) searchParams.set('num-providers', options.numProviders) + if (options.verbose != null) searchParams.set('verbose', options.verbose) + + const res = await ky.get('dht/findprovs', { + timeout: options.timeout, + signal: options.signal, + headers: options.headers, + searchParams + }) + + for await (const message of ndjson(toIterable(res.body))) { + // 4 = Provider + // https://github.com/libp2p/go-libp2p-core/blob/6e566d10f4a5447317a66d64c7459954b969bdab/routing/query.go#L20 + if (message.Type === 4 && message.Responses) { + for (const { ID, Addrs } of message.Responses) { + const peerInfo = new PeerInfo(PeerId.createFromB58String(ID)) + if (Addrs) Addrs.forEach(a => peerInfo.multiaddrs.add(multiaddr(a))) + yield peerInfo + } + } + } + })() +}) diff --git a/src/dht/findpeer.js b/src/dht/findpeer.js deleted file mode 100644 index 8bcc80fb5..000000000 --- a/src/dht/findpeer.js +++ /dev/null @@ -1,63 +0,0 @@ -'use strict' - -const promisify = require('promisify-es6') -const streamToValueWithTransformer = require('../utils/stream-to-value-with-transformer') - -const multiaddr = require('multiaddr') -const PeerId = require('peer-id') -const PeerInfo = require('peer-info') -const errcode = require('err-code') - -module.exports = (send) => { - return promisify((peerId, opts, callback) => { - if (typeof opts === 'function' && !callback) { - callback = opts - opts = {} - } - - // opts is the real callback -- - // 'callback' is being injected by promisify - if (typeof opts === 'function' && typeof callback === 'function') { - callback = opts - opts = {} - } - - const handleResult = (res, callback) => { - // Inconsistent return values in the browser - if (Array.isArray(res)) { - res = res.find(r => r.Type === 2) - } - - // Type 2 keys - // 2 = FinalPeer - // https://github.com/libp2p/go-libp2p-core/blob/6e566d10f4a5447317a66d64c7459954b969bdab/routing/query.go#L18 - if (!res || res.Type !== 2) { - const errMsg = 'key was not found (type 4)' - return callback(errcode(new Error(errMsg), 'ERR_KEY_TYPE_4_NOT_FOUND')) - } - - const responseReceived = res.Responses[0] - const peerInfo = new PeerInfo(PeerId.createFromB58String(responseReceived.ID)) - - responseReceived.Addrs.forEach((addr) => { - const ma = multiaddr(addr) - - peerInfo.multiaddrs.add(ma) - }) - - callback(null, peerInfo) - } - - send({ - path: 'dht/findpeer', - args: peerId.toString(), - qs: opts - }, (err, result) => { - if (err) { - return callback(err) - } - - streamToValueWithTransformer(result, handleResult, callback) - }) - }) -} diff --git a/src/dht/findprovs.js b/src/dht/findprovs.js deleted file mode 100644 index 695ef04df..000000000 --- a/src/dht/findprovs.js +++ /dev/null @@ -1,63 +0,0 @@ -'use strict' - -const promisify = require('promisify-es6') -const streamToValueWithTransformer = require('../utils/stream-to-value-with-transformer') - -const multiaddr = require('multiaddr') -const PeerId = require('peer-id') -const PeerInfo = require('peer-info') - -module.exports = (send) => { - return promisify((cid, opts, callback) => { - if (typeof opts === 'function' && !callback) { - callback = opts - opts = {} - } - - // opts is the real callback -- - // 'callback' is being injected by promisify - if (typeof opts === 'function' && typeof callback === 'function') { - callback = opts - opts = {} - } - - const handleResult = (res, callback) => { - // Inconsistent return values in the browser vs node - if (!Array.isArray(res)) { - res = [res] - } - - const responses = [] - res.forEach(result => { - // 4 = Provider - if (result.Type !== 4) return - result.Responses.forEach(response => { - const peerInfo = new PeerInfo(PeerId.createFromB58String(response.ID)) - - if (response.Addrs) { - response.Addrs.forEach((addr) => { - const ma = multiaddr(addr) - peerInfo.multiaddrs.add(ma) - }) - } - - responses.push(peerInfo) - }) - }) - - callback(null, responses) - } - - send({ - path: 'dht/findprovs', - args: cid.toString(), - qs: opts - }, (err, result) => { - if (err) { - return callback(err) - } - - streamToValueWithTransformer(result, handleResult, callback) - }) - }) -} diff --git a/src/dht/get.js b/src/dht/get.js index ab64fa892..8a7b8c6a3 100644 --- a/src/dht/get.js +++ b/src/dht/get.js @@ -1,48 +1,30 @@ 'use strict' -const promisify = require('promisify-es6') +const ndjson = require('iterable-ndjson') +const configure = require('../lib/configure') +const toIterable = require('../lib/stream-to-iterable') -module.exports = (send) => { - return promisify((key, opts, callback) => { - if (typeof opts === 'function' && !callback) { - callback = opts - opts = {} - } - - // opts is the real callback -- - // 'callback' is being injected by promisify - if (typeof opts === 'function' && typeof callback === 'function') { - callback = opts - opts = {} - } +module.exports = configure(({ ky }) => { + return (key, options) => (async function * () { + options = options || {} - function handleResult (done, err, res) { - if (err) { - return done(err) - } - if (!res) { - return done(new Error('empty response')) - } - if (res.length === 0) { - return done(new Error('no value returned for key')) - } + const searchParams = new URLSearchParams(options.searchParams) + searchParams.set('arg', `${key}`) + if (options.verbose != null) searchParams.set('verbose', options.verbose) - // Inconsistent return values in the browser vs node - if (Array.isArray(res)) { - res = res[0] - } + const res = await ky.get('dht/get', { + timeout: options.timeout, + signal: options.signal, + headers: options.headers, + searchParams + }) - if (res.Type === 5) { - done(null, res.Extra) - } else { - done(new Error('key was not found (type 6)')) + for await (const message of ndjson(toIterable(res.body))) { + // 5 = Value + // https://github.com/libp2p/go-libp2p-core/blob/6e566d10f4a5447317a66d64c7459954b969bdab/routing/query.go#L21 + if (message.Type === 5) { + yield message.Extra } } - - send({ - path: 'dht/get', - args: key, - qs: opts - }, handleResult.bind(null, callback)) - }) -} + })() +}) diff --git a/src/dht/index.js b/src/dht/index.js index b4ab8c640..5478876ff 100644 --- a/src/dht/index.js +++ b/src/dht/index.js @@ -1,17 +1,30 @@ 'use strict' -const moduleConfig = require('../utils/module-config') +const callbackify = require('callbackify') +const errCode = require('err-code') +const { collectify } = require('../lib/converters') -module.exports = (arg) => { - const send = moduleConfig(arg) +module.exports = config => { + const get = require('./get')(config) + const findPeer = require('./find-peer')(config) return { - get: require('./get')(send), - put: require('./put')(send), - findProvs: require('./findprovs')(send), - findPeer: require('./findpeer')(send), - provide: require('./provide')(send), + get: callbackify.variadic(async (key, options) => { + for await (const value of get(key, options)) { + return value + } + throw errCode(new Error('value not found'), 'ERR_TYPE_5_NOT_FOUND') + }), + put: callbackify.variadic(collectify(require('./put')(config))), + findProvs: callbackify.variadic(collectify(require('./find-provs')(config))), + findPeer: callbackify.variadic(async (peerId, options) => { + for await (const peerInfo of findPeer(peerId, options)) { + return peerInfo + } + throw errCode(new Error('final peer not found'), 'ERR_TYPE_2_NOT_FOUND') + }), + provide: callbackify.variadic(collectify(require('./provide')(config))), // find closest peerId to given peerId - query: require('./query')(send) + query: callbackify.variadic(collectify(require('./query')(config))) } } diff --git a/src/dht/provide.js b/src/dht/provide.js index 08bcad6d7..1f05710ec 100644 --- a/src/dht/provide.js +++ b/src/dht/provide.js @@ -1,37 +1,40 @@ 'use strict' -const promisify = require('promisify-es6') -const CID = require('cids') +const PeerId = require('peer-id') +const PeerInfo = require('peer-info') +const multiaddr = require('multiaddr') +const ndjson = require('iterable-ndjson') +const configure = require('../lib/configure') +const toIterable = require('../lib/stream-to-iterable') +const toCamel = require('../lib/object-to-camel') -module.exports = (send) => { - return promisify((cids, opts, callback) => { - if (typeof opts === 'function' && !callback) { - callback = opts - opts = {} - } +module.exports = configure(({ ky }) => { + return (cids, options) => (async function * () { + cids = Array.isArray(cids) ? cids : [cids] + options = options || {} - // opts is the real callback -- - // 'callback' is being injected by promisify - if (typeof opts === 'function' && typeof callback === 'function') { - callback = opts - opts = {} - } + const searchParams = new URLSearchParams(options.searchParams) + cids.forEach(cid => searchParams.append('arg', `${cid}`)) + if (options.recursive != null) searchParams.set('recursive', options.recursive) + if (options.verbose != null) searchParams.set('verbose', options.verbose) - if (!Array.isArray(cids)) { - cids = [cids] - } + const res = await ky.get('dht/provide', { + timeout: options.timeout, + signal: options.signal, + headers: options.headers, + searchParams + }) - // Validate CID(s) and serialize - try { - cids = cids.map(cid => new CID(cid).toBaseEncodedString('base58btc')) - } catch (err) { - return callback(err) + for await (let message of ndjson(toIterable(res.body))) { + message = toCamel(message) + if (message.responses) { + message.responses = message.responses.map(({ ID, Addrs }) => { + const peerInfo = new PeerInfo(PeerId.createFromB58String(ID)) + if (Addrs) Addrs.forEach(a => peerInfo.multiaddrs.add(multiaddr(a))) + return peerInfo + }) + } + yield message } - - send({ - path: 'dht/provide', - args: cids, - qs: opts - }, callback) - }) -} + })() +}) diff --git a/src/dht/put.js b/src/dht/put.js index c0937d158..50137e528 100644 --- a/src/dht/put.js +++ b/src/dht/put.js @@ -1,25 +1,41 @@ 'use strict' -const promisify = require('promisify-es6') +const PeerId = require('peer-id') +const PeerInfo = require('peer-info') +const multiaddr = require('multiaddr') +const ndjson = require('iterable-ndjson') +const configure = require('../lib/configure') +const toIterable = require('../lib/stream-to-iterable') +const encodeBufferURIComponent = require('../lib/encode-buffer-uri-component') +const toCamel = require('../lib/object-to-camel') -module.exports = (send) => { - return promisify((key, value, opts, callback) => { - if (typeof opts === 'function' && !callback) { - callback = opts - opts = {} - } +module.exports = configure(({ ky }) => { + return (key, value, options) => (async function * () { + options = options || {} - // opts is the real callback -- - // 'callback' is being injected by promisify - if (typeof opts === 'function' && typeof callback === 'function') { - callback = opts - opts = {} - } + const searchParams = new URLSearchParams(options.searchParams) + if (options.verbose != null) searchParams.set('verbose', options.verbose) + + key = Buffer.isBuffer(key) ? encodeBufferURIComponent(key) : encodeURIComponent(key) + value = Buffer.isBuffer(value) ? encodeBufferURIComponent(value) : encodeURIComponent(value) - send({ - path: 'dht/put', - args: [key, value], - qs: opts - }, callback) - }) -} + const url = `dht/put?arg=${key}&arg=${value}&${searchParams}` + const res = await ky.get(url, { + timeout: options.timeout, + signal: options.signal, + headers: options.headers + }) + + for await (let message of ndjson(toIterable(res.body))) { + message = toCamel(message) + if (message.responses) { + message.responses = message.responses.map(({ ID, Addrs }) => { + const peerInfo = new PeerInfo(PeerId.createFromB58String(ID)) + if (Addrs) Addrs.forEach(a => peerInfo.multiaddrs.add(multiaddr(a))) + return peerInfo + }) + } + yield message + } + })() +}) diff --git a/src/dht/query.js b/src/dht/query.js index 2dbc62a47..8ebca71f7 100644 --- a/src/dht/query.js +++ b/src/dht/query.js @@ -1,41 +1,28 @@ 'use strict' -const promisify = require('promisify-es6') -const streamToValueWithTransformer = require('../utils/stream-to-value-with-transformer') - const PeerId = require('peer-id') const PeerInfo = require('peer-info') +const ndjson = require('iterable-ndjson') +const configure = require('../lib/configure') +const toIterable = require('../lib/stream-to-iterable') + +module.exports = configure(({ ky }) => { + return (peerId, options) => (async function * () { + options = options || {} + + const searchParams = new URLSearchParams(options.searchParams) + searchParams.set('arg', `${peerId}`) + if (options.verbose != null) searchParams.set('verbose', options.verbose) + + const res = await ky.get('dht/query', { + timeout: options.timeout, + signal: options.signal, + headers: options.headers, + searchParams + }) -module.exports = (send) => { - return promisify((peerId, opts, callback) => { - if (typeof opts === 'function' && !callback) { - callback = opts - opts = {} - } - - // opts is the real callback -- - // 'callback' is being injected by promisify - if (typeof opts === 'function' && typeof callback === 'function') { - callback = opts - opts = {} - } - - const handleResult = (res, callback) => { - const peerIds = res.map((r) => (new PeerInfo(PeerId.createFromB58String(r.ID)))) - - callback(null, peerIds) + for await (const message of ndjson(toIterable(res.body))) { + yield new PeerInfo(PeerId.createFromB58String(message.ID)) } - - send({ - path: 'dht/query', - args: peerId, - qs: opts - }, (err, result) => { - if (err) { - return callback(err) - } - - streamToValueWithTransformer(result, handleResult, callback) - }) - }) -} + })() +}) diff --git a/src/lib/encode-buffer-uri-component.js b/src/lib/encode-buffer-uri-component.js new file mode 100644 index 000000000..c231970cb --- /dev/null +++ b/src/lib/encode-buffer-uri-component.js @@ -0,0 +1,25 @@ +'use strict' + +// https://github.com/ipfs/js-ipfs-http-client/issues/569 +module.exports = function encodeBuffer (buf) { + let uriEncoded = '' + for (const byte of buf) { + // https://tools.ietf.org/html/rfc3986#page-14 + // ALPHA (%41-%5A and %61-%7A), DIGIT (%30-%39), hyphen (%2D), period (%2E), + // underscore (%5F), or tilde (%7E) + if ( + (byte >= 0x41 && byte <= 0x5A) || + (byte >= 0x61 && byte <= 0x7A) || + (byte >= 0x30 && byte <= 0x39) || + (byte === 0x2D) || + (byte === 0x2E) || + (byte === 0x5F) || + (byte === 0x7E) + ) { + uriEncoded += String.fromCharCode(byte) + } else { + uriEncoded += `%${byte.toString(16).padStart(2, '0')}` + } + } + return uriEncoded +} diff --git a/src/pubsub/publish.js b/src/pubsub/publish.js index a41c8fba0..10a5017cc 100644 --- a/src/pubsub/publish.js +++ b/src/pubsub/publish.js @@ -2,6 +2,7 @@ const { Buffer } = require('buffer') const configure = require('../lib/configure') +const encodeBuffer = require('../lib/encode-buffer-uri-component') module.exports = configure(({ ky }) => { return async (topic, data, options) => { @@ -20,26 +21,3 @@ module.exports = configure(({ ky }) => { return res } }) - -function encodeBuffer (buf) { - let uriEncoded = '' - for (const byte of buf) { - // https://tools.ietf.org/html/rfc3986#page-14 - // ALPHA (%41-%5A and %61-%7A), DIGIT (%30-%39), hyphen (%2D), period (%2E), - // underscore (%5F), or tilde (%7E) - if ( - (byte >= 0x41 && byte <= 0x5A) || - (byte >= 0x61 && byte <= 0x7A) || - (byte >= 0x30 && byte <= 0x39) || - (byte === 0x2D) || - (byte === 0x2E) || - (byte === 0x5F) || - (byte === 0x7E) - ) { - uriEncoded += String.fromCharCode(byte) - } else { - uriEncoded += `%${byte.toString(16).padStart(2, '0')}` - } - } - return uriEncoded -} diff --git a/src/utils/load-commands.js b/src/utils/load-commands.js index 34a7591e5..fae44d26c 100644 --- a/src/utils/load-commands.js +++ b/src/utils/load-commands.js @@ -93,7 +93,8 @@ function requireCommands (send, config) { block: require('../block')(config), bootstrap: require('../bootstrap')(config), config: require('../config')(config), - dag: require('../dag')(config) + dag: require('../dag')(config), + dht: require('../dht')(config) } Object.assign(cmds.refs, { @@ -112,7 +113,6 @@ function requireCommands (send, config) { pin: require('../pin'), // Network - dht: require('../dht'), name: require('../name'), ping: require('../ping'), pingReadableStream: require('../ping-readable-stream'), From 0e011873747f9d8754d26ca21792df865fda8b1e Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Thu, 14 Nov 2019 20:41:21 +0000 Subject: [PATCH 184/233] refactor: convert diag API to async/await (#1157) License: MIT Signed-off-by: Alan Shaw --- src/diag/cmds.js | 28 +++++++++++++++------------- src/diag/index.js | 16 ++++++---------- src/diag/net.js | 25 ++++++++++++------------- src/diag/sys.js | 25 ++++++++++++------------- src/utils/load-commands.js | 4 ++-- 5 files changed, 47 insertions(+), 51 deletions(-) diff --git a/src/diag/cmds.js b/src/diag/cmds.js index e717604fa..68f20ca04 100644 --- a/src/diag/cmds.js +++ b/src/diag/cmds.js @@ -1,17 +1,19 @@ 'use strict' -const promisify = require('promisify-es6') +const configure = require('../lib/configure') -module.exports = (send) => { - return promisify((opts, callback) => { - if (typeof (opts) === 'function') { - callback = opts - opts = {} - } +module.exports = configure(({ ky }) => { + return options => { + options = options || {} - send({ - path: 'diag/cmds', - qs: opts - }, callback) - }) -} + const searchParams = new URLSearchParams(options.searchParams) + if (options.verbose != null) searchParams.set('verbose', options.verbose) + + return ky.get('diag/cmds', { + timeout: options.timeout, + signal: options.signal, + headers: options.headers, + searchParams + }).json() + } +}) diff --git a/src/diag/index.js b/src/diag/index.js index b24f7af53..7e48d576d 100644 --- a/src/diag/index.js +++ b/src/diag/index.js @@ -1,13 +1,9 @@ 'use strict' -const moduleConfig = require('../utils/module-config') +const callbackify = require('callbackify') -module.exports = (arg) => { - const send = moduleConfig(arg) - - return { - net: require('./net')(send), - sys: require('./sys')(send), - cmds: require('./cmds')(send) - } -} +module.exports = config => ({ + net: callbackify.variadic(require('./net')(config)), + sys: callbackify.variadic(require('./sys')(config)), + cmds: callbackify.variadic(require('./cmds')(config)) +}) diff --git a/src/diag/net.js b/src/diag/net.js index 9c84988d1..a7404b802 100644 --- a/src/diag/net.js +++ b/src/diag/net.js @@ -1,17 +1,16 @@ 'use strict' -const promisify = require('promisify-es6') +const configure = require('../lib/configure') -module.exports = (send) => { - return promisify((opts, callback) => { - if (typeof (opts) === 'function') { - callback = opts - opts = {} - } +module.exports = configure(({ ky }) => { + return options => { + options = options || {} - send({ - path: 'diag/net', - qs: opts - }, callback) - }) -} + return ky.get('diag/net', { + timeout: options.timeout, + signal: options.signal, + headers: options.headers, + searchParams: options.searchParams + }).json() + } +}) diff --git a/src/diag/sys.js b/src/diag/sys.js index c06968942..a8cd91b6f 100644 --- a/src/diag/sys.js +++ b/src/diag/sys.js @@ -1,17 +1,16 @@ 'use strict' -const promisify = require('promisify-es6') +const configure = require('../lib/configure') -module.exports = (send) => { - return promisify((opts, callback) => { - if (typeof (opts) === 'function') { - callback = opts - opts = {} - } +module.exports = configure(({ ky }) => { + return options => { + options = options || {} - send({ - path: 'diag/sys', - qs: opts - }, callback) - }) -} + return ky.get('diag/sys', { + timeout: options.timeout, + signal: options.signal, + headers: options.headers, + searchParams: options.searchParams + }).json() + } +}) diff --git a/src/utils/load-commands.js b/src/utils/load-commands.js index fae44d26c..14545b564 100644 --- a/src/utils/load-commands.js +++ b/src/utils/load-commands.js @@ -94,7 +94,8 @@ function requireCommands (send, config) { bootstrap: require('../bootstrap')(config), config: require('../config')(config), dag: require('../dag')(config), - dht: require('../dht')(config) + dht: require('../dht')(config), + diag: require('../diag')(config) } Object.assign(cmds.refs, { @@ -123,7 +124,6 @@ function requireCommands (send, config) { // Miscellaneous commands: require('../commands'), - diag: require('../diag'), id: require('../id'), key: require('../key'), log: require('../log'), From 12b7a2e6a98569d6a9ca4c3c01c6c74646a50102 Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Mon, 18 Nov 2019 15:51:40 +0000 Subject: [PATCH 185/233] refactor: switch tar-stream for it-tar (#1161) This switches out `tar-stream` for [`it-tar`](https://www.npmjs.com/package/it-tar), which is a fork that uses pure async iterables. This removes `readable-stream` from this branch of the tree (which will allow us to drop it entirely in the future) and allows us to drop the `event-iterator` dependency. --- package.json | 3 +- src/get.js | 18 ++++++- src/utils/load-commands.js | 24 +++++++-- src/utils/tar-stream-to-objects.js | 85 ------------------------------ 4 files changed, 38 insertions(+), 92 deletions(-) delete mode 100644 src/utils/tar-stream-to-objects.js diff --git a/package.json b/package.json index acd90bb63..bfc80c569 100644 --- a/package.json +++ b/package.json @@ -57,7 +57,6 @@ "detect-node": "^2.0.4", "end-of-stream": "^1.4.1", "err-code": "^2.0.0", - "event-iterator": "^1.2.0", "explain-error": "^1.0.4", "flatmap": "0.0.3", "form-data": "^3.0.0", @@ -74,6 +73,7 @@ "iso-stream-http": "~0.1.2", "iso-url": "~0.4.6", "it-glob": "0.0.6", + "it-tar": "^1.1.0", "it-to-stream": "^0.1.1", "iterable-ndjson": "^1.1.0", "just-kebab-case": "^1.1.0", @@ -101,7 +101,6 @@ "qs": "^6.5.2", "readable-stream": "^3.1.1", "stream-to-pull-stream": "^1.7.2", - "tar-stream": "^2.0.1", "through2": "^3.0.1" }, "devDependencies": { diff --git a/src/get.js b/src/get.js index 62adfd1e9..c06fc6d36 100644 --- a/src/get.js +++ b/src/get.js @@ -1,8 +1,9 @@ 'use strict' const configure = require('./lib/configure') -const tarStreamToObjects = require('./utils/tar-stream-to-objects') +const Tar = require('it-tar') const IsIpfs = require('is-ipfs') +const toIterable = require('./lib/stream-to-iterable') const cleanCID = require('./utils/clean-cid') module.exports = configure(({ ky }) => { @@ -43,6 +44,19 @@ module.exports = configure(({ ky }) => { searchParams }) - yield * tarStreamToObjects(res.body) + const extractor = Tar.extract() + + for await (const { header, body } of extractor(toIterable(res.body))) { + if (header.type === 'directory') { + yield { + path: header.name + } + } else { + yield { + path: header.name, + content: body + } + } + } } }) diff --git a/src/utils/load-commands.js b/src/utils/load-commands.js index 14545b564..3e51acdb2 100644 --- a/src/utils/load-commands.js +++ b/src/utils/load-commands.js @@ -7,6 +7,8 @@ const { concatify, collectify, pullify, streamify } = require('../lib/converters const toPullStream = require('async-iterator-to-pull-stream') const pull = require('pull-stream/pull') const map = require('pull-stream/throughs/map') +const toStream = require('it-to-stream') +const BufferList = require('bl/BufferList') function requireCommands (send, config) { const add = require('../add')(config) @@ -58,7 +60,7 @@ function requireCommands (send, config) { for await (const entry of get(path, options)) { if (entry.content) { - entry.content = Buffer.concat(await all(entry.content)) + entry.content = new BufferList(await all(entry.content)).slice() } output.push(entry) @@ -66,13 +68,29 @@ function requireCommands (send, config) { return output }), - getReadableStream: streamify.readable(get), + getReadableStream: streamify.readable((path, options) => (async function * () { + for await (const file of get(path, options)) { + if (file.content) { + const { content } = file + file.content = toStream((async function * () { + for await (const chunk of content) { + yield chunk.slice() // Convert bl to Buffer + } + })()) + } + + yield file + } + })()), getPullStream: (path, options) => { return pull( toPullStream(get(path, options)), map(file => { if (file.content) { - file.content = toPullStream(file.content) + file.content = pull( + toPullStream(file.content), + map(chunk => chunk.slice()) // Convert bl to Buffer + ) } return file diff --git a/src/utils/tar-stream-to-objects.js b/src/utils/tar-stream-to-objects.js deleted file mode 100644 index 7241b3445..000000000 --- a/src/utils/tar-stream-to-objects.js +++ /dev/null @@ -1,85 +0,0 @@ -'use strict' - -const tar = require('tar-stream') -const { EventIterator } = require('event-iterator') - -function pipe (reader, writable) { - reader.read() - .then(({ done, value }) => { - if (done) { - writable.end() - - return - } - - if (value) { - const beneathHighWaterMark = writable.write(value) - - if (beneathHighWaterMark) { - pipe(reader, writable) - } else { - writable.once('drain', () => { - pipe(reader, writable) - }) - } - } - }, (err) => { - writable.emit('error', err) - }) -} - -/* - Transform a tar readable stream into an async iterator of objects: - - Output format: - { path: 'string', content: AsyncIterator } -*/ -async function * tarStreamToObjects (inputStream) { - const extractStream = tar.extract() - let onEntry - - const tarStream = new EventIterator( - (push, stop, fail) => { - onEntry = (header, stream, next) => { - push({ header, stream }) - - next() - } - - extractStream.addListener('entry', onEntry) - extractStream.addListener('finish', stop) - extractStream.addListener('error', fail) - }, - (push, stop, fail) => { - extractStream.removeListener('entry', onEntry) - extractStream.removeListener('finish', stop) - extractStream.removeListener('error', fail) - extractStream.destroy() - } - ) - - if (inputStream.pipe) { - // node stream - inputStream.pipe(extractStream) - } else if (inputStream.getReader) { - // browser readable stream - pipe(inputStream.getReader(), extractStream) - } else { - throw new Error('Unknown stream type') - } - - for await (const { header, stream } of tarStream) { - if (header.type === 'directory') { - yield { - path: header.name - } - } else { - yield { - path: header.name, - content: stream - } - } - } -} - -module.exports = tarStreamToObjects From 8b48d57a106968b3d766939cb1ed3b6bc3365d14 Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Tue, 19 Nov 2019 22:46:14 +0000 Subject: [PATCH 186/233] refactor: convert pin API to async/await (#1168) License: MIT Signed-off-by: Alan Shaw --- src/pin/add.js | 38 ++++++++++++++-------------- src/pin/index.js | 16 +++++------- src/pin/ls.js | 52 +++++++++++++++++--------------------- src/pin/rm.js | 38 ++++++++++++++-------------- src/utils/load-commands.js | 4 +-- 5 files changed, 69 insertions(+), 79 deletions(-) diff --git a/src/pin/add.js b/src/pin/add.js index 7ef730eec..74eb47a2d 100644 --- a/src/pin/add.js +++ b/src/pin/add.js @@ -1,22 +1,22 @@ 'use strict' -const promisify = require('promisify-es6') +const configure = require('../lib/configure') -module.exports = (send) => { - return promisify((hash, opts, callback) => { - if (typeof opts === 'function') { - callback = opts - opts = null - } - send({ - path: 'pin/add', - args: hash, - qs: opts - }, (err, res) => { - if (err) { - return callback(err) - } - callback(null, res.Pins.map((hash) => ({ hash: hash }))) - }) - }) -} +module.exports = configure(({ ky }) => { + return async (path, options) => { + options = options || {} + + const searchParams = new URLSearchParams(options.searchParams) + searchParams.set('arg', `${path}`) + if (options.recursive != null) searchParams.set('recursive', options.recursive) + + const res = await ky.post('pin/add', { + timeout: options.timeout, + signal: options.signal, + headers: options.headers, + searchParams + }).json() + + return (res.Pins || []).map(hash => ({ hash })) + } +}) diff --git a/src/pin/index.js b/src/pin/index.js index 859052e2c..c62d3a46a 100644 --- a/src/pin/index.js +++ b/src/pin/index.js @@ -1,13 +1,9 @@ 'use strict' -const moduleConfig = require('../utils/module-config') +const callbackify = require('callbackify') -module.exports = (arg) => { - const send = moduleConfig(arg) - - return { - add: require('./add')(send), - rm: require('./rm')(send), - ls: require('./ls')(send) - } -} +module.exports = config => ({ + add: callbackify.variadic(require('./add')(config)), + rm: callbackify.variadic(require('./rm')(config)), + ls: callbackify.variadic(require('./ls')(config)) +}) diff --git a/src/pin/ls.js b/src/pin/ls.js index c8ad26a4b..bf1746d63 100644 --- a/src/pin/ls.js +++ b/src/pin/ls.js @@ -1,33 +1,27 @@ 'use strict' -const promisify = require('promisify-es6') +const configure = require('../lib/configure') -module.exports = (send) => { - return promisify((hash, opts, callback) => { - if (typeof hash === 'function') { - callback = hash - opts = null - hash = null +module.exports = configure(({ ky }) => { + return async (path, options) => { + if (path && path.type) { + options = path + path = null } - if (typeof opts === 'function') { - callback = opts - opts = null - } - if (hash && hash.type) { - opts = hash - hash = null - } - send({ - path: 'pin/ls', - args: hash, - qs: opts - }, (err, res) => { - if (err) { - return callback(err) - } - callback(null, Object.keys(res.Keys).map(hash => ( - { hash, type: res.Keys[hash].Type } - ))) - }) - }) -} + + options = options || {} + + const searchParams = new URLSearchParams(options.searchParams) + if (path) searchParams.set('arg', `${path}`) + if (options.type) searchParams.set('type', options.type) + + const { Keys } = await ky.get('pin/ls', { + timeout: options.timeout, + signal: options.signal, + headers: options.headers, + searchParams + }).json() + + return Object.keys(Keys).map(hash => ({ hash, type: Keys[hash].Type })) + } +}) diff --git a/src/pin/rm.js b/src/pin/rm.js index 05aada109..9f75307ff 100644 --- a/src/pin/rm.js +++ b/src/pin/rm.js @@ -1,22 +1,22 @@ 'use strict' -const promisify = require('promisify-es6') +const configure = require('../lib/configure') -module.exports = (send) => { - return promisify((hash, opts, callback) => { - if (typeof opts === 'function') { - callback = opts - opts = null - } - send({ - path: 'pin/rm', - args: hash, - qs: opts - }, (err, res) => { - if (err) { - return callback(err) - } - callback(null, res.Pins.map((hash) => ({ hash: hash }))) - }) - }) -} +module.exports = configure(({ ky }) => { + return async (path, options) => { + options = options || {} + + const searchParams = new URLSearchParams(options.searchParams) + searchParams.set('arg', `${path}`) + if (options.recursive != null) searchParams.set('recursive', options.recursive) + + const res = await ky.post('pin/rm', { + timeout: options.timeout, + signal: options.signal, + headers: options.headers, + searchParams + }).json() + + return (res.Pins || []).map(hash => ({ hash })) + } +}) diff --git a/src/utils/load-commands.js b/src/utils/load-commands.js index 3e51acdb2..933241a0b 100644 --- a/src/utils/load-commands.js +++ b/src/utils/load-commands.js @@ -113,7 +113,8 @@ function requireCommands (send, config) { config: require('../config')(config), dag: require('../dag')(config), dht: require('../dht')(config), - diag: require('../diag')(config) + diag: require('../diag')(config), + pin: require('../pin')(config) } Object.assign(cmds.refs, { @@ -129,7 +130,6 @@ function requireCommands (send, config) { // Graph object: require('../object'), - pin: require('../pin'), // Network name: require('../name'), From fc73da74496621abb264bc45f933333b2eda4a0f Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Wed, 20 Nov 2019 17:16:45 +0000 Subject: [PATCH 187/233] refactor: convert object.* and files.* API methods to async/await (#1160) License: MIT Signed-off-by: Alan Shaw --- package.json | 14 +--- src/files/cp.js | 37 +++++---- src/files/flush.js | 31 +++++--- src/files/index.js | 34 ++++---- src/files/ls-pull-stream.js | 12 --- src/files/ls-readable-stream.js | 62 --------------- src/files/ls.js | 65 ++++++++------- src/files/mkdir.js | 36 +++++---- src/files/mv.js | 37 +++++---- src/files/read-pull-stream.js | 26 ------ src/files/read-readable-stream.js | 26 ------ src/files/read.js | 38 +++++---- src/files/rm.js | 38 ++++----- src/files/stat.js | 55 ++++++------- src/{utils/find-sources.js => files/utils.js} | 14 ++-- src/files/write.js | 70 +++++++--------- src/lib/configure.js | 8 +- src/object/addLink.js | 35 -------- src/object/appendData.js | 35 -------- src/object/data.js | 63 +++++---------- src/object/get.js | 79 ++++++------------- src/object/index.js | 30 +++---- src/object/links.js | 63 ++++----------- src/object/new.js | 38 +++++---- src/object/patch/add-link.js | 25 ++++++ src/object/patch/append-data.js | 25 ++++++ src/object/patch/index.js | 10 +++ src/object/patch/rm-link.js | 24 ++++++ src/object/patch/set-data.js | 25 ++++++ src/object/put.js | 56 ++++++------- src/object/rmLink.js | 35 -------- src/object/setData.js | 34 -------- src/object/stat.js | 41 +++++----- src/utils/load-commands.js | 8 +- test/files-mfs.spec.js | 4 +- 35 files changed, 495 insertions(+), 738 deletions(-) delete mode 100644 src/files/ls-pull-stream.js delete mode 100644 src/files/ls-readable-stream.js delete mode 100644 src/files/read-pull-stream.js delete mode 100644 src/files/read-readable-stream.js rename src/{utils/find-sources.js => files/utils.js} (50%) delete mode 100644 src/object/addLink.js delete mode 100644 src/object/appendData.js create mode 100644 src/object/patch/add-link.js create mode 100644 src/object/patch/append-data.js create mode 100644 src/object/patch/index.js create mode 100644 src/object/patch/rm-link.js create mode 100644 src/object/patch/set-data.js delete mode 100644 src/object/rmLink.js delete mode 100644 src/object/setData.js diff --git a/package.json b/package.json index bfc80c569..4b305550a 100644 --- a/package.json +++ b/package.json @@ -53,14 +53,11 @@ "cids": "~0.7.1", "concat-stream": "github:hugomrdias/concat-stream#feat/smaller", "debug": "^4.1.0", - "delay": "^4.3.0", "detect-node": "^2.0.4", - "end-of-stream": "^1.4.1", "err-code": "^2.0.0", "explain-error": "^1.0.4", "flatmap": "0.0.3", "form-data": "^3.0.0", - "fs-extra": "^8.1.0", "glob": "^7.1.3", "ipfs-block": "~0.8.1", "ipfs-utils": "^0.4.0", @@ -71,17 +68,13 @@ "is-pull-stream": "0.0.0", "is-stream": "^2.0.0", "iso-stream-http": "~0.1.2", - "iso-url": "~0.4.6", "it-glob": "0.0.6", "it-tar": "^1.1.0", "it-to-stream": "^0.1.1", "iterable-ndjson": "^1.1.0", - "just-kebab-case": "^1.1.0", - "just-map-keys": "^1.1.0", "kind-of": "^6.0.2", "ky": "^0.15.0", "ky-universal": "^0.3.0", - "lru-cache": "^5.1.1", "merge-options": "^2.0.0", "multiaddr": "^6.0.6", "multibase": "~0.6.0", @@ -89,26 +82,25 @@ "multihashes": "~0.4.14", "ndjson": "github:hugomrdias/ndjson#feat/readable-stream3", "once": "^1.4.0", + "parse-duration": "^0.1.1", "peer-id": "~0.12.3", "peer-info": "~0.15.1", "promise-nodeify": "^3.0.1", "promisify-es6": "^1.0.3", "pull-defer": "~0.2.3", "pull-stream": "^3.6.9", - "pull-stream-to-async-iterator": "^1.0.2", "pull-to-stream": "~0.1.1", "pump": "^3.0.0", "qs": "^6.5.2", "readable-stream": "^3.1.1", - "stream-to-pull-stream": "^1.7.2", - "through2": "^3.0.1" + "stream-to-pull-stream": "^1.7.2" }, "devDependencies": { "aegir": "^20.4.1", "browser-process-platform": "~0.1.1", "cross-env": "^6.0.0", "go-ipfs-dep": "^0.4.22", - "interface-ipfs-core": "^0.119.0", + "interface-ipfs-core": "^0.120.0", "ipfsd-ctl": "^0.47.1", "nock": "^11.4.0", "stream-equal": "^1.1.1" diff --git a/src/files/cp.js b/src/files/cp.js index de4e0954d..812c8b7d7 100644 --- a/src/files/cp.js +++ b/src/files/cp.js @@ -1,20 +1,25 @@ 'use strict' -const promisify = require('promisify-es6') -const findSources = require('../utils/find-sources') +const CID = require('cids') +const configure = require('../lib/configure') +const { findSources } = require('./utils') -module.exports = (send) => { - return promisify(function () { - const { - callback, - sources, - opts - } = findSources(Array.prototype.slice.call(arguments)) +module.exports = configure(({ ky }) => { + return (...args) => { + const { sources, options } = findSources(args) - send({ - path: 'files/cp', - args: sources, - qs: opts - }, (error) => callback(error)) - }) -} + const searchParams = new URLSearchParams(options.searchParams) + sources.forEach(src => searchParams.append('arg', CID.isCID(src) ? `/ipfs/${src}` : src)) + if (options.format) searchParams.set('format', options.format) + if (options.flush != null) searchParams.set('flush', options.flush) + if (options.hashAlg) searchParams.set('hash', options.hashAlg) + if (options.parents != null) searchParams.set('parents', options.parents) + + return ky.post('files/cp', { + timeout: options.timeout, + signal: options.signal, + headers: options.headers, + searchParams + }).text() + } +}) diff --git a/src/files/flush.js b/src/files/flush.js index 6a131989b..ab2062387 100644 --- a/src/files/flush.js +++ b/src/files/flush.js @@ -1,17 +1,24 @@ 'use strict' -const promisify = require('promisify-es6') +const configure = require('../lib/configure') -module.exports = (send) => { - return promisify((args, callback) => { - if (typeof args === 'function') { - callback = args - args = '/' +module.exports = configure(({ ky }) => { + return async (path, options) => { + if (typeof path !== 'string') { + options = path + path = '/' } - return send({ - path: 'files/flush', - args: args - }, (error) => callback(error)) - }) -} + options = options || {} + + const searchParams = new URLSearchParams(options.searchParams) + searchParams.set('arg', path) + + await ky.post('files/flush', { + timeout: options.timeout, + signal: options.signal, + headers: options.headers, + searchParams + }).text() + } +}) diff --git a/src/files/index.js b/src/files/index.js index d35e82ea7..25e79fcab 100644 --- a/src/files/index.js +++ b/src/files/index.js @@ -1,23 +1,25 @@ 'use strict' -const moduleConfig = require('../utils/module-config') +const callbackify = require('callbackify') +const { collectify, streamify, pullify, concatify } = require('../lib/converters') -module.exports = (arg) => { - const send = moduleConfig(arg) +module.exports = config => { + const ls = require('./ls')(config) + const read = require('./read')(config) return { - cp: require('./cp')(send), - mkdir: require('./mkdir')(send), - flush: require('./flush')(send), - stat: require('./stat')(send), - rm: require('./rm')(send), - ls: require('./ls')(send), - lsReadableStream: require('./ls-readable-stream')(send), - lsPullStream: require('./ls-pull-stream')(send), - read: require('./read')(send), - readReadableStream: require('./read-readable-stream')(send), - readPullStream: require('./read-pull-stream')(send), - write: require('./write')(send), - mv: require('./mv')(send) + cp: callbackify.variadic(require('./cp')(config)), + mkdir: callbackify.variadic(require('./mkdir')(config)), + flush: callbackify.variadic(require('./flush')(config)), + stat: callbackify.variadic(require('./stat')(config)), + rm: callbackify.variadic(require('./rm')(config)), + ls: callbackify.variadic(collectify(ls)), + lsReadableStream: streamify.readable(ls), + lsPullStream: pullify.source(ls), + read: callbackify.variadic(concatify(read)), + readReadableStream: streamify.readable(read), + readPullStream: pullify.source(read), + write: callbackify.variadic(require('./write')(config)), + mv: callbackify.variadic(require('./mv')(config)) } } diff --git a/src/files/ls-pull-stream.js b/src/files/ls-pull-stream.js deleted file mode 100644 index 111eba7ed..000000000 --- a/src/files/ls-pull-stream.js +++ /dev/null @@ -1,12 +0,0 @@ -'use strict' - -const toPull = require('stream-to-pull-stream') -const lsReadableStream = require('./ls-readable-stream') - -module.exports = (send) => { - return (args, opts) => { - opts = opts || {} - - return toPull.source(lsReadableStream(send)(args, opts)) - } -} diff --git a/src/files/ls-readable-stream.js b/src/files/ls-readable-stream.js deleted file mode 100644 index 404893e70..000000000 --- a/src/files/ls-readable-stream.js +++ /dev/null @@ -1,62 +0,0 @@ -'use strict' - -const { - Transform, - PassThrough -} = require('readable-stream') -const pump = require('pump') -const ndjson = require('ndjson') -const isStream = require('is-stream') - -const toEntry = (entry) => { - return { - name: entry.Name, - type: entry.Type, - size: entry.Size, - hash: entry.Hash - } -} - -module.exports = (send) => { - return (args, opts) => { - opts = opts || {} - - const transform = new Transform({ - objectMode: true, - - transform (entry, encoding, callback) { - callback(null, toEntry(entry)) - } - }) - - const output = new PassThrough({ - objectMode: true - }) - - send({ - path: 'files/ls', - args: args, - qs: Object.assign({}, opts, { stream: true }) - }, (err, res) => { - if (err) { - return output.destroy(err) - } - - if (isStream(res)) { - const parse = ndjson.parse() - - pump(res, parse, transform, output) - } else { - const entries = res.Entries || [] - - entries.forEach((entry) => { - output.write(toEntry(entry)) - }) - - output.end() - } - }) - - return output - } -} diff --git a/src/files/ls.js b/src/files/ls.js index ff22f5396..1baa3f656 100644 --- a/src/files/ls.js +++ b/src/files/ls.js @@ -1,37 +1,42 @@ 'use strict' -const promisify = require('promisify-es6') +const CID = require('cids') +const ndjson = require('iterable-ndjson') +const toIterable = require('../lib/stream-to-iterable') +const configure = require('../lib/configure') +const toCamel = require('../lib/object-to-camel') -const transform = function (res, callback) { - const entries = res.Entries || [] - - callback(null, entries.map((entry) => { - return { - name: entry.Name, - type: entry.Type, - size: entry.Size, - hash: entry.Hash +module.exports = configure(({ ky }) => { + return async function * ls (path, options) { + if (typeof path !== 'string') { + options = path + path = '/' } - })) -} -module.exports = (send) => { - return promisify((args, opts, callback) => { - if (typeof (opts) === 'function') { - callback = opts - opts = {} - } + options = options || {} - if (typeof (args) === 'function') { - callback = args - opts = {} - args = null - } + const searchParams = new URLSearchParams(options.searchParams) + searchParams.set('arg', CID.isCID(path) ? `/ipfs/${path}` : path) + searchParams.set('stream', true) + if (options.cidBase) searchParams.set('cid-base', options.cidBase) + if (options.long != null) searchParams.set('long', options.long) - return send.andTransform({ - path: 'files/ls', - args: args, - qs: opts - }, transform, callback) - }) -} + const res = await ky.post('files/ls', { + timeout: options.timeout, + signal: options.signal, + headers: options.headers, + searchParams + }) + + for await (const result of ndjson(toIterable(res.body))) { + // go-ipfs does not yet support the "stream" option + if ('Entries' in result) { + for (const entry of result.Entries || []) { + yield toCamel(entry) + } + return + } + yield toCamel(result) + } + } +}) diff --git a/src/files/mkdir.js b/src/files/mkdir.js index b77fbf6dd..0fc3c238d 100644 --- a/src/files/mkdir.js +++ b/src/files/mkdir.js @@ -1,18 +1,24 @@ - 'use strict' -const promisify = require('promisify-es6') +const configure = require('../lib/configure') + +module.exports = configure(({ ky }) => { + return (path, options) => { + options = options || {} + + const searchParams = new URLSearchParams(options.searchParams) + searchParams.append('arg', path) + if (options.cidVersion != null) searchParams.set('cid-version', options.cidVersion) + if (options.format) searchParams.set('format', options.format) + if (options.flush != null) searchParams.set('flush', options.flush) + if (options.hashAlg) searchParams.set('hash', options.hashAlg) + if (options.parents != null) searchParams.set('parents', options.parents) -module.exports = (send) => { - return promisify((args, opts, callback) => { - if (typeof (opts) === 'function') { - callback = opts - opts = {} - } - send({ - path: 'files/mkdir', - args: args, - qs: opts - }, (error) => callback(error)) - }) -} + return ky.post('files/mkdir', { + timeout: options.timeout, + signal: options.signal, + headers: options.headers, + searchParams + }).text() + } +}) diff --git a/src/files/mv.js b/src/files/mv.js index 234491b28..fadf0c34c 100644 --- a/src/files/mv.js +++ b/src/files/mv.js @@ -1,20 +1,25 @@ 'use strict' -const promisify = require('promisify-es6') -const findSources = require('../utils/find-sources') +const CID = require('cids') +const configure = require('../lib/configure') +const { findSources } = require('./utils') -module.exports = (send) => { - return promisify(function () { - const { - callback, - sources, - opts - } = findSources(Array.prototype.slice.call(arguments)) +module.exports = configure(({ ky }) => { + return (...args) => { + const { sources, options } = findSources(args) - send({ - path: 'files/mv', - args: sources, - qs: opts - }, (error) => callback(error)) - }) -} + const searchParams = new URLSearchParams(options.searchParams) + sources.forEach(src => searchParams.append('arg', CID.isCID(src) ? `/ipfs/${src}` : src)) + if (options.format) searchParams.set('format', options.format) + if (options.flush != null) searchParams.set('flush', options.flush) + if (options.hashAlg) searchParams.set('hash', options.hashAlg) + if (options.parents != null) searchParams.set('parents', options.parents) + + return ky.post('files/mv', { + timeout: options.timeout, + signal: options.signal, + headers: options.headers, + searchParams + }).text() + } +}) diff --git a/src/files/read-pull-stream.js b/src/files/read-pull-stream.js deleted file mode 100644 index 3e9ab8c3d..000000000 --- a/src/files/read-pull-stream.js +++ /dev/null @@ -1,26 +0,0 @@ -'use strict' - -const toPull = require('stream-to-pull-stream') -const deferred = require('pull-defer') - -module.exports = (send) => { - return (args, opts) => { - opts = opts || {} - - const p = deferred.source() - - send({ - path: 'files/read', - args: args, - qs: opts - }, (err, stream) => { - if (err) { - return p.abort(err) - } - - p.resolve(toPull(stream)) - }) - - return p - } -} diff --git a/src/files/read-readable-stream.js b/src/files/read-readable-stream.js deleted file mode 100644 index df8b92fbf..000000000 --- a/src/files/read-readable-stream.js +++ /dev/null @@ -1,26 +0,0 @@ -'use strict' - -const Stream = require('readable-stream') -const pump = require('pump') - -module.exports = (send) => { - return (args, opts) => { - opts = opts || {} - - const pt = new Stream.PassThrough() - - send({ - path: 'files/read', - args: args, - qs: opts - }, (err, stream) => { - if (err) { - return pt.destroy(err) - } - - pump(stream, pt) - }) - - return pt - } -} diff --git a/src/files/read.js b/src/files/read.js index 378d53dfa..5a6a14acb 100644 --- a/src/files/read.js +++ b/src/files/read.js @@ -1,19 +1,27 @@ 'use strict' -const promisify = require('promisify-es6') -const streamToValue = require('../utils/stream-to-value') +const { Buffer } = require('buffer') +const configure = require('../lib/configure') +const toIterable = require('../lib/stream-to-iterable') -module.exports = (send) => { - return promisify((args, opts, callback) => { - if (typeof (opts) === 'function') { - callback = opts - opts = {} - } +module.exports = configure(({ ky }) => { + return async function * read (path, options) { + options = options || {} + + const searchParams = new URLSearchParams(options.searchParams) + searchParams.append('arg', `${path}`) + if (options.length != null) searchParams.set('length', options.length) + if (options.offset != null) searchParams.set('offset', options.offset) - send.andTransform({ - path: 'files/read', - args: args, - qs: opts - }, streamToValue, callback) - }) -} + const res = await ky.post('files/read', { + timeout: options.timeout, + signal: options.signal, + headers: options.headers, + searchParams + }) + + for await (const chunk of toIterable(res.body)) { + yield Buffer.from(chunk) + } + } +}) diff --git a/src/files/rm.js b/src/files/rm.js index 404ceed10..c0a5e7eab 100644 --- a/src/files/rm.js +++ b/src/files/rm.js @@ -1,27 +1,21 @@ 'use strict' -const promisify = require('promisify-es6') +const configure = require('../lib/configure') -module.exports = (send) => { - return promisify((path, opts, callback) => { - if (typeof opts === 'function' && - !callback) { - callback = opts - opts = {} - } +module.exports = configure(({ ky }) => { + return (path, options) => { + options = options || {} - // opts is the real callback -- - // 'callback' is being injected by promisify - if (typeof opts === 'function' && - typeof callback === 'function') { - callback = opts - opts = {} - } + const searchParams = new URLSearchParams(options.searchParams) + searchParams.append('arg', path) + if (options.recursive != null) searchParams.set('recursive', options.recursive) + if (options.force != null) searchParams.set('force', options.force) - send({ - path: 'files/rm', - args: path, - qs: opts - }, (error) => callback(error)) - }) -} + return ky.post('files/rm', { + timeout: options.timeout, + signal: options.signal, + headers: options.headers, + searchParams + }).text() + } +}) diff --git a/src/files/stat.js b/src/files/stat.js index 7274e32a1..98026283e 100644 --- a/src/files/stat.js +++ b/src/files/stat.js @@ -1,35 +1,32 @@ 'use strict' -const promisify = require('promisify-es6') -const mapKeys = require('just-map-keys') -const kebabCase = require('just-kebab-case') +const configure = require('../lib/configure') +const toCamel = require('../lib/object-to-camel') -const transform = function (data, callback) { - callback(null, { - type: data.Type, - blocks: data.Blocks, - size: data.Size, - hash: data.Hash, - cumulativeSize: data.CumulativeSize, - withLocality: data.WithLocality || false, - local: data.Local || undefined, - sizeLocal: data.SizeLocal || undefined - }) -} - -module.exports = (send) => { - return promisify((args, opts, callback) => { - if (typeof (opts) === 'function') { - callback = opts - opts = {} +module.exports = configure(({ ky }) => { + return async (path, options) => { + if (typeof path !== 'string') { + options = path + path = '/' } - opts = mapKeys(opts, (v, k) => kebabCase(k)) + options = options || {} + + const searchParams = new URLSearchParams(options.searchParams) + searchParams.set('arg', path) + if (options.cidBase) searchParams.set('cid-base', options.cidBase) + if (options.hash != null) searchParams.set('hash', options.hash) + if (options.size != null) searchParams.set('size', options.size) + if (options.withLocal != null) searchParams.set('with-local', options.withLocal) + + const res = await ky.post('files/stat', { + timeout: options.timeout, + signal: options.signal, + headers: options.headers, + searchParams + }).json() - send.andTransform({ - path: 'files/stat', - args: args, - qs: opts - }, transform, callback) - }) -} + res.WithLocality = res.WithLocality || false + return toCamel(res) + } +}) diff --git a/src/utils/find-sources.js b/src/files/utils.js similarity index 50% rename from src/utils/find-sources.js rename to src/files/utils.js index 2a862514a..6dc2c499d 100644 --- a/src/utils/find-sources.js +++ b/src/files/utils.js @@ -1,25 +1,23 @@ 'use strict' -module.exports = (args) => { - const callback = args.pop() - let opts = {} +exports.findSources = (args) => { + let options = {} let sources = [] if (!Array.isArray(args[args.length - 1]) && typeof args[args.length - 1] === 'object') { - opts = args.pop() + options = args.pop() } if (args.length === 1 && Array.isArray(args[0])) { - // support ipfs.file.cp([src, dest], opts, cb) + // support ipfs.files.cp([src, dest], opts) sources = args[0] } else { - // support ipfs.file.cp(src, dest, opts, cb) and ipfs.file.cp(src1, src2, dest, opts, cb) + // support ipfs.files.cp(src, dest, opts) and ipfs.files.cp(src1, src2, dest, opts) sources = args } return { - callback, sources, - opts + options } } diff --git a/src/files/write.js b/src/files/write.js index 33f1ec973..77a772ea6 100644 --- a/src/files/write.js +++ b/src/files/write.js @@ -1,42 +1,32 @@ 'use strict' -const promisify = require('promisify-es6') -const concatStream = require('concat-stream') -const once = require('once') -const SendFilesStream = require('../utils/send-files-stream') - -module.exports = (send) => { - const sendFilesStream = SendFilesStream(send, 'files/write') - - return promisify((pathDst, _files, opts, _callback) => { - if (typeof opts === 'function' && - !_callback) { - _callback = opts - opts = {} - } - - // opts is the real callback -- - // 'callback' is being injected by promisify - if (typeof opts === 'function' && - typeof _callback === 'function') { - _callback = opts - opts = {} - } - - const files = [].concat(_files) - const callback = once(_callback) - - const options = { - args: pathDst, - qs: opts - } - - const stream = sendFilesStream({ qs: options }) - const concat = concatStream((result) => callback(null, result)) - stream.once('error', callback) - stream.pipe(concat) - - files.forEach((file) => stream.write(file)) - stream.end() - }) -} +const configure = require('../lib/configure') +const toFormData = require('../lib/buffer-to-form-data') + +module.exports = configure(({ ky }) => { + return async (path, input, options) => { + options = options || {} + + const searchParams = new URLSearchParams(options.searchParams) + searchParams.set('arg', path) + searchParams.set('stream-channels', true) + if (options.cidVersion) searchParams.set('cid-version', options.cidVersion) + if (options.create != null) searchParams.set('create', options.create) + if (options.hashAlg) searchParams.set('hash', options.hashAlg) + if (options.length != null) searchParams.set('length', options.length) + if (options.offset != null) searchParams.set('offset', options.offset) + if (options.parents != null) searchParams.set('parents', options.parents) + if (options.rawLeaves != null) searchParams.set('raw-leaves', options.rawLeaves) + if (options.truncate != null) searchParams.set('truncate', options.truncate) + + const res = await ky.post('files/write', { + timeout: options.timeout, + signal: options.signal, + headers: options.headers, + searchParams, + body: toFormData(input) // TODO: support inputs other than buffer as per spec + }) + + return res.text() + } +}) diff --git a/src/lib/configure.js b/src/lib/configure.js index 8401683f9..b1a1f8948 100644 --- a/src/lib/configure.js +++ b/src/lib/configure.js @@ -6,6 +6,7 @@ const { isBrowser, isWebWorker } = require('ipfs-utils/src/env') const { toUri } = require('./multiaddr') const errorHandler = require('./error-handler') const mergeOptions = require('merge-options').bind({ ignoreUndefined: true }) +const parseDuration = require('parse-duration') // Set default configuration and call create function with them module.exports = create => config => { @@ -27,7 +28,7 @@ module.exports = create => config => { // https://github.com/sindresorhus/ky/pull/153 const defaults = { prefixUrl: config.apiAddr + config.apiPath, - timeout: config.timeout || 60000 * 20, + timeout: parseTimeout(config.timeout) || 60000 * 20, headers: config.headers, hooks: { afterResponse: [errorHandler] @@ -72,6 +73,11 @@ function getDefaultApiAddr ({ protocol, host, port }) { // undefined values in the passed `options` object function wrap (fn, defaults) { return (input, options) => { + if (options.timeout) options.timeout = parseTimeout(options.timeout) return fn(input, mergeOptions(defaults, options)) } } + +function parseTimeout (value) { + return typeof value === 'string' ? parseDuration(value) : value +} diff --git a/src/object/addLink.js b/src/object/addLink.js deleted file mode 100644 index bda202bce..000000000 --- a/src/object/addLink.js +++ /dev/null @@ -1,35 +0,0 @@ -'use strict' - -const promisify = require('promisify-es6') -const CID = require('cids') - -module.exports = (send) => { - return promisify((cid, dLink, opts, callback) => { - if (typeof opts === 'function') { - callback = opts - opts = {} - } - if (!opts) { - opts = {} - } - - try { - cid = new CID(cid) - } catch (err) { - return callback(err) - } - - const args = [ - cid.toString(), - dLink.Name || dLink.name || null, - (dLink.Hash || dLink.cid || '').toString() || null - ] - - send({ path: 'object/patch/add-link', args }, (err, result) => { - if (err) { - return callback(err) - } - callback(null, new CID(result.Hash)) - }) - }) -} diff --git a/src/object/appendData.js b/src/object/appendData.js deleted file mode 100644 index 6c6cdb722..000000000 --- a/src/object/appendData.js +++ /dev/null @@ -1,35 +0,0 @@ -'use strict' - -const promisify = require('promisify-es6') -const once = require('once') -const CID = require('cids') -const SendOneFile = require('../utils/send-one-file') - -module.exports = (send) => { - const sendOneFile = SendOneFile(send, 'object/patch/append-data') - - return promisify((cid, data, opts, _callback) => { - if (typeof opts === 'function') { - _callback = opts - opts = {} - } - const callback = once(_callback) - if (!opts) { - opts = {} - } - - try { - cid = new CID(cid) - } catch (err) { - return callback(err) - } - - sendOneFile(data, { args: [cid.toString()] }, (err, result) => { - if (err) { - return callback(err) - } - - callback(null, new CID(result.Hash)) - }) - }) -} diff --git a/src/object/data.js b/src/object/data.js index bbc43ebd6..8f1e42b7a 100644 --- a/src/object/data.js +++ b/src/object/data.js @@ -1,53 +1,26 @@ 'use strict' -const promisify = require('promisify-es6') -const streamToValue = require('../utils/stream-to-value') +const { Buffer } = require('buffer') const CID = require('cids') -const LRU = require('lru-cache') -const lruOptions = { - max: 128 -} +const configure = require('../lib/configure') +const toIterable = require('../lib/stream-to-iterable') -const cache = new LRU(lruOptions) +module.exports = configure(({ ky }) => { + return async function * (cid, options) { + options = options || {} -module.exports = (send) => { - return promisify((cid, options, callback) => { - if (typeof options === 'function') { - callback = options - options = {} - } - if (!options) { - options = {} - } - - let cidB58Str - - try { - cid = new CID(cid) - cidB58Str = cid.toBaseEncodedString() - } catch (err) { - return callback(err) - } + const searchParams = new URLSearchParams(options.searchParams) + searchParams.set('arg', `${Buffer.isBuffer(cid) ? new CID(cid) : cid}`) - const node = cache.get(cidB58Str) + const res = await ky.get('object/data', { + timeout: options.timeout, + signal: options.signal, + headers: options.headers, + searchParams + }) - if (node) { - return callback(null, node.data) + for await (const chunk of toIterable(res.body)) { + yield Buffer.from(chunk) } - - send({ - path: 'object/data', - args: cidB58Str - }, (err, result) => { - if (err) { - return callback(err) - } - - if (typeof result.pipe === 'function') { - streamToValue(result, callback) - } else { - callback(null, result) - } - }) - }) -} + } +}) diff --git a/src/object/get.js b/src/object/get.js index 5052c8af3..5ed7468dc 100644 --- a/src/object/get.js +++ b/src/object/get.js @@ -1,57 +1,28 @@ 'use strict' -const promisify = require('promisify-es6') -const { DAGNode, DAGLink } = require('ipld-dag-pb') +const { Buffer } = require('buffer') const CID = require('cids') -const LRU = require('lru-cache') -const lruOptions = { - max: 128 -} - -const cache = new LRU(lruOptions) - -module.exports = (send) => { - return promisify((cid, options, callback) => { - if (typeof options === 'function') { - callback = options - options = {} - } - - if (!options) { - options = {} - } - - let cidB58Str - - try { - cid = new CID(cid) - cidB58Str = cid.toBaseEncodedString() - } catch (err) { - return callback(err) - } - - const node = cache.get(cidB58Str) - - if (node) { - return callback(null, node) - } - - send({ - path: 'object/get', - args: cidB58Str, - qs: { - 'data-encoding': 'base64' - } - }, (err, result) => { - if (err) { - return callback(err) - } - - const links = result.Links.map(l => new DAGLink(l.Name, l.Size, l.Hash)) - const node = new DAGNode(Buffer.from(result.Data, 'base64'), links) - - cache.set(cidB58Str, node) - callback(null, node) - }) - }) -} +const { DAGNode, DAGLink } = require('ipld-dag-pb') +const configure = require('../lib/configure') + +module.exports = configure(({ ky }) => { + return async (cid, options) => { + options = options || {} + + const searchParams = new URLSearchParams(options.searchParams) + searchParams.set('arg', `${Buffer.isBuffer(cid) ? new CID(cid) : cid}`) + searchParams.set('data-encoding', 'base64') + + const res = await ky.get('object/get', { + timeout: options.timeout, + signal: options.signal, + headers: options.headers, + searchParams + }).json() + + return new DAGNode( + Buffer.from(res.Data, 'base64'), + (res.Links || []).map(l => new DAGLink(l.Name, l.Size, l.Hash)) + ) + } +}) diff --git a/src/object/index.js b/src/object/index.js index 2966232c4..dac85598c 100644 --- a/src/object/index.js +++ b/src/object/index.js @@ -1,22 +1,14 @@ 'use strict' -const moduleConfig = require('../utils/module-config') +const callbackify = require('callbackify') +const { concatify } = require('../lib/converters') -module.exports = (arg) => { - const send = moduleConfig(arg) - - return { - get: require('./get')(send), - put: require('./put')(send), - data: require('./data')(send), - links: require('./links')(send), - stat: require('./stat')(send), - new: require('./new')(send), - patch: { - addLink: require('./addLink')(send), - rmLink: require('./rmLink')(send), - setData: require('./setData')(send), - appendData: require('./appendData')(send) - } - } -} +module.exports = config => ({ + data: callbackify.variadic(concatify(require('./data')(config))), + get: callbackify.variadic(require('./get')(config)), + links: callbackify.variadic(require('./links')(config)), + new: callbackify.variadic(require('./new')(config)), + patch: require('./patch')(config), + put: callbackify.variadic(require('./put')(config)), + stat: callbackify.variadic(require('./stat')(config)) +}) diff --git a/src/object/links.js b/src/object/links.js index 0b0366c81..49b088254 100644 --- a/src/object/links.js +++ b/src/object/links.js @@ -1,53 +1,24 @@ 'use strict' -const promisify = require('promisify-es6') -const { DAGLink } = require('ipld-dag-pb') +const { Buffer } = require('buffer') const CID = require('cids') -const LRU = require('lru-cache') -const lruOptions = { - max: 128 -} - -const cache = new LRU(lruOptions) - -module.exports = (send) => { - return promisify((cid, options, callback) => { - if (typeof options === 'function') { - callback = options - options = {} - } - if (!options) { - options = {} - } - - try { - cid = new CID(cid) - } catch (err) { - return callback(err) - } - - const node = cache.get(cid.toString()) +const { DAGLink } = require('ipld-dag-pb') +const configure = require('../lib/configure') - if (node) { - return callback(null, node.links) - } +module.exports = configure(({ ky }) => { + return async (cid, options) => { + options = options || {} - send({ - path: 'object/links', - args: cid.toString() - }, (err, result) => { - if (err) { - return callback(err) - } + const searchParams = new URLSearchParams(options.searchParams) + searchParams.set('arg', `${Buffer.isBuffer(cid) ? new CID(cid) : cid}`) - let links = [] + const res = await ky.get('object/links', { + timeout: options.timeout, + signal: options.signal, + headers: options.headers, + searchParams + }).json() - if (result.Links) { - links = result.Links.map((l) => { - return new DAGLink(l.Name, l.Size, l.Hash) - }) - } - callback(null, links) - }) - }) -} + return (res.Links || []).map(l => new DAGLink(l.Name, l.Size, l.Hash)) + } +}) diff --git a/src/object/new.js b/src/object/new.js index f9d8ddb35..d372812a5 100644 --- a/src/object/new.js +++ b/src/object/new.js @@ -1,23 +1,27 @@ 'use strict' -const promisify = require('promisify-es6') const CID = require('cids') +const configure = require('../lib/configure') -module.exports = (send) => { - return promisify((template, callback) => { - if (typeof template === 'function') { - callback = template - template = undefined +module.exports = configure(({ ky }) => { + return async (template, options) => { + if (typeof template !== 'string') { + options = template + template = null } - send({ - path: 'object/new', - args: template - }, (err, result) => { - if (err) { - return callback(err) - } - callback(null, new CID(result.Hash)) - }) - }) -} + options = options || {} + + const searchParams = new URLSearchParams(options.searchParams) + if (template) searchParams.set('arg', template) + + const { Hash } = await ky.post('object/new', { + timeout: options.timeout, + signal: options.signal, + headers: options.headers, + searchParams + }).json() + + return new CID(Hash) + } +}) diff --git a/src/object/patch/add-link.js b/src/object/patch/add-link.js new file mode 100644 index 000000000..55821751d --- /dev/null +++ b/src/object/patch/add-link.js @@ -0,0 +1,25 @@ +'use strict' + +const { Buffer } = require('buffer') +const CID = require('cids') +const configure = require('../../lib/configure') + +module.exports = configure(({ ky }) => { + return async (cid, dLink, options) => { + options = options || {} + + const searchParams = new URLSearchParams(options.searchParams) + searchParams.set('arg', `${Buffer.isBuffer(cid) ? new CID(cid) : cid}`) + searchParams.append('arg', dLink.Name || dLink.name || null) + searchParams.append('arg', (dLink.Hash || dLink.cid || '').toString() || null) + + const { Hash } = await ky.post('object/patch/add-link', { + timeout: options.timeout, + signal: options.signal, + headers: options.headers, + searchParams + }).json() + + return new CID(Hash) + } +}) diff --git a/src/object/patch/append-data.js b/src/object/patch/append-data.js new file mode 100644 index 000000000..1ab8d1381 --- /dev/null +++ b/src/object/patch/append-data.js @@ -0,0 +1,25 @@ +'use strict' + +const { Buffer } = require('buffer') +const CID = require('cids') +const configure = require('../../lib/configure') +const toFormData = require('../../lib/buffer-to-form-data') + +module.exports = configure(({ ky }) => { + return async (cid, data, options) => { + options = options || {} + + const searchParams = new URLSearchParams(options.searchParams) + searchParams.set('arg', `${Buffer.isBuffer(cid) ? new CID(cid) : cid}`) + + const { Hash } = await ky.post('object/patch/append-data', { + timeout: options.timeout, + signal: options.signal, + headers: options.headers, + searchParams, + body: toFormData(data) + }).json() + + return new CID(Hash) + } +}) diff --git a/src/object/patch/index.js b/src/object/patch/index.js new file mode 100644 index 000000000..5711200ec --- /dev/null +++ b/src/object/patch/index.js @@ -0,0 +1,10 @@ +'use strict' + +const callbackify = require('callbackify') + +module.exports = config => ({ + addLink: callbackify.variadic(require('./add-link')(config)), + appendData: callbackify.variadic(require('./append-data')(config)), + rmLink: callbackify.variadic(require('./rm-link')(config)), + setData: callbackify.variadic(require('./set-data')(config)) +}) diff --git a/src/object/patch/rm-link.js b/src/object/patch/rm-link.js new file mode 100644 index 000000000..39ea0ea3b --- /dev/null +++ b/src/object/patch/rm-link.js @@ -0,0 +1,24 @@ +'use strict' + +const { Buffer } = require('buffer') +const CID = require('cids') +const configure = require('../../lib/configure') + +module.exports = configure(({ ky }) => { + return async (cid, dLink, options) => { + options = options || {} + + const searchParams = new URLSearchParams(options.searchParams) + searchParams.set('arg', `${Buffer.isBuffer(cid) ? new CID(cid) : cid}`) + searchParams.append('arg', dLink.Name || dLink.name || null) + + const { Hash } = await ky.post('object/patch/rm-link', { + timeout: options.timeout, + signal: options.signal, + headers: options.headers, + searchParams + }).json() + + return new CID(Hash) + } +}) diff --git a/src/object/patch/set-data.js b/src/object/patch/set-data.js new file mode 100644 index 000000000..7bb131fb7 --- /dev/null +++ b/src/object/patch/set-data.js @@ -0,0 +1,25 @@ +'use strict' + +const { Buffer } = require('buffer') +const CID = require('cids') +const configure = require('../../lib/configure') +const toFormData = require('../../lib/buffer-to-form-data') + +module.exports = configure(({ ky }) => { + return async (cid, data, options) => { + options = options || {} + + const searchParams = new URLSearchParams(options.searchParams) + searchParams.set('arg', `${Buffer.isBuffer(cid) ? new CID(cid) : cid}`) + + const { Hash } = await ky.post('object/patch/set-data', { + timeout: options.timeout, + signal: options.signal, + headers: options.headers, + searchParams, + body: toFormData(data) + }).json() + + return new CID(Hash) + } +}) diff --git a/src/object/put.js b/src/object/put.js index 40b9ffac4..be8660a00 100644 --- a/src/object/put.js +++ b/src/object/put.js @@ -1,26 +1,14 @@ 'use strict' -const promisify = require('promisify-es6') const CID = require('cids') const { DAGNode } = require('ipld-dag-pb') +const { Buffer } = require('buffer') +const configure = require('../lib/configure') +const toFormData = require('../lib/buffer-to-form-data') -const SendOneFile = require('../utils/send-one-file') -const once = require('once') - -module.exports = (send) => { - const sendOneFile = SendOneFile(send, 'object/put') - - return promisify((obj, options, _callback) => { - if (typeof options === 'function') { - _callback = options - options = {} - } - - const callback = once(_callback) - - if (!options) { - options = {} - } +module.exports = configure(({ ky }) => { + return async (obj, options) => { + options = options || {} let tmpObj = { Data: null, @@ -47,7 +35,7 @@ module.exports = (send) => { tmpObj.Data = obj.Data.toString() tmpObj.Links = obj.Links } else { - return callback(new Error('obj not recognized')) + throw new Error('obj not recognized') } let buf @@ -56,18 +44,20 @@ module.exports = (send) => { } else { buf = Buffer.from(JSON.stringify(tmpObj)) } - const enc = options.enc || 'json' - - const sendOptions = { - qs: { inputenc: enc } - } - - sendOneFile(buf, sendOptions, (err, result) => { - if (err) { - return callback(err) // early - } - callback(null, new CID(result.Hash)) - }) - }) -} + const searchParams = new URLSearchParams(options.searchParams) + if (options.enc) searchParams.set('inputenc', options.enc) + if (options.pin != null) searchParams.set('pin', options.pin) + if (options.quiet != null) searchParams.set('quiet', options.quiet) + + const { Hash } = await ky.post('object/put', { + timeout: options.timeout, + signal: options.signal, + headers: options.headers, + searchParams, + body: toFormData(buf) + }).json() + + return new CID(Hash) + } +}) diff --git a/src/object/rmLink.js b/src/object/rmLink.js deleted file mode 100644 index db699feeb..000000000 --- a/src/object/rmLink.js +++ /dev/null @@ -1,35 +0,0 @@ -'use strict' - -const promisify = require('promisify-es6') -const CID = require('cids') - -module.exports = (send) => { - return promisify((cid, dLink, opts, callback) => { - if (typeof opts === 'function') { - callback = opts - opts = {} - } - if (!opts) { - opts = {} - } - - try { - cid = new CID(cid) - } catch (err) { - return callback(err) - } - - send({ - path: 'object/patch/rm-link', - args: [ - cid.toString(), - dLink.Name || dLink.name || null - ] - }, (err, result) => { - if (err) { - return callback(err) - } - callback(null, new CID(result.Hash)) - }) - }) -} diff --git a/src/object/setData.js b/src/object/setData.js deleted file mode 100644 index 5eb014474..000000000 --- a/src/object/setData.js +++ /dev/null @@ -1,34 +0,0 @@ -'use strict' - -const promisify = require('promisify-es6') -const once = require('once') -const CID = require('cids') -const SendOneFile = require('../utils/send-one-file') - -module.exports = (send) => { - const sendOneFile = SendOneFile(send, 'object/patch/set-data') - - return promisify((cid, data, opts, _callback) => { - if (typeof opts === 'function') { - _callback = opts - opts = {} - } - const callback = once(_callback) - if (!opts) { - opts = {} - } - - try { - cid = new CID(cid) - } catch (err) { - return callback(err) - } - - sendOneFile(data, { args: [cid.toString()] }, (err, result) => { - if (err) { - return callback(err) - } - callback(null, new CID(result.Hash)) - }) - }) -} diff --git a/src/object/stat.js b/src/object/stat.js index 6488a297e..c3d2d8edc 100644 --- a/src/object/stat.js +++ b/src/object/stat.js @@ -1,28 +1,31 @@ 'use strict' -const promisify = require('promisify-es6') +const { Buffer } = require('buffer') const CID = require('cids') +const configure = require('../lib/configure') -module.exports = (send) => { - return promisify((cid, opts, callback) => { - if (typeof opts === 'function') { - callback = opts - opts = {} - } - if (!opts) { - opts = {} - } +module.exports = configure(({ ky }) => { + return async (cid, options) => { + options = options || {} + + const searchParams = new URLSearchParams(options.searchParams) + searchParams.set('arg', `${Buffer.isBuffer(cid) ? new CID(cid) : cid}`) + let res try { - cid = new CID(cid) + res = await ky.post('object/stat', { + timeout: options.timeout, + signal: options.signal, + headers: options.headers, + searchParams + }).json() } catch (err) { - return callback(err) + if (err.name === 'TimeoutError') { + err.message = `failed to get block for ${Buffer.isBuffer(cid) ? new CID(cid) : cid}: context deadline exceeded` + } + throw err } - send({ - path: 'object/stat', - args: cid.toString(), - qs: opts - }, callback) - }) -} + return res + } +}) diff --git a/src/utils/load-commands.js b/src/utils/load-commands.js index 933241a0b..a4a6dcd07 100644 --- a/src/utils/load-commands.js +++ b/src/utils/load-commands.js @@ -102,6 +102,7 @@ function requireCommands (send, config) { lsReadableStream: streamify.readable(ls), lsPullStream: pullify.source(ls), _lsAsyncIterator: ls, + object: require('../object')(config), refs: callbackify.variadic((path, options) => collectify(refs)(path, options)), refsReadableStream: streamify.readable(refs), refsPullStream: pullify.source(refs), @@ -114,6 +115,7 @@ function requireCommands (send, config) { dag: require('../dag')(config), dht: require('../dht')(config), diag: require('../diag')(config), + files: require('../files')(config), pin: require('../pin')(config) } @@ -125,12 +127,6 @@ function requireCommands (send, config) { }) const subCmds = { - // Files MFS (Mutable Filesystem) - files: require('../files'), - - // Graph - object: require('../object'), - // Network name: require('../name'), ping: require('../ping'), diff --git a/test/files-mfs.spec.js b/test/files-mfs.spec.js index 203fd6eb5..6ae508d1d 100644 --- a/test/files-mfs.spec.js +++ b/test/files-mfs.spec.js @@ -376,9 +376,7 @@ describe('.files (the MFS API part)', function () { cumulativeSize: 70, blocks: 1, type: 'file', - withLocality: false, - local: undefined, - sizeLocal: undefined + withLocality: false }) }) From 3e5967af8e456517485c8a7536792107c0ed6e63 Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Fri, 22 Nov 2019 11:45:30 +0000 Subject: [PATCH 188/233] refactor: async await roundup (#1173) This is a round up of the remaining async/await PRs along with some cleanup and docs fixes. resolves #1103 resolves https://github.com/ipfs/js-ipfs-http-client/issues/1122 resolves https://github.com/ipfs/js-ipfs-http-client/issues/1158 (hopefully!) closes https://github.com/ipfs/js-ipfs-http-client/pull/1164 closes https://github.com/ipfs/js-ipfs-http-client/pull/1165 closes https://github.com/ipfs/js-ipfs-http-client/pull/1166 closes https://github.com/ipfs/js-ipfs-http-client/pull/1169 closes https://github.com/ipfs/js-ipfs-http-client/pull/1170 closes https://github.com/ipfs/js-ipfs-http-client/pull/1172 BREAKING CHANGE: The `log.tail` method now returns an async iterator that yields log messages. Use it like: ```js for await (const message of ipfs.log.tail()) { console.log(message) } ``` BREAKING CHANGE: The response to a call to `log.level` now returns an object that has camel cased keys. i.e. `Message` and `Error` properties have changed to `message` and `error`. BREAKING CHANGE: Dropped support for go-ipfs <= 0.4.4 in `swarm.peers` response. BREAKING CHANGE: The signature for `ipfs.mount` has changed from `ipfs.mount([ipfsPath], [ipnsPath])` to `ipfs.mount([options])`. Where `options` is an optional object that may contain two boolean properties `ipfsPath` and `ipnsPath`. The response object has also changed to be camel case. See https://docs.ipfs.io/reference/api/http/#api-v0-mount. BREAKING CHANGE: Default ping `count` of 1 in client has been removed. The default ping count is now whatever the IPFS node defaults it to (currently 10). If you specifically need 1 ping message then please pass `count: 1` in options for `ipfs.ping()`. BREAKING CHANGE: Multi parameter constructor options are no longer supported. To create a new IPFS HTTP client, pass a single parameter to the constructor. The parameter can be one of: * String, formatted as one of: * Multiaddr e.g. /ip4/127.0.0.1/tcp/5001 * URL e.g. http://127.0.0.1:5001 * [Multiaddr](https://www.npmjs.com/package/multiaddr) instance * Object, in format of either: * Address and path e.g. `{ apiAddr: '/ip4/127.0.0.1/tcp/5001': apiPath: '/api/v0' }` (Note: `apiAddr` can also be a string in URL form or a Multiaddr instance) * Node.js style address e.g. `{ host: '127.0.0.1', port: 5001, protocol: 'http' }` --- README.md | 231 +++++++++-------- package.json | 32 +-- src/add-from-url.js | 4 +- src/add/index.js | 4 +- src/bitswap/stat.js | 2 +- src/bitswap/unwant.js | 2 +- src/bitswap/wantlist.js | 2 +- src/block/get.js | 2 +- src/block/rm-async-iterator.js | 2 +- src/block/stat.js | 2 +- src/bootstrap/list.js | 2 +- src/cat.js | 6 +- src/commands.js | 29 ++- src/config/get.js | 2 +- src/config/profiles/list.js | 2 +- src/dag/resolve.js | 2 +- src/dht/find-peer.js | 6 +- src/dht/find-provs.js | 6 +- src/dht/get.js | 6 +- src/dht/provide.js | 6 +- src/dht/put.js | 6 +- src/dht/query.js | 6 +- src/diag/cmds.js | 2 +- src/diag/net.js | 2 +- src/diag/sys.js | 2 +- src/dns.js | 35 ++- src/get-endpoint-config.js | 15 +- src/get.js | 16 +- src/id.js | 41 +-- src/index.js | 191 ++++++++++---- src/key/export.js | 35 ++- src/key/gen.js | 39 ++- src/key/import.js | 44 ++-- src/key/index.js | 22 +- src/key/list.js | 35 +-- src/key/rename.js | 37 +-- src/key/rm.js | 33 +-- src/lib/configure.js | 31 ++- src/lib/multiaddr.js | 18 -- src/log/index.js | 16 +- src/log/level.js | 40 ++- src/log/ls.js | 27 +- src/log/tail.js | 32 +-- src/ls.js | 16 +- src/mount.js | 43 ++-- src/name/index.js | 16 +- src/name/publish.js | 43 ++-- src/name/pubsub/cancel.js | 36 ++- src/name/pubsub/index.js | 10 +- src/name/pubsub/state.js | 32 +-- src/name/pubsub/subs.js | 29 +-- src/name/resolve.js | 37 +-- src/object/data.js | 4 +- src/object/get.js | 2 +- src/object/links.js | 2 +- src/pin/ls.js | 2 +- src/ping-pull-stream.js | 34 --- src/ping-readable-stream.js | 30 --- src/ping.js | 81 ++---- src/pubsub/ls.js | 2 +- src/pubsub/peers.js | 2 +- src/refs/index.js | 18 +- src/refs/local.js | 2 +- src/repo/gc.js | 48 ++-- src/repo/index.js | 17 +- src/repo/stat.js | 44 ++-- src/repo/version.js | 32 +-- src/resolve.js | 75 ++---- src/stats/bitswap.js | 32 --- src/stats/bw-pull-stream.js | 31 --- src/stats/bw-readable-stream.js | 31 --- src/stats/bw-util.js | 12 - src/stats/bw.js | 51 ++-- src/stats/index.js | 22 +- src/stats/repo.js | 28 -- src/stop.js | 20 +- src/swarm/addrs.js | 40 ++- src/swarm/connect.js | 33 ++- src/swarm/disconnect.js | 33 ++- src/swarm/index.js | 20 +- src/swarm/localAddrs.js | 38 ++- src/swarm/peers.js | 104 +++----- src/update.js | 47 +--- src/utils/clean-cid.js | 17 -- src/utils/clean-multihash.js | 21 -- src/utils/default-config.js | 13 - src/utils/load-commands.js | 161 ------------ src/utils/module-config.js | 22 -- src/utils/multipart.js | 121 --------- src/utils/ping-message-converter.js | 23 -- src/utils/ping-message-stream.js | 27 -- src/utils/prepare-file.js | 153 ----------- src/utils/progress-stream.js | 49 ---- src/utils/send-files-stream.js | 161 ------------ src/utils/send-one-file-multiple-results.js | 18 -- src/utils/send-one-file.js | 15 -- src/utils/send-request.js | 239 ------------------ src/utils/stream-to-json-value.js | 34 --- src/utils/stream-to-value-with-transformer.js | 18 -- src/utils/stream-to-value.js | 18 -- src/version.js | 39 +-- test/constructor.spec.js | 21 +- test/custom-headers.spec.js | 21 +- test/endpoint-config.spec.js | 35 +-- test/lib.configure.spec.js | 13 +- test/log.spec.js | 23 +- test/node/swarm.js | 18 -- test/ping.spec.js | 54 +--- test/sub-modules.spec.js | 52 ++-- 109 files changed, 1079 insertions(+), 2581 deletions(-) delete mode 100644 src/lib/multiaddr.js delete mode 100644 src/ping-pull-stream.js delete mode 100644 src/ping-readable-stream.js delete mode 100644 src/stats/bitswap.js delete mode 100644 src/stats/bw-pull-stream.js delete mode 100644 src/stats/bw-readable-stream.js delete mode 100644 src/stats/bw-util.js delete mode 100644 src/stats/repo.js delete mode 100644 src/utils/clean-cid.js delete mode 100644 src/utils/clean-multihash.js delete mode 100644 src/utils/default-config.js delete mode 100644 src/utils/load-commands.js delete mode 100644 src/utils/module-config.js delete mode 100644 src/utils/multipart.js delete mode 100644 src/utils/ping-message-converter.js delete mode 100644 src/utils/ping-message-stream.js delete mode 100644 src/utils/prepare-file.js delete mode 100644 src/utils/progress-stream.js delete mode 100644 src/utils/send-files-stream.js delete mode 100644 src/utils/send-one-file-multiple-results.js delete mode 100644 src/utils/send-one-file.js delete mode 100644 src/utils/send-request.js delete mode 100644 src/utils/stream-to-json-value.js delete mode 100644 src/utils/stream-to-value-with-transformer.js delete mode 100644 src/utils/stream-to-value.js diff --git a/README.md b/README.md index 4e27f3db3..5c6a00070 100644 --- a/README.md +++ b/README.md @@ -43,14 +43,16 @@ - [In a web browser](#in-a-web-browser) - [CORS](#cors) - [Custom Headers](#custom-headers) + - [Global Timeouts](#global-timeouts) - [Usage](#usage) - [API](#api) - [Files](#files) - [Graph](#graph) - [Network](#network) - [Node Management](#node-management) - - [Instance utils](#instance-utils) - - [Static types and utils](#static-types-and-utils) + - [Additional Options](#additional-options) + - [Instance Utils](#instance-utils) + - [Static Types and Utils](#static-types-and-utils) - [Development](#development) - [Testing](#testing) - [Contribute](#contribute) @@ -86,19 +88,19 @@ To interact with the API, you need to have a local daemon running. It needs to b ### Importing the module and usage ```javascript -var ipfsClient = require('ipfs-http-client') +const ipfsClient = require('ipfs-http-client') // connect to ipfs daemon API server -var ipfs = ipfsClient('localhost', '5001', { protocol: 'http' }) // leaving out the arguments will default to these values +const ipfs = ipfsClient('http://localhost:5001') // (the default in Node.js) // or connect with multiaddr -var ipfs = ipfsClient('/ip4/127.0.0.1/tcp/5001') +const ipfs = ipfsClient('/ip4/127.0.0.1/tcp/5001') // or using options -var ipfs = ipfsClient({ host: 'localhost', port: '5001', protocol: 'http' }) +const ipfs = ipfsClient({ host: 'localhost', port: '5001', protocol: 'http' }) // or specifying a specific API path -var ipfs = ipfsClient({ host: '1.1.1.1', port: '80', 'api-path': '/ipfs/api/v0' }) +const ipfs = ipfsClient({ host: '1.1.1.1', port: '80', apiPath: '/ipfs/api/v0' }) ``` ### Importing a sub-module and usage @@ -106,9 +108,8 @@ var ipfs = ipfsClient({ host: '1.1.1.1', port: '80', 'api-path': '/ipfs/api/v0' ```javascript const bitswap = require('ipfs-http-client/src/bitswap')('/ip4/127.0.0.1/tcp/5001') -bitswap.wantlist(key, (err) => { - // ... -}) +const list = await bitswap.wantlist(key) +// ... ``` ### In a web browser @@ -130,12 +131,11 @@ Instead of a local installation (and browserification) you may request a remote To always request the latest version, use the following: ```html - - - ``` +Note: remove the `.min` from the URL to get the human-readable (not minified) version. + For maximum security you may also decide to: * reference a specific version of IPFS API (to prevent unexpected breaking changes when a newer latest version is published) @@ -153,7 +153,7 @@ crossorigin="anonymous"> CDN-based IPFS API provides the `IpfsHttpClient` constructor as a method of the global `window` object. Example: ```js -const ipfs = window.IpfsHttpClient('localhost', '5001') +const ipfs = window.IpfsHttpClient({ host: 'localhost', port: 5001 }) ``` If you omit the host and port, the client will parse `window.host`, and use this information. This also works, and can be useful if you want to write apps that can be run from multiple different gateways: @@ -186,6 +186,18 @@ const ipfs = ipfsClient({ }) ``` +### Global Timeouts + +To set a global timeout for _all_ requests pass a value for the `timeout` option: + +```js +// Timeout after 10 seconds +const ipfs = ipfsClient({ timeout: 10000 }) +// Timeout after 2 minutes +const ipfs = ipfsClient({ timeout: '2m' }) +// see https://www.npmjs.com/package/parse-duration for valid string values +``` + ## Usage ### API @@ -197,74 +209,74 @@ const ipfs = ipfsClient({ #### Files - [Regular Files API](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md) - - [`ipfs.add(data, [options], [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#add) + - [`ipfs.add(data, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#add) - [`ipfs.addPullStream([options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#addpullstream) - [`ipfs.addReadableStream([options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#addreadablestream) - - [`ipfs.addFromStream(stream, [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#addfromstream) - - [`ipfs.addFromFs(path, [options], [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#addfromfs) - - [`ipfs.addFromURL(url, [options], [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#addfromurl) - - [`ipfs.cat(ipfsPath, [options], [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#cat) + - [`ipfs.addFromStream(stream)`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#addfromstream) + - [`ipfs.addFromFs(path, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#addfromfs) + - [`ipfs.addFromURL(url, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#addfromurl) + - [`ipfs.cat(ipfsPath, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#cat) - [`ipfs.catPullStream(ipfsPath, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#catpullstream) - [`ipfs.catReadableStream(ipfsPath, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#catreadablestream) - - [`ipfs.get(ipfsPath, [options], [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#get) + - [`ipfs.get(ipfsPath, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#get) - [`ipfs.getPullStream(ipfsPath, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#getpullstream) - [`ipfs.getReadableStream(ipfsPath, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#getreadablestream) - - [`ipfs.ls(ipfsPath, [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#ls) + - [`ipfs.ls(ipfsPath)`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#ls) - [`ipfs.lsPullStream(ipfsPath)`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#lspullstream) - [`ipfs.lsReadableStream(ipfsPath)`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#lsreadablestream) - [MFS (mutable file system) specific](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#mutable-file-system) _Explore the Mutable File System through interactive coding challenges in our [ProtoSchool tutorial](https://proto.school/#/mutable-file-system/)._ - - [`ipfs.files.cp([from, to], [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#filescp) - - [`ipfs.files.flush([path], [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#filesflush) - - [`ipfs.files.ls([path], [options], [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#filesls) - - [`ipfs.files.mkdir(path, [options], [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#filesmkdir) - - [`ipfs.files.mv([from, to], [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#filesmv) - - [`ipfs.files.read(path, [options], [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#filesread) + - [`ipfs.files.cp([from, to])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#filescp) + - [`ipfs.files.flush([path])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#filesflush) + - [`ipfs.files.ls([path], [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#filesls) + - [`ipfs.files.mkdir(path, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#filesmkdir) + - [`ipfs.files.mv([from, to])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#filesmv) + - [`ipfs.files.read(path, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#filesread) - [`ipfs.files.readPullStream(path, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#filesreadpullstream) - [`ipfs.files.readReadableStream(path, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#filesreadreadablestream) - - [`ipfs.files.rm(path, [options], [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#filesrm) - - [`ipfs.files.stat(path, [options], [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#filesstat) - - [`ipfs.files.write(path, content, [options], [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#fileswrite) + - [`ipfs.files.rm(path, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#filesrm) + - [`ipfs.files.stat(path, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#filesstat) + - [`ipfs.files.write(path, content, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#fileswrite) - [block](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/BLOCK.md) - - [`ipfs.block.get(cid, [options], [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/BLOCK.md#blockget) - - [`ipfs.block.put(block, [options], [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/BLOCK.md#blockput) - - [`ipfs.block.stat(cid, [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/BLOCK.md#blockstat) + - [`ipfs.block.get(cid, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/BLOCK.md#blockget) + - [`ipfs.block.put(block, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/BLOCK.md#blockput) + - [`ipfs.block.stat(cid)`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/BLOCK.md#blockstat) - [refs](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/REFS.md) - - [`ipfs.refs(ipfsPath, [options], [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/REFS.md#refs) - - [`ipfs.refsReadableStream(ipfsPath, [options], [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/REFS.md#refsreadablestream) - - [`ipfs.refsPullStream(ipfsPath, [options], [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/REFS.md#refspullstream) - - [`ipfs.refs.local([callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/REFS.md#refslocal) - - [`ipfs.refs.localReadableStream([callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/REFS.md#refslocalreadablestream) - - [`ipfs.refs.localPullStream([callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/REFS.md#refslocalpullstream) + - [`ipfs.refs(ipfsPath, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/REFS.md#refs) + - [`ipfs.refsReadableStream(ipfsPath, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/REFS.md#refsreadablestream) + - [`ipfs.refsPullStream(ipfsPath, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/REFS.md#refspullstream) + - [`ipfs.refs.local()`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/REFS.md#refslocal) + - [`ipfs.refs.localReadableStream()`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/REFS.md#refslocalreadablestream) + - [`ipfs.refs.localPullStream()`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/REFS.md#refslocalpullstream) #### Graph - [dag](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/DAG.md) _Explore the DAG API through interactive coding challenges in our [ProtoSchool tutorial](https://proto.school/#/basics)._ - - [`ipfs.dag.get(cid, [path], [options], [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/DAG.md#dagget) - - [`ipfs.dag.put(dagNode, [options], [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/DAG.md#dagput) - - [`ipfs.dag.tree(cid, [path], [options], [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/DAG.md#dagtree) + - [`ipfs.dag.get(cid, [path], [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/DAG.md#dagget) + - [`ipfs.dag.put(dagNode, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/DAG.md#dagput) + - [`ipfs.dag.tree(cid, [path], [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/DAG.md#dagtree) - [object](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/OBJECT.md) - - [`ipfs.object.data(multihash, [options], [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/OBJECT.md#objectdata) - - [`ipfs.object.get(multihash, [options], [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/OBJECT.md#objectget) - - [`ipfs.object.links(multihash, [options], [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/OBJECT.md#objectlinks) - - [`ipfs.object.new([template], [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/OBJECT.md#objectnew) - - [`ipfs.object.patch.addLink(multihash, DAGLink, [options], [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/OBJECT.md#objectpatchaddlink) - - [`ipfs.object.patch.appendData(multihash, data, [options], [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/OBJECT.md#objectpatchappenddata) - - [`ipfs.object.patch.rmLink(multihash, DAGLink, [options], [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/OBJECT.md#objectpatchrmlink) - - [`ipfs.object.patch.setData(multihash, data, [options], [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/OBJECT.md#objectpatchsetdata) - - [`ipfs.object.put(obj, [options], [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/OBJECT.md#objectput) - - [`ipfs.object.stat(multihash, [options], [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/OBJECT.md#objectstat) + - [`ipfs.object.data(multihash, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/OBJECT.md#objectdata) + - [`ipfs.object.get(multihash, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/OBJECT.md#objectget) + - [`ipfs.object.links(multihash, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/OBJECT.md#objectlinks) + - [`ipfs.object.new([template])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/OBJECT.md#objectnew) + - [`ipfs.object.patch.addLink(multihash, DAGLink, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/OBJECT.md#objectpatchaddlink) + - [`ipfs.object.patch.appendData(multihash, data, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/OBJECT.md#objectpatchappenddata) + - [`ipfs.object.patch.rmLink(multihash, DAGLink, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/OBJECT.md#objectpatchrmlink) + - [`ipfs.object.patch.setData(multihash, data, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/OBJECT.md#objectpatchsetdata) + - [`ipfs.object.put(obj, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/OBJECT.md#objectput) + - [`ipfs.object.stat(multihash, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/OBJECT.md#objectstat) - [pin](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/PIN.md) - - [`ipfs.pin.add(hash, [options], [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/PIN.md#pinadd) - - [`ipfs.pin.ls([hash], [options], [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/PIN.md#pinls) - - [`ipfs.pin.rm(hash, [options], [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/PIN.md#pinrm) + - [`ipfs.pin.add(hash, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/PIN.md#pinadd) + - [`ipfs.pin.ls([hash], [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/PIN.md#pinls) + - [`ipfs.pin.rm(hash, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/PIN.md#pinrm) - refs - `ipfs.refs.local()` @@ -272,92 +284,101 @@ const ipfs = ipfsClient({ #### Network - [bootstrap](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/BOOTSTRAP.md) - - [`ipfs.bootstrap.add(addr, [options], [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/BOOTSTRAP.md#bootstrapadd) - - [`ipfs.bootstrap.list([callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/BOOTSTRAP.md#bootstraplist) - - [`ipfs.bootstrap.rm(addr, [options], [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/BOOTSTRAP.md#bootstraprm) + - [`ipfs.bootstrap.add(addr, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/BOOTSTRAP.md#bootstrapadd) + - [`ipfs.bootstrap.list()`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/BOOTSTRAP.md#bootstraplist) + - [`ipfs.bootstrap.rm(addr, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/BOOTSTRAP.md#bootstraprm) - [bitswap](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/BITSWAP.md) - - [`ipfs.bitswap.stat([callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/BITSWAP.md#bitswapstat) + - [`ipfs.bitswap.stat()`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/BITSWAP.md#bitswapstat) - [`ipfs.bitswap.wantlist([peerId])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/BITSWAP.md#bitswapwantlist) - [`ipfs.bitswap.unwant(cid)`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/BITSWAP.md#bitswapunwant) - [dht](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/DHT.md) - - [`ipfs.dht.findPeer(peerId, [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/DHT.md#dhtfindpeer) - - [`ipfs.dht.findProvs(hash, [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/DHT.md#dhtfindprovs) - - [`ipfs.dht.get(key, [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/DHT.md#dhtget) - - [`ipfs.dht.provide(cid, [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/DHT.md#dhtprovide) - - [`ipfs.dht.put(key, value, [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/DHT.md#dhtput) + - [`ipfs.dht.findPeer(peerId)`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/DHT.md#dhtfindpeer) + - [`ipfs.dht.findProvs(hash)`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/DHT.md#dhtfindprovs) + - [`ipfs.dht.get(key)`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/DHT.md#dhtget) + - [`ipfs.dht.provide(cid)`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/DHT.md#dhtprovide) + - [`ipfs.dht.put(key, value)`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/DHT.md#dhtput) - [pubsub](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/PUBSUB.md) - - [`ipfs.pubsub.ls(topic, [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/PUBSUB.md#pubsubls) - - [`ipfs.pubsub.peers(topic, [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/PUBSUB.md#pubsubpeers) - - [`ipfs.pubsub.publish(topic, data, [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/PUBSUB.md#pubsubpublish) - - [`ipfs.pubsub.subscribe(topic, handler, [options], [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/PUBSUB.md#pubsubsubscribe) - - [`ipfs.pubsub.unsubscribe(topic, handler, [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/PUBSUB.md#pubsubunsubscribe) + - [`ipfs.pubsub.ls(topic)`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/PUBSUB.md#pubsubls) + - [`ipfs.pubsub.peers(topic)`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/PUBSUB.md#pubsubpeers) + - [`ipfs.pubsub.publish(topic, data)`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/PUBSUB.md#pubsubpublish) + - [`ipfs.pubsub.subscribe(topic, handler, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/PUBSUB.md#pubsubsubscribe) + - [`ipfs.pubsub.unsubscribe(topic, handler)`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/PUBSUB.md#pubsubunsubscribe) - [swarm](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/SWARM.md) - - [`ipfs.swarm.addrs([callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/SWARM.md#swarmaddrs) - - [`ipfs.swarm.connect(addr, [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/SWARM.md#swarmconnect) - - [`ipfs.swarm.disconnect(addr, [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/SWARM.md#swarmdisconnect) - - [`ipfs.swarm.peers([options], [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/SWARM.md#swarmpeers) + - [`ipfs.swarm.addrs()`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/SWARM.md#swarmaddrs) + - [`ipfs.swarm.connect(addr)`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/SWARM.md#swarmconnect) + - [`ipfs.swarm.disconnect(addr)`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/SWARM.md#swarmdisconnect) + - [`ipfs.swarm.peers([options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/SWARM.md#swarmpeers) - [name](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/NAME.md) - - [`ipfs.name.publish(addr, [options], [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/NAME.md#namepublish) - - [`ipfs.name.pubsub.cancel(arg, [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/NAME.md#namepubsubcancel) - - [`ipfs.name.pubsub.state([callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/NAME.md#namepubsubstate) - - [`ipfs.name.pubsub.subs([callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/NAME.md#namepubsubsubs) - - [`ipfs.name.resolve(addr, [options], [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/NAME.md#nameresolve) + - [`ipfs.name.publish(addr, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/NAME.md#namepublish) + - [`ipfs.name.pubsub.cancel(arg)`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/NAME.md#namepubsubcancel) + - [`ipfs.name.pubsub.state()`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/NAME.md#namepubsubstate) + - [`ipfs.name.pubsub.subs()`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/NAME.md#namepubsubsubs) + - [`ipfs.name.resolve(addr, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/NAME.md#nameresolve) #### Node Management - [miscellaneous operations](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/MISCELLANEOUS.md) - - [`ipfs.dns(domain, [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/MISCELLANEOUS.md#dns) - - [`ipfs.id([callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/MISCELLANEOUS.md#id) - - [`ipfs.ping(id, [options], [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/MISCELLANEOUS.md#ping) + - [`ipfs.dns(domain)`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/MISCELLANEOUS.md#dns) + - [`ipfs.id()`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/MISCELLANEOUS.md#id) + - [`ipfs.ping(id, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/MISCELLANEOUS.md#ping) - [`ipfs.pingPullStream(id, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/MISCELLANEOUS.md#pingpullstream) - [`ipfs.pingReadableStream(id, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/MISCELLANEOUS.md#pingreadablestream) - - [`ipfs.stop([callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/MISCELLANEOUS.md#stop). Alias to `ipfs.shutdown`. - - [`ipfs.version([callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/MISCELLANEOUS.md#version) + - [`ipfs.stop()`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/MISCELLANEOUS.md#stop). Alias to `ipfs.shutdown`. + - [`ipfs.version()`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/MISCELLANEOUS.md#version) - [config](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/CONFIG.md) - - [`ipfs.config.get([key], [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/CONFIG.md#configget) - - [`ipfs.config.replace(config, [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/CONFIG.md#configreplace) - - [`ipfs.config.set(key, value, [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/CONFIG.md#configset) - - [`ipfs.config.profiles.list([callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/CONFIG.md#configprofileslist) - - [`ipfs.config.profiles.apply(name, [options], [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/CONFIG.md#configprofilesapply) + - [`ipfs.config.get([key])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/CONFIG.md#configget) + - [`ipfs.config.replace(config)`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/CONFIG.md#configreplace) + - [`ipfs.config.set(key, value)`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/CONFIG.md#configset) + - [`ipfs.config.profiles.list()`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/CONFIG.md#configprofileslist) + - [`ipfs.config.profiles.apply(name, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/CONFIG.md#configprofilesapply) - [stats](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/STATS.md) - - [`ipfs.stats.bitswap([callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/STATS.md#statsbitswap) - - [`ipfs.stats.bw([options], [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/STATS.md#statsbw) + - [`ipfs.stats.bitswap()`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/STATS.md#statsbitswap) + - [`ipfs.stats.bw([options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/STATS.md#statsbw) - [`ipfs.stats.bwPullStream([options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/STATS.md#statsbwpullstream) - [`ipfs.stats.bwReadableStream([options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/STATS.md#statsbwreadablestream) - - [`ipfs.stats.repo([options], [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/STATS.md#statsrepo) + - [`ipfs.stats.repo([options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/STATS.md#statsrepo) - log - - `ipfs.log.level(subsystem, level, [options], [callback])` - - `ipfs.log.ls([callback])` - - `ipfs.log.tail([callback])` + - `ipfs.log.level(subsystem, level, [options])` + - `ipfs.log.ls()` + - `ipfs.log.tail()` - [repo](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/REPO.md) - - [`ipfs.repo.gc([options], [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/REPO.md#repogc) - - [`ipfs.repo.stat([options], [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/REPO.md#repostat) - - [`ipfs.repo.version([callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/REPO.md#repoversion) + - [`ipfs.repo.gc([options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/REPO.md#repogc) + - [`ipfs.repo.stat([options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/REPO.md#repostat) + - [`ipfs.repo.version()`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/REPO.md#repoversion) - [key](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/KEY.md) - - [`ipfs.key.export(name, password, [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/KEY.md#keyexport) - - [`ipfs.key.gen(name, [options], [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/KEY.md#keygen) - - [`ipfs.key.import(name, pem, password, [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/KEY.md#keyimport) - - [`ipfs.key.list([options, callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/KEY.md#keylist) - - [`ipfs.key.rename(oldName, newName, [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/KEY.md#keyrename) - - [`ipfs.key.rm(name, [callback])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/KEY.md#keyrm) + - [`ipfs.key.export(name, password)`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/KEY.md#keyexport) + - [`ipfs.key.gen(name, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/KEY.md#keygen) + - [`ipfs.key.import(name, pem, password)`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/KEY.md#keyimport) + - [`ipfs.key.list([options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/KEY.md#keylist) + - [`ipfs.key.rename(oldName, newName)`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/KEY.md#keyrename) + - [`ipfs.key.rm(name)`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/KEY.md#keyrm) + +#### Additional Options + +All core API methods take _additional_ `options` specific to the HTTP API: + +* `headers` - An object or [Headers](https://developer.mozilla.org/en-US/docs/Web/API/Headers) instance that can be used to set custom HTTP headers. Note that this option can also be [configured globally](#custom-headers) via the constructor options. +* `signal` - An [`AbortSignal`](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal) that can be used to abort the request on demand. +* `timeout` - A number or string specifying a timeout for the request. If the timeout is reached before data is received a [`TimeoutError`](https://github.com/sindresorhus/ky/blob/2f37c3f999efb36db9108893b8b3d4b3a7f5ec45/index.js#L127-L132) is thrown. If a number is specified it is interpreted as milliseconds, if a string is passed, it is intepreted according to [`parse-duration`](https://www.npmjs.com/package/parse-duration). Note that this option can also be [configured globally](#global-timeouts) via the constructor options. +* `searchParams` - An object or [`URLSearchParams`](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams) instance that can be used to add additional query parameters to the query string sent with each request. -#### Instance utils +#### Instance Utils - `ipfs.getEndpointConfig()` Call this on your client instance to return an object containing the `host`, `port`, `protocol` and `api-path`. -#### Static types and utils +#### Static Types and Utils Aside from the default export, `ipfs-http-client` exports various types and utilities that are included in the bundle: diff --git a/package.json b/package.json index 4b305550a..8fc450b79 100644 --- a/package.json +++ b/package.json @@ -42,7 +42,6 @@ }, "dependencies": { "abort-controller": "^3.0.0", - "async": "^2.6.1", "async-iterator-all": "^1.0.0", "async-iterator-to-pull-stream": "^1.3.0", "bignumber.js": "^9.0.0", @@ -51,58 +50,47 @@ "buffer": "^5.4.2", "callbackify": "^1.1.0", "cids": "~0.7.1", - "concat-stream": "github:hugomrdias/concat-stream#feat/smaller", "debug": "^4.1.0", - "detect-node": "^2.0.4", "err-code": "^2.0.0", "explain-error": "^1.0.4", - "flatmap": "0.0.3", "form-data": "^3.0.0", - "glob": "^7.1.3", "ipfs-block": "~0.8.1", "ipfs-utils": "^0.4.0", "ipld-dag-cbor": "~0.15.0", "ipld-dag-pb": "^0.18.1", "ipld-raw": "^4.0.0", "is-ipfs": "~0.6.1", - "is-pull-stream": "0.0.0", - "is-stream": "^2.0.0", - "iso-stream-http": "~0.1.2", "it-glob": "0.0.6", - "it-tar": "^1.1.0", + "it-tar": "^1.1.1", "it-to-stream": "^0.1.1", "iterable-ndjson": "^1.1.0", - "kind-of": "^6.0.2", "ky": "^0.15.0", "ky-universal": "^0.3.0", "merge-options": "^2.0.0", "multiaddr": "^6.0.6", + "multiaddr-to-uri": "^5.0.0", "multibase": "~0.6.0", "multicodec": "~0.5.1", "multihashes": "~0.4.14", - "ndjson": "github:hugomrdias/ndjson#feat/readable-stream3", - "once": "^1.4.0", "parse-duration": "^0.1.1", "peer-id": "~0.12.3", "peer-info": "~0.15.1", - "promise-nodeify": "^3.0.1", - "promisify-es6": "^1.0.3", - "pull-defer": "~0.2.3", - "pull-stream": "^3.6.9", - "pull-to-stream": "~0.1.1", - "pump": "^3.0.0", - "qs": "^6.5.2", - "readable-stream": "^3.1.1", - "stream-to-pull-stream": "^1.7.2" + "promise-nodeify": "^3.0.1" }, "devDependencies": { "aegir": "^20.4.1", + "async": "^3.1.0", "browser-process-platform": "~0.1.1", "cross-env": "^6.0.0", + "detect-node": "^2.0.4", "go-ipfs-dep": "^0.4.22", - "interface-ipfs-core": "^0.120.0", + "interface-ipfs-core": "^0.121.0", "ipfsd-ctl": "^0.47.1", + "ndjson": "^1.5.0", "nock": "^11.4.0", + "promisify-es6": "^1.0.3", + "pull-stream": "^3.6.14", + "pump": "^3.0.0", "stream-equal": "^1.1.1" }, "engines": { diff --git a/src/add-from-url.js b/src/add-from-url.js index 388072984..deb3f4bad 100644 --- a/src/add-from-url.js +++ b/src/add-from-url.js @@ -6,7 +6,7 @@ const toIterable = require('./lib/stream-to-iterable') module.exports = (config) => { const add = require('./add')(config) - return (url, options) => (async function * () { + return async function * addFromURL (url, options) { options = options || {} const { body } = await kyDefault.get(url) @@ -17,5 +17,5 @@ module.exports = (config) => { } yield * add(input, options) - })() + } } diff --git a/src/add/index.js b/src/add/index.js index 8b8ba7690..b1a8bb2a1 100644 --- a/src/add/index.js +++ b/src/add/index.js @@ -7,7 +7,7 @@ const { toFormData } = require('./form-data') const toCamel = require('../lib/object-to-camel') module.exports = configure(({ ky }) => { - return (input, options) => (async function * () { + return async function * add (input, options) { options = options || {} const searchParams = new URLSearchParams(options.searchParams) @@ -47,7 +47,7 @@ module.exports = configure(({ ky }) => { yield toCoreInterface(file) } } - })() + } }) function toCoreInterface ({ name, hash, size }) { diff --git a/src/bitswap/stat.js b/src/bitswap/stat.js index 3795327bb..fee13c355 100644 --- a/src/bitswap/stat.js +++ b/src/bitswap/stat.js @@ -7,7 +7,7 @@ module.exports = configure(({ ky }) => { return async (options) => { options = options || {} - const res = await ky.get('bitswap/stat', { + const res = await ky.post('bitswap/stat', { timeout: options.timeout, signal: options.signal, headers: options.headers, diff --git a/src/bitswap/unwant.js b/src/bitswap/unwant.js index 9b2044d00..a66653d69 100644 --- a/src/bitswap/unwant.js +++ b/src/bitswap/unwant.js @@ -15,7 +15,7 @@ module.exports = configure(({ ky }) => { searchParams.set('arg', new CID(cid).toString()) } - const res = await ky.get('bitswap/unwant', { + const res = await ky.post('bitswap/unwant', { timeout: options.timeout, signal: options.signal, headers: options.headers, diff --git a/src/bitswap/wantlist.js b/src/bitswap/wantlist.js index 3235de8a9..6b087db1b 100644 --- a/src/bitswap/wantlist.js +++ b/src/bitswap/wantlist.js @@ -17,7 +17,7 @@ module.exports = configure(({ ky }) => { } } - const res = await ky.get('bitswap/wantlist', { + const res = await ky.post('bitswap/wantlist', { timeout: options.timeout, signal: options.signal, headers: options.headers, diff --git a/src/block/get.js b/src/block/get.js index 6e28643f3..b53b38f64 100644 --- a/src/block/get.js +++ b/src/block/get.js @@ -13,7 +13,7 @@ module.exports = configure(({ ky }) => { const searchParams = new URLSearchParams(options.searchParams) searchParams.set('arg', `${cid}`) - const data = await ky.get('block/get', { + const data = await ky.post('block/get', { timeout: options.timeout, signal: options.signal, headers: options.headers, diff --git a/src/block/rm-async-iterator.js b/src/block/rm-async-iterator.js index b934df32b..e44aedcd2 100644 --- a/src/block/rm-async-iterator.js +++ b/src/block/rm-async-iterator.js @@ -7,7 +7,7 @@ const toIterable = require('../lib/stream-to-iterable') const toCamel = require('../lib/object-to-camel') module.exports = configure(({ ky }) => { - return async function * removeBlock (cid, options) { + return async function * rm (cid, options) { options = options || {} if (!Array.isArray(cid)) { diff --git a/src/block/stat.js b/src/block/stat.js index 4d0b82787..9063d137c 100644 --- a/src/block/stat.js +++ b/src/block/stat.js @@ -16,7 +16,7 @@ module.exports = configure(({ ky }) => { const searchParams = new URLSearchParams(options.searchParams) searchParams.set('arg', `${cid}`) - const res = await ky.get('block/stat', { + const res = await ky.post('block/stat', { timeout: options.timeout, signal: options.signal, headers: options.headers, diff --git a/src/bootstrap/list.js b/src/bootstrap/list.js index 2a20f5d05..2a6bbef4b 100644 --- a/src/bootstrap/list.js +++ b/src/bootstrap/list.js @@ -6,7 +6,7 @@ module.exports = configure(({ ky }) => { return async (options) => { options = options || {} - const res = await ky.get('bootstrap/list', { + const res = await ky.post('bootstrap/list', { timeout: options.timeout, signal: options.signal, headers: options.headers, diff --git a/src/cat.js b/src/cat.js index 496257e84..32bccf59e 100644 --- a/src/cat.js +++ b/src/cat.js @@ -6,7 +6,7 @@ const configure = require('./lib/configure') const toIterable = require('./lib/stream-to-iterable') module.exports = configure(({ ky }) => { - return (path, options) => (async function * () { + return async function * cat (path, options) { options = options || {} const searchParams = new URLSearchParams(options.searchParams) @@ -20,7 +20,7 @@ module.exports = configure(({ ky }) => { if (options.offset) searchParams.set('offset', options.offset) if (options.length) searchParams.set('length', options.length) - const res = await ky.get('cat', { + const res = await ky.post('cat', { timeout: options.timeout, signal: options.signal, headers: options.headers, @@ -30,5 +30,5 @@ module.exports = configure(({ ky }) => { for await (const chunk of toIterable(res.body)) { yield Buffer.from(chunk) } - })() + } }) diff --git a/src/commands.js b/src/commands.js index 8327e103a..4f8463fe9 100644 --- a/src/commands.js +++ b/src/commands.js @@ -1,14 +1,19 @@ 'use strict' -const promisify = require('promisify-es6') -const moduleConfig = require('./utils/module-config') - -module.exports = (arg) => { - const send = moduleConfig(arg) - - return promisify((callback) => { - send({ - path: 'commands' - }, callback) - }) -} +const configure = require('./lib/configure') + +module.exports = configure(({ ky }) => { + return options => { + options = options || {} + + const searchParams = new URLSearchParams(options.searchParams) + if (options.flags != null) searchParams.set('flags', options.flags) + + return ky.post('commands', { + timeout: options.timeout, + signal: options.signal, + headers: options.headers, + searchParams + }).json() + } +}) diff --git a/src/config/get.js b/src/config/get.js index b8a42a2e3..e4a7b5c2d 100644 --- a/src/config/get.js +++ b/src/config/get.js @@ -15,7 +15,7 @@ module.exports = configure(({ ky }) => { if (key) searchParams.set('arg', key) const url = key ? 'config' : 'config/show' - const data = await ky.get(url, { + const data = await ky.post(url, { timeout: options.timeout, signal: options.signal, headers: options.headers, diff --git a/src/config/profiles/list.js b/src/config/profiles/list.js index 1e3f44308..0261070bf 100644 --- a/src/config/profiles/list.js +++ b/src/config/profiles/list.js @@ -7,7 +7,7 @@ module.exports = configure(({ ky }) => { return async (options) => { options = options || {} - const res = await ky.get('config/profile/list', { + const res = await ky.post('config/profile/list', { timeout: options.timeout, signal: options.signal, headers: options.headers, diff --git a/src/dag/resolve.js b/src/dag/resolve.js index f0a83d69d..cb7014a41 100644 --- a/src/dag/resolve.js +++ b/src/dag/resolve.js @@ -19,7 +19,7 @@ module.exports = configure(({ ky }) => { const searchParams = new URLSearchParams(options.searchParams) searchParams.set('arg', cidPath) - const res = await ky.get('dag/resolve', { + const res = await ky.post('dag/resolve', { timeout: options.timeout, signal: options.signal, headers: options.headers, diff --git a/src/dht/find-peer.js b/src/dht/find-peer.js index 953e9fc78..71779952c 100644 --- a/src/dht/find-peer.js +++ b/src/dht/find-peer.js @@ -8,14 +8,14 @@ const configure = require('../lib/configure') const toIterable = require('../lib/stream-to-iterable') module.exports = configure(({ ky }) => { - return (peerId, options) => (async function * () { + return async function * findPeer (peerId, options) { options = options || {} const searchParams = new URLSearchParams(options.searchParams) searchParams.set('arg', `${peerId}`) if (options.verbose != null) searchParams.set('verbose', options.verbose) - const res = await ky.get('dht/findpeer', { + const res = await ky.post('dht/findpeer', { timeout: options.timeout, signal: options.signal, headers: options.headers, @@ -33,5 +33,5 @@ module.exports = configure(({ ky }) => { } } } - })() + } }) diff --git a/src/dht/find-provs.js b/src/dht/find-provs.js index b04d001d8..a0fc35722 100644 --- a/src/dht/find-provs.js +++ b/src/dht/find-provs.js @@ -8,7 +8,7 @@ const configure = require('../lib/configure') const toIterable = require('../lib/stream-to-iterable') module.exports = configure(({ ky }) => { - return (cid, options) => (async function * () { + return async function * findProvs (cid, options) { options = options || {} const searchParams = new URLSearchParams(options.searchParams) @@ -16,7 +16,7 @@ module.exports = configure(({ ky }) => { if (options.numProviders) searchParams.set('num-providers', options.numProviders) if (options.verbose != null) searchParams.set('verbose', options.verbose) - const res = await ky.get('dht/findprovs', { + const res = await ky.post('dht/findprovs', { timeout: options.timeout, signal: options.signal, headers: options.headers, @@ -34,5 +34,5 @@ module.exports = configure(({ ky }) => { } } } - })() + } }) diff --git a/src/dht/get.js b/src/dht/get.js index 8a7b8c6a3..d2cd0db22 100644 --- a/src/dht/get.js +++ b/src/dht/get.js @@ -5,14 +5,14 @@ const configure = require('../lib/configure') const toIterable = require('../lib/stream-to-iterable') module.exports = configure(({ ky }) => { - return (key, options) => (async function * () { + return async function * get (key, options) { options = options || {} const searchParams = new URLSearchParams(options.searchParams) searchParams.set('arg', `${key}`) if (options.verbose != null) searchParams.set('verbose', options.verbose) - const res = await ky.get('dht/get', { + const res = await ky.post('dht/get', { timeout: options.timeout, signal: options.signal, headers: options.headers, @@ -26,5 +26,5 @@ module.exports = configure(({ ky }) => { yield message.Extra } } - })() + } }) diff --git a/src/dht/provide.js b/src/dht/provide.js index 1f05710ec..cb72f9c6d 100644 --- a/src/dht/provide.js +++ b/src/dht/provide.js @@ -9,7 +9,7 @@ const toIterable = require('../lib/stream-to-iterable') const toCamel = require('../lib/object-to-camel') module.exports = configure(({ ky }) => { - return (cids, options) => (async function * () { + return async function * provide (cids, options) { cids = Array.isArray(cids) ? cids : [cids] options = options || {} @@ -18,7 +18,7 @@ module.exports = configure(({ ky }) => { if (options.recursive != null) searchParams.set('recursive', options.recursive) if (options.verbose != null) searchParams.set('verbose', options.verbose) - const res = await ky.get('dht/provide', { + const res = await ky.post('dht/provide', { timeout: options.timeout, signal: options.signal, headers: options.headers, @@ -36,5 +36,5 @@ module.exports = configure(({ ky }) => { } yield message } - })() + } }) diff --git a/src/dht/put.js b/src/dht/put.js index 50137e528..49a6947aa 100644 --- a/src/dht/put.js +++ b/src/dht/put.js @@ -10,7 +10,7 @@ const encodeBufferURIComponent = require('../lib/encode-buffer-uri-component') const toCamel = require('../lib/object-to-camel') module.exports = configure(({ ky }) => { - return (key, value, options) => (async function * () { + return async function * put (key, value, options) { options = options || {} const searchParams = new URLSearchParams(options.searchParams) @@ -20,7 +20,7 @@ module.exports = configure(({ ky }) => { value = Buffer.isBuffer(value) ? encodeBufferURIComponent(value) : encodeURIComponent(value) const url = `dht/put?arg=${key}&arg=${value}&${searchParams}` - const res = await ky.get(url, { + const res = await ky.post(url, { timeout: options.timeout, signal: options.signal, headers: options.headers @@ -37,5 +37,5 @@ module.exports = configure(({ ky }) => { } yield message } - })() + } }) diff --git a/src/dht/query.js b/src/dht/query.js index 8ebca71f7..5aefaf90d 100644 --- a/src/dht/query.js +++ b/src/dht/query.js @@ -7,14 +7,14 @@ const configure = require('../lib/configure') const toIterable = require('../lib/stream-to-iterable') module.exports = configure(({ ky }) => { - return (peerId, options) => (async function * () { + return async function * query (peerId, options) { options = options || {} const searchParams = new URLSearchParams(options.searchParams) searchParams.set('arg', `${peerId}`) if (options.verbose != null) searchParams.set('verbose', options.verbose) - const res = await ky.get('dht/query', { + const res = await ky.post('dht/query', { timeout: options.timeout, signal: options.signal, headers: options.headers, @@ -24,5 +24,5 @@ module.exports = configure(({ ky }) => { for await (const message of ndjson(toIterable(res.body))) { yield new PeerInfo(PeerId.createFromB58String(message.ID)) } - })() + } }) diff --git a/src/diag/cmds.js b/src/diag/cmds.js index 68f20ca04..88bb728ef 100644 --- a/src/diag/cmds.js +++ b/src/diag/cmds.js @@ -9,7 +9,7 @@ module.exports = configure(({ ky }) => { const searchParams = new URLSearchParams(options.searchParams) if (options.verbose != null) searchParams.set('verbose', options.verbose) - return ky.get('diag/cmds', { + return ky.post('diag/cmds', { timeout: options.timeout, signal: options.signal, headers: options.headers, diff --git a/src/diag/net.js b/src/diag/net.js index a7404b802..71b971ba7 100644 --- a/src/diag/net.js +++ b/src/diag/net.js @@ -6,7 +6,7 @@ module.exports = configure(({ ky }) => { return options => { options = options || {} - return ky.get('diag/net', { + return ky.post('diag/net', { timeout: options.timeout, signal: options.signal, headers: options.headers, diff --git a/src/diag/sys.js b/src/diag/sys.js index a8cd91b6f..768d13d4d 100644 --- a/src/diag/sys.js +++ b/src/diag/sys.js @@ -6,7 +6,7 @@ module.exports = configure(({ ky }) => { return options => { options = options || {} - return ky.get('diag/sys', { + return ky.post('diag/sys', { timeout: options.timeout, signal: options.signal, headers: options.headers, diff --git a/src/dns.js b/src/dns.js index 3f734bfc2..5032e3fb5 100644 --- a/src/dns.js +++ b/src/dns.js @@ -1,25 +1,22 @@ 'use strict' -const promisify = require('promisify-es6') -const moduleConfig = require('./utils/module-config') +const configure = require('./lib/configure') -const transform = function (res, callback) { - callback(null, res.Path) -} +module.exports = configure(({ ky }) => { + return async (domain, options) => { + options = options || {} -module.exports = (arg) => { - const send = moduleConfig(arg) + const searchParams = new URLSearchParams(options.searchParams) + searchParams.set('arg', domain) + if (options.recursive != null) searchParams.set('recursive', options.recursive) - return promisify((args, opts, callback) => { - if (typeof (opts) === 'function') { - callback = opts - opts = {} - } + const res = await ky.post('dns', { + timeout: options.timeout, + signal: options.signal, + headers: options.headers, + searchParams + }).json() - send.andTransform({ - path: 'dns', - args: args, - qs: opts - }, transform, callback) - }) -} + return res.Path + } +}) diff --git a/src/get-endpoint-config.js b/src/get-endpoint-config.js index a4f0c80e1..cf7125e70 100644 --- a/src/get-endpoint-config.js +++ b/src/get-endpoint-config.js @@ -1,10 +1,13 @@ 'use strict' -module.exports = (config) => { +const configure = require('./lib/configure') + +module.exports = configure(({ apiAddr, apiPath }) => { + const url = new URL(apiAddr) return () => ({ - host: config.host, - port: config.port, - protocol: config.protocol, - 'api-path': config['api-path'] + host: url.hostname, + port: url.port, + protocol: url.protocol.split(':')[0], // remove ":" + 'api-path': apiPath }) -} +}) diff --git a/src/get.js b/src/get.js index c06fc6d36..1a5ebfd93 100644 --- a/src/get.js +++ b/src/get.js @@ -2,24 +2,16 @@ const configure = require('./lib/configure') const Tar = require('it-tar') -const IsIpfs = require('is-ipfs') +const { Buffer } = require('buffer') +const CID = require('cids') const toIterable = require('./lib/stream-to-iterable') -const cleanCID = require('./utils/clean-cid') module.exports = configure(({ ky }) => { return async function * get (path, options) { options = options || {} - try { - path = cleanCID(path) - } catch (err) { - if (!IsIpfs.ipfsPath(path)) { - throw err - } - } - const searchParams = new URLSearchParams() - searchParams.set('arg', path.toString()) + searchParams.set('arg', `${Buffer.isBuffer(path) ? new CID(path) : path}`) if (options.compress !== undefined) { searchParams.set('compress', options.compress) @@ -37,7 +29,7 @@ module.exports = configure(({ ky }) => { searchParams.set('length', options.length) } - const res = await ky.get('get', { + const res = await ky.post('get', { timeout: options.timeout, signal: options.signal, headers: options.headers, diff --git a/src/id.js b/src/id.js index b98be8443..d6080ea67 100644 --- a/src/id.js +++ b/src/id.js @@ -1,32 +1,19 @@ 'use strict' -const promisify = require('promisify-es6') -const moduleConfig = require('./utils/module-config') +const configure = require('./lib/configure') +const toCamel = require('./lib/object-to-camel') -module.exports = (arg) => { - const send = moduleConfig(arg) +module.exports = configure(({ ky }) => { + return async options => { + options = options || {} - return promisify((opts, callback) => { - if (typeof opts === 'function') { - callback = opts - opts = undefined - } + const res = await ky.post('id', { + timeout: options.timeout, + signal: options.signal, + headers: options.headers, + searchParams: options.searchParams + }).json() - send({ - path: 'id', - args: opts - }, (err, result) => { - if (err) { - return callback(err) - } - const identity = { - id: result.ID, - publicKey: result.PublicKey, - addresses: result.Addresses, - agentVersion: result.AgentVersion, - protocolVersion: result.ProtocolVersion - } - callback(null, identity) - }) - }) -} + return toCamel(res) + } +}) diff --git a/src/index.js b/src/index.js index bd58a66f1..d9dc89630 100644 --- a/src/index.js +++ b/src/index.js @@ -1,5 +1,4 @@ 'use strict' -/* global self */ const isIPFS = require('is-ipfs') const { Buffer } = require('buffer') @@ -10,67 +9,151 @@ const multicodec = require('multicodec') const multihash = require('multihashes') const PeerId = require('peer-id') const PeerInfo = require('peer-info') -const loadCommands = require('./utils/load-commands') -const getConfig = require('./utils/default-config') -const sendRequest = require('./utils/send-request') +const nodeify = require('promise-nodeify') +const callbackify = require('callbackify') +const all = require('async-iterator-all') +const toPullStream = require('async-iterator-to-pull-stream') +const toStream = require('it-to-stream') +const BufferList = require('bl/BufferList') +const { concatify, collectify, pullify, streamify } = require('./lib/converters') -function ipfsClient (hostOrMultiaddr, port, userOptions) { - // convert all three params to objects that we can merge. - let options = {} +function ipfsClient (config) { + const add = require('./add')(config) + const addFromFs = require('./add-from-fs')(config) + const addFromURL = require('./add-from-url')(config) + const cat = require('./cat')(config) + const get = require('./get')(config) + const ls = require('./ls')(config) + const ping = require('./ping')(config) + const refs = require('./refs')(config) - if (!hostOrMultiaddr) { - // autoconfigure host and port in browser - if (typeof self !== 'undefined') { - options = urlToOptions(self.location) - } - } else if (multiaddr.isMultiaddr(hostOrMultiaddr)) { - options = maToOptions(hostOrMultiaddr) - } else if (typeof hostOrMultiaddr === 'object') { - options = hostOrMultiaddr - } else if (typeof hostOrMultiaddr === 'string') { - if (hostOrMultiaddr[0] === '/') { - // throws if multiaddr is malformed or can't be converted to a nodeAddress - options = maToOptions(multiaddr(hostOrMultiaddr)) - } else { - // hostOrMultiaddr is domain or ip address as a string - options.host = hostOrMultiaddr - } - } + const api = { + add: (input, options, callback) => { + if (typeof options === 'function') { + callback = options + options = {} + } + return nodeify(collectify(add)(input, options), callback) + }, + addReadableStream: streamify.transform(add), + addPullStream: pullify.transform(add), + addFromFs: (path, options, callback) => { + if (typeof options === 'function') { + callback = options + options = {} + } + return nodeify(collectify(addFromFs)(path, options), callback) + }, + addFromURL: (url, options, callback) => { + if (typeof options === 'function') { + callback = options + options = {} + } + return nodeify(collectify(addFromURL)(url, options), callback) + }, + addFromStream: (input, options, callback) => { + if (typeof options === 'function') { + callback = options + options = {} + } + return nodeify(collectify(add)(input, options), callback) + }, + _addAsyncIterator: add, + bitswap: require('./bitswap')(config), + block: require('./block')(config), + bootstrap: require('./bootstrap')(config), + cat: callbackify.variadic((path, options) => concatify(cat)(path, options)), + catReadableStream: streamify.readable(cat), + catPullStream: pullify.source(cat), + _catAsyncIterator: cat, + commands: callbackify.variadic(require('./commands')(config)), + config: require('./config')(config), + dag: require('./dag')(config), + dht: require('./dht')(config), + diag: require('./diag')(config), + dns: callbackify.variadic(require('./dns')(config)), + files: require('./files')(config), + get: callbackify.variadic(async (path, options) => { + const output = [] - if (port && typeof port !== 'object') { - port = { port: port } - } + for await (const entry of get(path, options)) { + if (entry.content) { + entry.content = new BufferList(await all(entry.content)).slice() + } - const config = Object.assign(getConfig(), options, port, userOptions) - const requestAPI = sendRequest(config) - const cmds = loadCommands(requestAPI, config) - cmds.send = requestAPI + output.push(entry) + } - return cmds -} + return output + }), + getEndpointConfig: require('./get-endpoint-config')(config), + getReadableStream: streamify.readable(async function * (path, options) { + for await (const file of get(path, options)) { + if (file.content) { + const { content } = file + file.content = toStream((async function * () { + for await (const chunk of content) { + yield chunk.slice() // Convert bl to Buffer + } + })()) + } -function maToOptions (multiaddr) { - // ma.nodeAddress() throws if multiaddr can't be converted to a nodeAddress - const nodeAddr = multiaddr.nodeAddress() - const protos = multiaddr.protos() - // only http and https are allowed as protocol, - // anything else will be replaced with http - const exitProtocol = protos[protos.length - 1].name - return { - host: nodeAddr.address, - port: nodeAddr.port, - protocol: exitProtocol.startsWith('http') ? exitProtocol : 'http' - } -} + yield file + } + }), + getPullStream: pullify.source(async function * (path, options) { + for await (const file of get(path, options)) { + if (file.content) { + const { content } = file + file.content = toPullStream((async function * () { + for await (const chunk of content) { + yield chunk.slice() // Convert bl to Buffer + } + })()) + } -function urlToOptions (url) { - return { - host: url.hostname, - port: url.port || (url.protocol.startsWith('https') ? 443 : 80), - protocol: url.protocol.startsWith('http') ? url.protocol.split(':')[0] : 'http' + yield file + } + }), + _getAsyncIterator: get, + id: callbackify.variadic(require('./id')(config)), + key: require('./key')(config), + log: require('./log')(config), + ls: callbackify.variadic((path, options) => collectify(ls)(path, options)), + lsReadableStream: streamify.readable(ls), + lsPullStream: pullify.source(ls), + _lsAsyncIterator: ls, + mount: callbackify.variadic(require('./mount')(config)), + name: require('./name')(config), + object: require('./object')(config), + pin: require('./pin')(config), + ping: callbackify.variadic(collectify(ping)), + pingReadableStream: streamify.readable(ping), + pingPullStream: pullify.source(ping), + pubsub: require('./pubsub')(config), + refs: callbackify.variadic((path, options) => collectify(refs)(path, options)), + refsReadableStream: streamify.readable(refs), + refsPullStream: pullify.source(refs), + _refsAsyncIterator: refs, + repo: require('./repo')(config), + resolve: callbackify.variadic(require('./resolve')(config)), + stats: require('./stats')(config), + stop: callbackify.variadic(require('./stop')(config)), + shutdown: callbackify.variadic(require('./stop')(config)), + swarm: require('./swarm')(config), + version: callbackify.variadic(require('./version')(config)) } + + Object.assign(api.refs, { + local: callbackify.variadic(options => collectify(refs.local)(options)), + localReadableStream: streamify.readable(refs.local), + localPullStream: pullify.source(refs.local), + _localAsyncIterator: refs.local + }) + + return api } -module.exports = ipfsClient +Object.assign(ipfsClient, { isIPFS, Buffer, CID, multiaddr, multibase, multicodec, multihash, PeerId, PeerInfo }) -Object.assign(module.exports, { isIPFS, Buffer, CID, multiaddr, multibase, multicodec, multihash, PeerId, PeerInfo }) +module.exports = ipfsClient diff --git a/src/key/export.js b/src/key/export.js index f19db4022..b5f315580 100644 --- a/src/key/export.js +++ b/src/key/export.js @@ -1,16 +1,25 @@ 'use strict' -const promisify = require('promisify-es6') +const configure = require('../lib/configure') -module.exports = (send) => { - return promisify((name, password, callback) => { - send({ - path: 'key/export', - args: name, - qs: { password: password } - }, (err, pem) => { - if (err) return callback(err) - callback(null, pem.toString()) - }) - }) -} +module.exports = configure(({ ky }) => { + return (name, password, options) => { + if (typeof password !== 'string') { + options = password + password = null + } + + options = options || {} + + const searchParams = new URLSearchParams(options.searchParams) + searchParams.set('arg', name) + if (password) searchParams.set('password', password) + + return ky.post('key/export', { + timeout: options.timeout, + signal: options.signal, + headers: options.headers, + searchParams + }).text() + } +}) diff --git a/src/key/gen.js b/src/key/gen.js index 38612d9af..5fd6acb86 100644 --- a/src/key/gen.js +++ b/src/key/gen.js @@ -1,25 +1,24 @@ 'use strict' -const promisify = require('promisify-es6') +const configure = require('../lib/configure') +const toCamel = require('../lib/object-to-camel') -const transform = function (res, callback) { - callback(null, { - id: res.Id, - name: res.Name - }) -} +module.exports = configure(({ ky }) => { + return async (name, options) => { + options = options || {} -module.exports = (send) => { - return promisify((args, opts, callback) => { - if (typeof (opts) === 'function') { - callback = opts - opts = {} - } + const searchParams = new URLSearchParams(options.searchParams) + searchParams.set('arg', name) + if (options.type) searchParams.set('type', options.type) + if (options.size != null) searchParams.set('size', options.size) - send.andTransform({ - path: 'key/gen', - args: args, - qs: opts - }, transform, callback) - }) -} + const res = await ky.post('key/gen', { + timeout: options.timeout, + signal: options.signal, + headers: options.headers, + searchParams + }).json() + + return toCamel(res) + } +}) diff --git a/src/key/import.js b/src/key/import.js index 9cea80e27..7cc8f5ddc 100644 --- a/src/key/import.js +++ b/src/key/import.js @@ -1,23 +1,29 @@ 'use strict' -const promisify = require('promisify-es6') +const configure = require('../lib/configure') +const toCamel = require('../lib/object-to-camel') -const transform = function (res, callback) { - callback(null, { - id: res.Id, - name: res.Name - }) -} +module.exports = configure(({ ky }) => { + return async (name, pem, password, options) => { + if (typeof password !== 'string') { + options = password + password = null + } -module.exports = (send) => { - return promisify((name, pem, password, callback) => { - send.andTransform({ - path: 'key/import', - args: name, - qs: { - pem: pem, - password: password - } - }, transform, callback) - }) -} + options = options || {} + + const searchParams = new URLSearchParams(options.searchParams) + searchParams.set('arg', name) + searchParams.set('pem', pem) + if (password) searchParams.set('password', password) + + const res = await ky.post('key/import', { + timeout: options.timeout, + signal: options.signal, + headers: options.headers, + searchParams + }).json() + + return toCamel(res) + } +}) diff --git a/src/key/index.js b/src/key/index.js index 717d719c3..7293236f1 100644 --- a/src/key/index.js +++ b/src/key/index.js @@ -1,16 +1,12 @@ 'use strict' -const moduleConfig = require('../utils/module-config') +const callbackify = require('callbackify') -module.exports = (arg) => { - const send = moduleConfig(arg) - - return { - gen: require('./gen')(send), - list: require('./list')(send), - rename: require('./rename')(send), - rm: require('./rm')(send), - export: require('./export')(send), - import: require('./import')(send) - } -} +module.exports = config => ({ + gen: callbackify.variadic(require('./gen')(config)), + list: callbackify.variadic(require('./list')(config)), + rename: callbackify.variadic(require('./rename')(config)), + rm: callbackify.variadic(require('./rm')(config)), + export: callbackify.variadic(require('./export')(config)), + import: callbackify.variadic(require('./import')(config)) +}) diff --git a/src/key/list.js b/src/key/list.js index bcd9bc8e2..80e5069aa 100644 --- a/src/key/list.js +++ b/src/key/list.js @@ -1,26 +1,19 @@ 'use strict' -const promisify = require('promisify-es6') +const configure = require('../lib/configure') +const toCamel = require('../lib/object-to-camel') -const transform = function (res, callback) { - callback(null, res.Keys.map(key => { - return { - id: key.Id, - name: key.Name - } - })) -} +module.exports = configure(({ ky }) => { + return async options => { + options = options || {} -module.exports = (send) => { - return promisify((opts, callback) => { - if (typeof (opts) === 'function') { - callback = opts - opts = {} - } + const res = await ky.post('key/list', { + timeout: options.timeout, + signal: options.signal, + headers: options.headers, + searchParams: options.searchParams + }).json() - send.andTransform({ - path: 'key/list', - qs: opts - }, transform, callback) - }) -} + return (res.Keys || []).map(k => toCamel(k)) + } +}) diff --git a/src/key/rename.js b/src/key/rename.js index 68b45f010..18e069768 100644 --- a/src/key/rename.js +++ b/src/key/rename.js @@ -1,21 +1,24 @@ 'use strict' -const promisify = require('promisify-es6') +const configure = require('../lib/configure') +const toCamel = require('../lib/object-to-camel') -const transform = function (res, callback) { - callback(null, { - id: res.Id, - was: res.Was, - now: res.Now, - overwrite: res.Overwrite - }) -} +module.exports = configure(({ ky }) => { + return async (oldName, newName, options) => { + options = options || {} -module.exports = (send) => { - return promisify((oldName, newName, callback) => { - send.andTransform({ - path: 'key/rename', - args: [oldName, newName] - }, transform, callback) - }) -} + const searchParams = new URLSearchParams(options.searchParams) + searchParams.set('arg', oldName) + searchParams.append('arg', newName) + if (options.force != null) searchParams.set('force', options.force) + + const res = await ky.post('key/rename', { + timeout: options.timeout, + signal: options.signal, + headers: options.headers, + searchParams + }).json() + + return toCamel(res) + } +}) diff --git a/src/key/rm.js b/src/key/rm.js index 7e4e98500..edab61060 100644 --- a/src/key/rm.js +++ b/src/key/rm.js @@ -1,19 +1,22 @@ 'use strict' -const promisify = require('promisify-es6') +const configure = require('../lib/configure') +const toCamel = require('../lib/object-to-camel') -const transform = function (res, callback) { - callback(null, { - id: res.Keys[0].Id, - name: res.Keys[0].Name - }) -} +module.exports = configure(({ ky }) => { + return async (name, options) => { + options = options || {} -module.exports = (send) => { - return promisify((args, callback) => { - send.andTransform({ - path: 'key/rm', - args: args - }, transform, callback) - }) -} + const searchParams = new URLSearchParams(options.searchParams) + searchParams.set('arg', name) + + const res = await ky.post('key/rm', { + timeout: options.timeout, + signal: options.signal, + headers: options.headers, + searchParams + }).json() + + return toCamel(res.Keys[0]) + } +}) diff --git a/src/lib/configure.js b/src/lib/configure.js index b1a1f8948..9e6c9465f 100644 --- a/src/lib/configure.js +++ b/src/lib/configure.js @@ -3,7 +3,7 @@ const ky = require('ky-universal').default const { isBrowser, isWebWorker } = require('ipfs-utils/src/env') -const { toUri } = require('./multiaddr') +const toUri = require('multiaddr-to-uri') const errorHandler = require('./error-handler') const mergeOptions = require('merge-options').bind({ ignoreUndefined: true }) const parseDuration = require('parse-duration') @@ -22,10 +22,17 @@ module.exports = create => config => { config.apiAddr = (config.apiAddr || getDefaultApiAddr(config)).toString() config.apiAddr = config.apiAddr.startsWith('/') ? toUri(config.apiAddr) : config.apiAddr - config.apiPath = config.apiPath || config['api-path'] || '/api/v0' + config.apiAddr = trimEnd(config.apiAddr, '/') + + const apiAddrPath = getNonRootPath(config.apiAddr) + + // Use configured apiPath, or path on the end of apiAddr (if there is one) or default to /api/v0 + config.apiPath = config.apiPath || config['api-path'] || apiAddrPath || '/api/v0' + config.apiPath = trimEnd(config.apiPath, '/') + + // If user passed apiAddr with a path, trim it from the end (it is now apiPath) + config.apiAddr = apiAddrPath ? trimEnd(config.apiAddr, apiAddrPath) : config.apiAddr - // TODO configure ky to use config.fetch when this is released: - // https://github.com/sindresorhus/ky/pull/153 const defaults = { prefixUrl: config.apiAddr + config.apiPath, timeout: parseTimeout(config.timeout) || 60000 * 20, @@ -50,13 +57,9 @@ module.exports = create => config => { function getDefaultApiAddr ({ protocol, host, port }) { if (isBrowser || isWebWorker) { - if (!protocol && !host && !port) { // Use current origin - return '' - } - if (!protocol) { protocol = location.protocol.startsWith('http') - ? location.protocol.split(':')[0] + ? trimEnd(location.protocol, ':') : 'http' } @@ -81,3 +84,13 @@ function wrap (fn, defaults) { function parseTimeout (value) { return typeof value === 'string' ? parseDuration(value) : value } + +const trimEnd = (str, end) => str.endsWith(end) ? str.slice(0, -end.length) : str + +// Get the path from a URL is it is not / +function getNonRootPath (url) { + if (url) { + const { pathname } = new URL(url) + return pathname === '/' ? null : pathname + } +} diff --git a/src/lib/multiaddr.js b/src/lib/multiaddr.js deleted file mode 100644 index 09462ab34..000000000 --- a/src/lib/multiaddr.js +++ /dev/null @@ -1,18 +0,0 @@ -'use strict' - -// Convert a multiaddr to a URI -// Assumes multiaddr is in a format that can be converted to a HTTP(s) URI -exports.toUri = ma => { - const parts = `${ma}`.split('/') - const port = getPort(parts) - return `${getProtocol(parts)}://${parts[2]}${port == null ? '' : ':' + port}` -} - -function getProtocol (maParts) { - return maParts.indexOf('https') === -1 ? 'http' : 'https' -} - -function getPort (maParts) { - const tcpIndex = maParts.indexOf('tcp') - return tcpIndex === -1 ? null : maParts[tcpIndex + 1] -} diff --git a/src/log/index.js b/src/log/index.js index 94597bdc6..f7d94f910 100644 --- a/src/log/index.js +++ b/src/log/index.js @@ -1,13 +1,9 @@ 'use strict' -const moduleConfig = require('../utils/module-config') +const callbackify = require('callbackify') -module.exports = (arg) => { - const send = moduleConfig(arg) - - return { - tail: require('./tail')(send), - ls: require('./ls')(send), - level: require('./level')(send) - } -} +module.exports = config => ({ + tail: require('./tail')(config), + ls: callbackify.variadic(require('./ls')(config)), + level: callbackify.variadic(require('./level')(config)) +}) diff --git a/src/log/level.js b/src/log/level.js index 4304ff90f..dcc20c7bd 100644 --- a/src/log/level.js +++ b/src/log/level.js @@ -1,27 +1,23 @@ 'use strict' -const promisify = require('promisify-es6') +const configure = require('../lib/configure') +const toCamel = require('../lib/object-to-camel') -module.exports = (send) => { - return promisify((subsystem, level, opts, callback) => { - if (typeof opts === 'function') { - callback = opts - opts = {} - } - if (typeof subsystem !== 'string') { - return callback(new Error('Invalid subsystem type')) - } +module.exports = configure(({ ky }) => { + return async (subsystem, level, options) => { + options = options || {} - if (typeof level !== 'string') { - return callback(new Error('Invalid level type')) - } + const searchParams = new URLSearchParams(options.searchParams) + searchParams.set('arg', subsystem) + searchParams.append('arg', level) - send({ - path: 'log/level', - args: [subsystem, level], - qs: opts, - files: undefined, - buffer: true - }, callback) - }) -} + const res = await ky.post('log/level', { + timeout: options.timeout, + signal: options.signal, + headers: options.headers, + searchParams + }).json() + + return toCamel(res) + } +}) diff --git a/src/log/ls.js b/src/log/ls.js index ab243605b..0a8d69c6c 100644 --- a/src/log/ls.js +++ b/src/log/ls.js @@ -1,17 +1,18 @@ 'use strict' -const promisify = require('promisify-es6') +const configure = require('../lib/configure') -module.exports = (send) => { - return promisify((callback) => { - send({ - path: 'log/ls' - }, (err, result) => { - if (err) { - return callback(err) - } +module.exports = configure(({ ky }) => { + return async options => { + options = options || {} - callback(null, result.Strings) - }) - }) -} + const res = await ky.post('log/ls', { + timeout: options.timeout, + signal: options.signal, + headers: options.headers, + searchParams: options.searchParams + }).json() + + return res.Strings + } +}) diff --git a/src/log/tail.js b/src/log/tail.js index bad4e4d34..00708e9b9 100644 --- a/src/log/tail.js +++ b/src/log/tail.js @@ -1,20 +1,20 @@ 'use strict' -const promisify = require('promisify-es6') -const pump = require('pump') -const ndjson = require('ndjson') +const ndjson = require('iterable-ndjson') +const configure = require('../lib/configure') +const toIterable = require('../lib/stream-to-iterable') -module.exports = (send) => { - return promisify((callback) => { - return send({ - path: 'log/tail' - }, (err, response) => { - if (err) { - return callback(err) - } - const outputStream = ndjson.parse() - pump(response, outputStream) - callback(null, outputStream) +module.exports = configure(({ ky }) => { + return async function * tail (options) { + options = options || {} + + const res = await ky.post('log/tail', { + timeout: options.timeout, + signal: options.signal, + headers: options.headers, + searchParams: options.searchParams }) - }) -} + + yield * ndjson(toIterable(res.body)) + } +}) diff --git a/src/ls.js b/src/ls.js index fc9921963..a9cd476f9 100644 --- a/src/ls.js +++ b/src/ls.js @@ -1,23 +1,15 @@ 'use strict' -const IsIpfs = require('is-ipfs') -const cleanCID = require('./utils/clean-cid') +const { Buffer } = require('buffer') +const CID = require('cids') const configure = require('./lib/configure') module.exports = configure(({ ky }) => { return async function * ls (path, options) { options = options || {} - try { - path = cleanCID(path) - } catch (err) { - if (!IsIpfs.ipfsPath(path)) { - throw err - } - } - const searchParams = new URLSearchParams() - searchParams.set('arg', path.toString()) + searchParams.set('arg', `${Buffer.isBuffer(path) ? new CID(path) : path}`) if (options.long !== undefined) { searchParams.set('long', options.long) @@ -31,7 +23,7 @@ module.exports = configure(({ ky }) => { searchParams.set('recursive', options.recursive) } - const res = await ky.get('ls', { + const res = await ky.post('ls', { timeout: options.timeout, signal: options.signal, headers: options.headers, diff --git a/src/mount.js b/src/mount.js index 7c2e92cab..a5d2faef1 100644 --- a/src/mount.js +++ b/src/mount.js @@ -1,30 +1,23 @@ 'use strict' -const promisify = require('promisify-es6') -const moduleConfig = require('./utils/module-config') +const configure = require('./lib/configure') +const toCamel = require('./lib/object-to-camel') -module.exports = (arg) => { - const send = moduleConfig(arg) +module.exports = configure(({ ky }) => { + return async options => { + options = options || {} - return promisify((ipfs, ipns, callback) => { - if (typeof ipfs === 'function') { - callback = ipfs - ipfs = null - } else if (typeof ipns === 'function') { - callback = ipns - ipns = null - } - const opts = {} - if (ipfs) { - opts.f = ipfs - } - if (ipns) { - opts.n = ipns - } + const searchParams = new URLSearchParams(options.searchParams) + if (options.ipfsPath != null) searchParams.set('ipfs-path', options.ipfsPath) + if (options.ipnsPath != null) searchParams.set('ipns-path', options.ipnsPath) - send({ - path: 'mount', - qs: opts - }, callback) - }) -} + const res = await ky.post('dns', { + timeout: options.timeout, + signal: options.signal, + headers: options.headers, + searchParams + }).json() + + return toCamel(res) + } +}) diff --git a/src/name/index.js b/src/name/index.js index 8f823311a..7a6837b82 100644 --- a/src/name/index.js +++ b/src/name/index.js @@ -1,13 +1,9 @@ 'use strict' -const moduleConfig = require('../utils/module-config') +const callbackify = require('callbackify') -module.exports = (arg) => { - const send = moduleConfig(arg) - - return { - publish: require('./publish')(send), - resolve: require('./resolve')(send), - pubsub: require('./pubsub')(send) - } -} +module.exports = config => ({ + publish: callbackify.variadic(require('./publish')(config)), + resolve: callbackify.variadic(require('./resolve')(config)), + pubsub: require('./pubsub')(config) +}) diff --git a/src/name/publish.js b/src/name/publish.js index cfc7482e3..e470606f9 100644 --- a/src/name/publish.js +++ b/src/name/publish.js @@ -1,25 +1,28 @@ 'use strict' -const promisify = require('promisify-es6') +const configure = require('../lib/configure') +const toCamel = require('../lib/object-to-camel') -const transform = function (res, callback) { - callback(null, { - name: res.Name, - value: res.Value - }) -} +module.exports = configure(({ ky }) => { + return async (path, options) => { + options = options || {} -module.exports = (send) => { - return promisify((args, opts, callback) => { - if (typeof (opts) === 'function') { - callback = opts - opts = {} - } + const searchParams = new URLSearchParams(options.searchParams) + searchParams.set('arg', path) + if (options.allowOffline != null) searchParams.set('allow-offline', options.allowOffline) + if (options.key) searchParams.set('key', options.key) + if (options.lifetime) searchParams.set('lifetime', options.lifetime) + if (options.quieter != null) searchParams.set('quieter', options.quieter) + if (options.resolve != null) searchParams.set('resolve', options.resolve) + if (options.ttl) searchParams.set('ttl', options.ttl) - send.andTransform({ - path: 'name/publish', - args: args, - qs: opts - }, transform, callback) - }) -} + const res = await ky.post('name/publish', { + timeout: options.timeout, + signal: options.signal, + headers: options.headers, + searchParams + }).json() + + return toCamel(res) + } +}) diff --git a/src/name/pubsub/cancel.js b/src/name/pubsub/cancel.js index 32dbbb3af..ea5391e64 100644 --- a/src/name/pubsub/cancel.js +++ b/src/name/pubsub/cancel.js @@ -1,24 +1,22 @@ 'use strict' -const promisify = require('promisify-es6') +const configure = require('../../lib/configure') +const toCamel = require('../../lib/object-to-camel') -const transform = function (res, callback) { - callback(null, { - canceled: res.Canceled === undefined || res.Canceled === true - }) -} +module.exports = configure(({ ky }) => { + return async (name, options) => { + options = options || {} -module.exports = (send) => { - return promisify((args, opts, callback) => { - if (typeof (opts) === 'function') { - callback = opts - opts = {} - } + const searchParams = new URLSearchParams(options.searchParams) + searchParams.set('arg', name) - send.andTransform({ - path: 'name/pubsub/cancel', - args: args, - qs: opts - }, transform, callback) - }) -} + const res = await ky.post('name/pubsub/cancel', { + timeout: options.timeout, + signal: options.signal, + headers: options.headers, + searchParams + }).json() + + return toCamel(res) + } +}) diff --git a/src/name/pubsub/index.js b/src/name/pubsub/index.js index aefc0f880..70db19874 100644 --- a/src/name/pubsub/index.js +++ b/src/name/pubsub/index.js @@ -1,7 +1,9 @@ 'use strict' -module.exports = (send) => ({ - cancel: require('./cancel')(send), - state: require('./state')(send), - subs: require('./subs')(send) +const callbackify = require('callbackify') + +module.exports = config => ({ + cancel: callbackify.variadic(require('./cancel')(config)), + state: callbackify.variadic(require('./state')(config)), + subs: callbackify.variadic(require('./subs')(config)) }) diff --git a/src/name/pubsub/state.js b/src/name/pubsub/state.js index cc9b0b369..03e18aa7f 100644 --- a/src/name/pubsub/state.js +++ b/src/name/pubsub/state.js @@ -1,23 +1,19 @@ 'use strict' -const promisify = require('promisify-es6') +const configure = require('../../lib/configure') +const toCamel = require('../../lib/object-to-camel') -const transform = function (res, callback) { - callback(null, { - enabled: res.Enabled - }) -} +module.exports = configure(({ ky }) => { + return async options => { + options = options || {} -module.exports = (send) => { - return promisify((opts, callback) => { - if (typeof (opts) === 'function') { - callback = opts - opts = {} - } + const res = await ky.post('name/pubsub/state', { + timeout: options.timeout, + signal: options.signal, + headers: options.headers, + searchParams: options.searchParams + }).json() - send.andTransform({ - path: 'name/pubsub/state', - qs: opts - }, transform, callback) - }) -} + return toCamel(res) + } +}) diff --git a/src/name/pubsub/subs.js b/src/name/pubsub/subs.js index 3a3a54c2a..9bc6c2208 100644 --- a/src/name/pubsub/subs.js +++ b/src/name/pubsub/subs.js @@ -1,21 +1,18 @@ 'use strict' -const promisify = require('promisify-es6') +const configure = require('../../lib/configure') -const transform = function (res, callback) { - callback(null, res.Strings || []) -} +module.exports = configure(({ ky }) => { + return async (name, options) => { + options = options || {} -module.exports = (send) => { - return promisify((opts, callback) => { - if (typeof (opts) === 'function') { - callback = opts - opts = {} - } + const res = await ky.post('name/pubsub/subs', { + timeout: options.timeout, + signal: options.signal, + headers: options.headers, + searchParams: options.searchParams + }).json() - send.andTransform({ - path: 'name/pubsub/subs', - qs: opts - }, transform, callback) - }) -} + return res.Strings || [] + } +}) diff --git a/src/name/resolve.js b/src/name/resolve.js index addb567d6..b6e8db47e 100644 --- a/src/name/resolve.js +++ b/src/name/resolve.js @@ -1,22 +1,25 @@ 'use strict' -const promisify = require('promisify-es6') +const configure = require('../lib/configure') -const transform = function (res, callback) { - callback(null, res.Path) -} +module.exports = configure(({ ky }) => { + return async (path, options) => { + options = options || {} -module.exports = (send) => { - return promisify((args, opts, callback) => { - if (typeof (opts) === 'function') { - callback = opts - opts = {} - } + const searchParams = new URLSearchParams(options.searchParams) + searchParams.set('arg', path) + if (options.dhtRecordCount != null) searchParams.set('dht-record-count', options.dhtRecordCount) + if (options.dhtTimeout != null) searchParams.set('dht-timeout', options.dhtTimeout) + if (options.noCache != null) searchParams.set('nocache', options.noCache) + if (options.recursive != null) searchParams.set('recursive', options.recursive) - send.andTransform({ - path: 'name/resolve', - args: args, - qs: opts - }, transform, callback) - }) -} + const res = await ky.post('name/resolve', { + timeout: options.timeout, + signal: options.signal, + headers: options.headers, + searchParams + }).json() + + return res.Path + } +}) diff --git a/src/object/data.js b/src/object/data.js index 8f1e42b7a..48291f722 100644 --- a/src/object/data.js +++ b/src/object/data.js @@ -6,13 +6,13 @@ const configure = require('../lib/configure') const toIterable = require('../lib/stream-to-iterable') module.exports = configure(({ ky }) => { - return async function * (cid, options) { + return async function * data (cid, options) { options = options || {} const searchParams = new URLSearchParams(options.searchParams) searchParams.set('arg', `${Buffer.isBuffer(cid) ? new CID(cid) : cid}`) - const res = await ky.get('object/data', { + const res = await ky.post('object/data', { timeout: options.timeout, signal: options.signal, headers: options.headers, diff --git a/src/object/get.js b/src/object/get.js index 5ed7468dc..8dd2b638d 100644 --- a/src/object/get.js +++ b/src/object/get.js @@ -13,7 +13,7 @@ module.exports = configure(({ ky }) => { searchParams.set('arg', `${Buffer.isBuffer(cid) ? new CID(cid) : cid}`) searchParams.set('data-encoding', 'base64') - const res = await ky.get('object/get', { + const res = await ky.post('object/get', { timeout: options.timeout, signal: options.signal, headers: options.headers, diff --git a/src/object/links.js b/src/object/links.js index 49b088254..f05ddb630 100644 --- a/src/object/links.js +++ b/src/object/links.js @@ -12,7 +12,7 @@ module.exports = configure(({ ky }) => { const searchParams = new URLSearchParams(options.searchParams) searchParams.set('arg', `${Buffer.isBuffer(cid) ? new CID(cid) : cid}`) - const res = await ky.get('object/links', { + const res = await ky.post('object/links', { timeout: options.timeout, signal: options.signal, headers: options.headers, diff --git a/src/pin/ls.js b/src/pin/ls.js index bf1746d63..cd1cc07f1 100644 --- a/src/pin/ls.js +++ b/src/pin/ls.js @@ -15,7 +15,7 @@ module.exports = configure(({ ky }) => { if (path) searchParams.set('arg', `${path}`) if (options.type) searchParams.set('type', options.type) - const { Keys } = await ky.get('pin/ls', { + const { Keys } = await ky.post('pin/ls', { timeout: options.timeout, signal: options.signal, headers: options.headers, diff --git a/src/ping-pull-stream.js b/src/ping-pull-stream.js deleted file mode 100644 index a7871faa3..000000000 --- a/src/ping-pull-stream.js +++ /dev/null @@ -1,34 +0,0 @@ -'use strict' - -const toPull = require('stream-to-pull-stream') -const deferred = require('pull-defer') -const pump = require('pump') -const moduleConfig = require('./utils/module-config') -const PingMessageStream = require('./utils/ping-message-stream') - -module.exports = (arg) => { - const send = moduleConfig(arg) - - return (id, opts = {}) => { - // Default number of packtes to 1 - if (!opts.n && !opts.count) { - opts.n = 1 - } - const request = { - path: 'ping', - args: id, - qs: opts - } - const p = deferred.source() - const response = new PingMessageStream() - - send(request, (err, stream) => { - if (err) { return p.abort(err) } - - pump(stream, response) - p.resolve(toPull.source(response)) - }) - - return p - } -} diff --git a/src/ping-readable-stream.js b/src/ping-readable-stream.js deleted file mode 100644 index df4f70401..000000000 --- a/src/ping-readable-stream.js +++ /dev/null @@ -1,30 +0,0 @@ -'use strict' - -const pump = require('pump') -const moduleConfig = require('./utils/module-config') -const PingMessageStream = require('./utils/ping-message-stream') - -module.exports = (arg) => { - const send = moduleConfig(arg) - - return (id, opts = {}) => { - // Default number of packtes to 1 - if (!opts.n && !opts.count) { - opts.n = 1 - } - const request = { - path: 'ping', - args: id, - qs: opts - } - - const response = new PingMessageStream() - - send(request, (err, stream) => { - if (err) { return response.emit('error', err) } - pump(stream, response) - }) - - return response - } -} diff --git a/src/ping.js b/src/ping.js index f3ff63ec8..33b275617 100644 --- a/src/ping.js +++ b/src/ping.js @@ -1,60 +1,27 @@ 'use strict' -const promisify = require('promisify-es6') -const pump = require('pump') -const Writable = require('readable-stream').Writable -const moduleConfig = require('./utils/module-config') -const PingMessageStream = require('./utils/ping-message-stream') - -module.exports = (arg) => { - const send = moduleConfig(arg) - - return promisify((id, opts, callback) => { - if (typeof opts === 'function') { - callback = opts - opts = {} - } - - if (opts.n && opts.count) { - return callback(new Error('Use either n or count, not both')) - } - - // Default number of packtes to 1 - if (!opts.n && !opts.count) { - opts.n = 1 +const ndjson = require('iterable-ndjson') +const configure = require('./lib/configure') +const toIterable = require('./lib/stream-to-iterable') +const toCamel = require('./lib/object-to-camel') + +module.exports = configure(({ ky }) => { + return async function * ping (peerId, options) { + options = options || {} + + const searchParams = new URLSearchParams(options.searchParams) + searchParams.set('arg', `${peerId}`) + if (options.count != null) searchParams.set('count', options.count) + + const res = await ky.post('ping', { + timeout: options.timeout, + signal: options.signal, + headers: options.headers, + searchParams + }) + + for await (const chunk of ndjson(toIterable(res.body))) { + yield toCamel(chunk) } - - const request = { - path: 'ping', - args: id, - qs: opts - } - - // Transform the response stream to a value: - // [{ success: , time: , text: }] - const transform = (stream, callback) => { - const messageConverter = new PingMessageStream() - const responses = [] - - pump( - stream, - messageConverter, - new Writable({ - objectMode: true, - write (chunk, enc, cb) { - responses.push(chunk) - cb() - } - }), - (err) => { - if (err) { - return callback(err) - } - callback(null, responses) - } - ) - } - - send.andTransform(request, transform, callback) - }) -} + } +}) diff --git a/src/pubsub/ls.js b/src/pubsub/ls.js index 177dcd491..d2bc8f68d 100644 --- a/src/pubsub/ls.js +++ b/src/pubsub/ls.js @@ -6,7 +6,7 @@ module.exports = configure(({ ky }) => { return async (options) => { options = options || {} - const { Strings } = await ky.get('pubsub/ls', { + const { Strings } = await ky.post('pubsub/ls', { timeout: options.timeout, signal: options.signal, headers: options.headers, diff --git a/src/pubsub/peers.js b/src/pubsub/peers.js index bdeca60e4..5fa5b2436 100644 --- a/src/pubsub/peers.js +++ b/src/pubsub/peers.js @@ -14,7 +14,7 @@ module.exports = configure(({ ky }) => { const searchParams = new URLSearchParams(options.searchParams) searchParams.set('arg', topic) - const { Strings } = await ky.get('pubsub/peers', { + const { Strings } = await ky.post('pubsub/peers', { timeout: options.timeout, signal: options.signal, headers: options.headers, diff --git a/src/refs/index.js b/src/refs/index.js index d86944eb2..b15f2cd0c 100644 --- a/src/refs/index.js +++ b/src/refs/index.js @@ -1,8 +1,8 @@ 'use strict' const configure = require('../lib/configure') -const cleanCID = require('../utils/clean-cid') -const IsIpfs = require('is-ipfs') +const { Buffer } = require('buffer') +const CID = require('cids') const ndjson = require('iterable-ndjson') const toIterable = require('../lib/stream-to-iterable') const toCamel = require('../lib/object-to-camel') @@ -38,19 +38,11 @@ module.exports = config => { args = [args] } - for (let arg of args) { - try { - arg = cleanCID(arg) - } catch (err) { - if (!IsIpfs.ipfsPath(arg)) { - throw err - } - } - - searchParams.append('arg', arg.toString()) + for (const arg of args) { + searchParams.append('arg', `${Buffer.isBuffer(arg) ? new CID(arg) : arg}`) } - const res = await ky.get('refs', { + const res = await ky.post('refs', { timeout: options.timeout, signal: options.signal, headers: options.headers, diff --git a/src/refs/local.js b/src/refs/local.js index efb8d32d2..afa1630ea 100644 --- a/src/refs/local.js +++ b/src/refs/local.js @@ -9,7 +9,7 @@ module.exports = configure(({ ky }) => { return async function * refsLocal (options) { options = options || {} - const res = await ky.get('refs/local', { + const res = await ky.post('refs/local', { timeout: options.timeout, signal: options.signal, headers: options.headers diff --git a/src/repo/gc.js b/src/repo/gc.js index 35d4288b0..3d92dee4c 100644 --- a/src/repo/gc.js +++ b/src/repo/gc.js @@ -1,33 +1,29 @@ 'use strict' -const promisify = require('promisify-es6') -const streamToValueWithTransformer = require('../utils/stream-to-value-with-transformer') const CID = require('cids') +const ndjson = require('iterable-ndjson') +const configure = require('../lib/configure') +const toIterable = require('../lib/stream-to-iterable') -const transform = function (res, callback) { - callback(null, res.map(r => ({ - err: r.Err ? new Error(r.Err) : null, - cid: (r.Key || {})['/'] ? new CID(r.Key['/']) : null - }))) -} +module.exports = configure(({ ky }) => { + return async function * gc (peerId, options) { + options = options || {} -module.exports = (send) => { - return promisify((opts, callback) => { - if (typeof (opts) === 'function') { - callback = opts - opts = {} - } - - const request = { - path: 'repo/gc', - qs: opts - } - send(request, (err, result) => { - if (err) { - return callback(err) - } + const searchParams = new URLSearchParams(options.searchParams) + if (options.streamErrors) searchParams.set('stream-errors', options.streamErrors) - streamToValueWithTransformer(result, transform, callback) + const res = await ky.post('repo/gc', { + timeout: options.timeout, + signal: options.signal, + headers: options.headers, + searchParams }) - }) -} + + for await (const gcResult of ndjson(toIterable(res.body))) { + yield { + err: gcResult.Error ? new Error(gcResult.Error) : null, + cid: (gcResult.Key || {})['/'] ? new CID(gcResult.Key['/']) : null + } + } + } +}) diff --git a/src/repo/index.js b/src/repo/index.js index d3ac72785..fe58504ad 100644 --- a/src/repo/index.js +++ b/src/repo/index.js @@ -1,13 +1,10 @@ 'use strict' -const moduleConfig = require('../utils/module-config') +const callbackify = require('callbackify') +const { collectify } = require('../lib/converters') -module.exports = (arg) => { - const send = moduleConfig(arg) - - return { - gc: require('./gc')(send), - stat: require('./stat')(send), - version: require('./version')(send) - } -} +module.exports = config => ({ + gc: callbackify.variadic(collectify(require('./gc')(config))), + stat: callbackify.variadic(require('./stat')(config)), + version: callbackify.variadic(require('./version')(config)) +}) diff --git a/src/repo/stat.js b/src/repo/stat.js index 2b922de03..17895e353 100644 --- a/src/repo/stat.js +++ b/src/repo/stat.js @@ -1,28 +1,28 @@ 'use strict' -const promisify = require('promisify-es6') const Big = require('bignumber.js') +const configure = require('../lib/configure') -const transform = function (res, callback) { - callback(null, { - numObjects: new Big(res.NumObjects), - repoSize: new Big(res.RepoSize), - repoPath: res.RepoPath, - version: res.Version, - storageMax: new Big(res.StorageMax) - }) -} +module.exports = configure(({ ky }) => { + return async options => { + options = options || {} -module.exports = (send) => { - return promisify((opts, callback) => { - if (typeof (opts) === 'function') { - callback = opts - opts = {} - } + const searchParams = new URLSearchParams(options.searchParams) + if (options.sizeOnly) searchParams.set('size-only', options.sizeOnly) + + const res = await ky.post('repo/stat', { + timeout: options.timeout, + signal: options.signal, + headers: options.headers, + searchParams + }).json() - send.andTransform({ - path: 'repo/stat', - qs: opts - }, transform, callback) - }) -} + return { + numObjects: new Big(res.NumObjects), + repoSize: new Big(res.RepoSize), + repoPath: res.RepoPath, + version: res.Version, + storageMax: new Big(res.StorageMax) + } + } +}) diff --git a/src/repo/version.js b/src/repo/version.js index 84e2a0008..1bfc708e0 100644 --- a/src/repo/version.js +++ b/src/repo/version.js @@ -1,21 +1,21 @@ 'use strict' -const promisify = require('promisify-es6') +const configure = require('../lib/configure') -const transform = function (res, callback) { - callback(null, res.Version) -} +module.exports = configure(({ ky }) => { + return async options => { + options = options || {} -module.exports = (send) => { - return promisify((opts, callback) => { - if (typeof (opts) === 'function') { - callback = opts - opts = {} - } + const searchParams = new URLSearchParams(options.searchParams) + if (options.sizeOnly) searchParams.set('size-only', options.sizeOnly) - send.andTransform({ - path: 'repo/version', - qs: opts - }, transform, callback) - }) -} + const res = await ky.post('repo/version', { + timeout: options.timeout, + signal: options.signal, + headers: options.headers, + searchParams + }).json() + + return res.Version + } +}) diff --git a/src/resolve.js b/src/resolve.js index f48a3b02b..33c44b6e6 100644 --- a/src/resolve.js +++ b/src/resolve.js @@ -1,54 +1,25 @@ 'use strict' -const promisify = require('promisify-es6') -const multibase = require('multibase') -const CID = require('cids') - -module.exports = (send) => { - return promisify((args, opts, callback) => { - if (typeof (opts) === 'function') { - callback = opts - opts = {} - } - - opts = opts || {} - - if (opts.cidBase) { - opts['cid-base'] = opts.cidBase - delete opts.cidBase - } - - const transform = (res, callback) => { - if (!opts['cid-base']) { - return callback(null, res.Path) - } - - // FIXME: remove when go-ipfs supports ?cid-base for /api/v0/resolve - // https://github.com/ipfs/go-ipfs/pull/5777#issuecomment-439838555 - const parts = res.Path.split('/') // ['', 'ipfs', 'QmHash', ...] - - if (multibase.isEncoded(parts[2]) !== opts['cid-base']) { - try { - let cid = new CID(parts[2]) - - if (cid.version === 0 && opts['cid-base'] !== 'base58btc') { - cid = cid.toV1() - } - - parts[2] = cid.toBaseEncodedString(opts['cid-base']) - res.Path = parts.join('/') - } catch (err) { - return callback(err) - } - } - - callback(null, res.Path) - } - - send.andTransform({ - path: 'resolve', - args: args, - qs: opts - }, transform, callback) - }) -} +const configure = require('./lib/configure') + +module.exports = configure(({ ky }) => { + return async (path, options) => { + options = options || {} + + const searchParams = new URLSearchParams(options.searchParams) + searchParams.set('arg', `${path}`) + if (options.cidBase) searchParams.set('cid-base', options.cidBase) + if (options.dhtRecordCount) searchParams.set('dht-record-count', options.dhtRecordCount) + if (options.dhtTimeout) searchParams.set('dht-timeout', options.dhtTimeout) + if (options.recursive != null) searchParams.set('recursive', options.recursive) + + const res = await ky.post('resolve', { + timeout: options.timeout, + signal: options.signal, + headers: options.headers, + searchParams + }).json() + + return res.Path + } +}) diff --git a/src/stats/bitswap.js b/src/stats/bitswap.js deleted file mode 100644 index 3f641f680..000000000 --- a/src/stats/bitswap.js +++ /dev/null @@ -1,32 +0,0 @@ -'use strict' - -const promisify = require('promisify-es6') -const Big = require('bignumber.js') - -const transform = function (res, callback) { - callback(null, { - provideBufLen: res.ProvideBufLen, - wantlist: res.Wantlist || [], - peers: res.Peers || [], - blocksReceived: new Big(res.BlocksReceived), - dataReceived: new Big(res.DataReceived), - blocksSent: new Big(res.BlocksSent), - dataSent: new Big(res.DataSent), - dupBlksReceived: new Big(res.DupBlksReceived), - dupDataReceived: new Big(res.DupDataReceived) - }) -} - -module.exports = (send) => { - return promisify((opts, callback) => { - if (typeof (opts) === 'function') { - callback = opts - opts = {} - } - - send.andTransform({ - path: 'stats/bitswap', - qs: opts - }, transform, callback) - }) -} diff --git a/src/stats/bw-pull-stream.js b/src/stats/bw-pull-stream.js deleted file mode 100644 index 26a4eb311..000000000 --- a/src/stats/bw-pull-stream.js +++ /dev/null @@ -1,31 +0,0 @@ -'use strict' - -const toPull = require('stream-to-pull-stream') -const map = require('pull-stream/throughs/map') -const pull = require('pull-stream/pull') -const transformChunk = require('./bw-util') -const deferred = require('pull-defer') - -module.exports = (send) => { - return (opts) => { - opts = opts || {} - - const p = deferred.source() - - send({ - path: 'stats/bw', - qs: opts - }, (err, stream) => { - if (err) { - return p.end(err) - } - - p.resolve(pull( - toPull.source(stream), - map(transformChunk) - )) - }) - - return p - } -} diff --git a/src/stats/bw-readable-stream.js b/src/stats/bw-readable-stream.js deleted file mode 100644 index c36fea518..000000000 --- a/src/stats/bw-readable-stream.js +++ /dev/null @@ -1,31 +0,0 @@ -'use strict' - -const Stream = require('readable-stream') -const pump = require('pump') -const transformChunk = require('./bw-util') - -module.exports = (send) => { - return (opts) => { - opts = opts || {} - - const pt = new Stream.Transform({ - objectMode: true, - transform (chunk, encoding, cb) { - cb(null, transformChunk(chunk)) - } - }) - - send({ - path: 'stats/bw', - qs: opts - }, (err, stream) => { - if (err) { - return pt.destroy(err) - } - - pump(stream, pt) - }) - - return pt - } -} diff --git a/src/stats/bw-util.js b/src/stats/bw-util.js deleted file mode 100644 index 928ee0c3c..000000000 --- a/src/stats/bw-util.js +++ /dev/null @@ -1,12 +0,0 @@ -'use strict' - -const Big = require('bignumber.js') - -module.exports = (chunk) => { - return { - totalIn: new Big(chunk.TotalIn), - totalOut: new Big(chunk.TotalOut), - rateIn: new Big(chunk.RateIn), - rateOut: new Big(chunk.RateOut) - } -} diff --git a/src/stats/bw.js b/src/stats/bw.js index 1db636a25..f68ad23ba 100644 --- a/src/stats/bw.js +++ b/src/stats/bw.js @@ -1,29 +1,34 @@ 'use strict' -const promisify = require('promisify-es6') -const streamToValue = require('../utils/stream-to-value') -const transformChunk = require('./bw-util') +const ndjson = require('iterable-ndjson') +const Big = require('bignumber.js') +const configure = require('../lib/configure') +const toIterable = require('../lib/stream-to-iterable') -const transform = (res, callback) => { - return streamToValue(res, (err, data) => { - if (err) { - return callback(err) - } +module.exports = configure(({ ky }) => { + return async function * bw (options) { + options = options || {} - callback(null, transformChunk(data[0])) - }) -} + const searchParams = new URLSearchParams(options.searchParams) + if (options.interval) searchParams.set('interval', options.interval) + if (options.peer) searchParams.set('peer', options.peer) + if (options.poll != null) searchParams.set('poll', options.poll) + if (options.proto) searchParams.set('proto', options.proto) -module.exports = (send) => { - return promisify((opts, callback) => { - if (typeof (opts) === 'function') { - callback = opts - opts = {} - } + const res = await ky.post('stats/bw', { + timeout: options.timeout, + signal: options.signal, + headers: options.headers, + searchParams + }) - send.andTransform({ - path: 'stats/bw', - qs: opts - }, transform, callback) - }) -} + for await (const stats of ndjson(toIterable(res.body))) { + yield { + totalIn: new Big(stats.TotalIn), + totalOut: new Big(stats.TotalOut), + rateIn: new Big(stats.RateIn), + rateOut: new Big(stats.RateOut) + } + } + } +}) diff --git a/src/stats/index.js b/src/stats/index.js index 445a39835..4351d79e2 100644 --- a/src/stats/index.js +++ b/src/stats/index.js @@ -1,15 +1,19 @@ 'use strict' -const moduleConfig = require('../utils/module-config') - -module.exports = (arg) => { - const send = moduleConfig(arg) +const callbackify = require('callbackify') +const { streamify, pullify } = require('../lib/converters') +module.exports = config => { + const bw = require('./bw')(config) return { - bitswap: require('./bitswap')(send), - bw: require('./bw')(send), - bwReadableStream: require('./bw-readable-stream')(send), - bwPullStream: require('./bw-pull-stream')(send), - repo: require('./repo')(send) + bitswap: callbackify.variadic(require('../bitswap/stat')(config)), + bw: callbackify.variadic(async options => { + for await (const stats of bw(options)) { + return stats + } + }), + bwReadableStream: streamify.readable(bw), + bwPullStream: pullify.source(bw), + repo: callbackify.variadic(require('../repo/stat')(config)) } } diff --git a/src/stats/repo.js b/src/stats/repo.js deleted file mode 100644 index 81f808951..000000000 --- a/src/stats/repo.js +++ /dev/null @@ -1,28 +0,0 @@ -'use strict' - -const promisify = require('promisify-es6') -const Big = require('bignumber.js') - -const transform = function (res, callback) { - callback(null, { - numObjects: new Big(res.NumObjects), - repoSize: new Big(res.RepoSize), - repoPath: res.RepoPath, - version: res.Version, - storageMax: new Big(res.StorageMax) - }) -} - -module.exports = (send) => { - return promisify((opts, callback) => { - if (typeof (opts) === 'function') { - callback = opts - opts = {} - } - - send.andTransform({ - path: 'stats/repo', - qs: opts - }, transform, callback) - }) -} diff --git a/src/stop.js b/src/stop.js index 0da69eaa1..7cae46880 100644 --- a/src/stop.js +++ b/src/stop.js @@ -1,12 +1,16 @@ 'use strict' -const promisify = require('promisify-es6') -const moduleConfig = require('./utils/module-config') +const configure = require('./lib/configure') -module.exports = (arg) => { - const send = moduleConfig(arg) +module.exports = configure(({ ky }) => { + return options => { + options = options || {} - return promisify((callback) => { - send({ path: 'shutdown' }, callback) - }) -} + return ky.post('shutdown', { + timeout: options.timeout, + signal: options.signal, + headers: options.headers, + searchParams: options.searchParams + }).text() + } +}) diff --git a/src/swarm/addrs.js b/src/swarm/addrs.js index 103df148b..a786d32cb 100644 --- a/src/swarm/addrs.js +++ b/src/swarm/addrs.js @@ -1,33 +1,25 @@ 'use strict' -const promisify = require('promisify-es6') const PeerInfo = require('peer-info') const PeerId = require('peer-id') const multiaddr = require('multiaddr') +const configure = require('../lib/configure') -module.exports = (send) => { - return promisify((opts, callback) => { - if (typeof (opts) === 'function') { - callback = opts - opts = {} - } - send({ - path: 'swarm/addrs', - qs: opts - }, (err, result) => { - if (err) { - return callback(err) - } +module.exports = configure(({ ky }) => { + return async options => { + options = options || {} - const peers = Object.keys(result.Addrs).map((id) => { - const peerInfo = new PeerInfo(PeerId.createFromB58String(id)) - result.Addrs[id].forEach((addr) => { - peerInfo.multiaddrs.add(multiaddr(addr)) - }) - return peerInfo - }) + const res = await ky.post('swarm/addrs', { + timeout: options.timeout, + signal: options.signal, + headers: options.headers, + searchParams: options.searchParams + }).json() - callback(null, peers) + return Object.keys(res.Addrs).map(id => { + const peerInfo = new PeerInfo(PeerId.createFromB58String(id)) + res.Addrs[id].forEach(addr => peerInfo.multiaddrs.add(multiaddr(addr))) + return peerInfo }) - }) -} + } +}) diff --git a/src/swarm/connect.js b/src/swarm/connect.js index 9875af411..f47ae6974 100644 --- a/src/swarm/connect.js +++ b/src/swarm/connect.js @@ -1,17 +1,22 @@ 'use strict' -const promisify = require('promisify-es6') +const configure = require('../lib/configure') -module.exports = (send) => { - return promisify((args, opts, callback) => { - if (typeof (opts) === 'function') { - callback = opts - opts = {} - } - send({ - path: 'swarm/connect', - args: args, - qs: opts - }, callback) - }) -} +module.exports = configure(({ ky }) => { + return async (addrs, options) => { + addrs = Array.isArray(addrs) ? addrs : [addrs] + options = options || {} + + const searchParams = new URLSearchParams(options.searchParams) + addrs.forEach(addr => searchParams.append('arg', addr)) + + const res = await ky.post('swarm/connect', { + timeout: options.timeout, + signal: options.signal, + headers: options.headers, + searchParams + }).json() + + return res.Strings || [] + } +}) diff --git a/src/swarm/disconnect.js b/src/swarm/disconnect.js index 84b800f7e..a3d60d172 100644 --- a/src/swarm/disconnect.js +++ b/src/swarm/disconnect.js @@ -1,17 +1,22 @@ 'use strict' -const promisify = require('promisify-es6') +const configure = require('../lib/configure') -module.exports = (send) => { - return promisify((args, opts, callback) => { - if (typeof (opts) === 'function') { - callback = opts - opts = {} - } - send({ - path: 'swarm/disconnect', - args: args, - qs: opts - }, callback) - }) -} +module.exports = configure(({ ky }) => { + return async (addrs, options) => { + addrs = Array.isArray(addrs) ? addrs : [addrs] + options = options || {} + + const searchParams = new URLSearchParams(options.searchParams) + addrs.forEach(addr => searchParams.append('arg', addr)) + + const res = await ky.post('swarm/disconnect', { + timeout: options.timeout, + signal: options.signal, + headers: options.headers, + searchParams + }).json() + + return res.Strings || [] + } +}) diff --git a/src/swarm/index.js b/src/swarm/index.js index fe8c88b35..e86a7c22c 100644 --- a/src/swarm/index.js +++ b/src/swarm/index.js @@ -1,15 +1,11 @@ 'use strict' -const moduleConfig = require('../utils/module-config') +const callbackify = require('callbackify') -module.exports = (arg) => { - const send = moduleConfig(arg) - - return { - peers: require('./peers')(send), - connect: require('./connect')(send), - disconnect: require('./disconnect')(send), - addrs: require('./addrs')(send), - localAddrs: require('./localAddrs')(send) - } -} +module.exports = config => ({ + addrs: callbackify.variadic(require('./addrs')(config)), + connect: callbackify.variadic(require('./connect')(config)), + disconnect: callbackify.variadic(require('./disconnect')(config)), + localAddrs: callbackify.variadic(require('./localAddrs')(config)), + peers: callbackify.variadic(require('./peers')(config)) +}) diff --git a/src/swarm/localAddrs.js b/src/swarm/localAddrs.js index 4798aad52..41c32db2d 100644 --- a/src/swarm/localAddrs.js +++ b/src/swarm/localAddrs.js @@ -1,24 +1,22 @@ 'use strict' -const promisify = require('promisify-es6') const multiaddr = require('multiaddr') +const configure = require('../lib/configure') -module.exports = (send) => { - return promisify((opts, callback) => { - if (typeof (opts) === 'function') { - callback = opts - opts = {} - } - send({ - path: 'swarm/addrs/local', - qs: opts - }, (err, result) => { - if (err) { - return callback(err) - } - callback(null, result.Strings.map((addr) => { - return multiaddr(addr) - })) - }) - }) -} +module.exports = configure(({ ky }) => { + return async options => { + options = options || {} + + const searchParams = new URLSearchParams(options.searchParams) + if (options.id != null) searchParams.append('id', options.id) + + const res = await ky.post('swarm/addrs/local', { + timeout: options.timeout, + signal: options.signal, + headers: options.headers, + searchParams + }).json() + + return (res.Strings || []).map(a => multiaddr(a)) + } +}) diff --git a/src/swarm/peers.js b/src/swarm/peers.js index 37d11cd7e..3b897348c 100644 --- a/src/swarm/peers.js +++ b/src/swarm/peers.js @@ -1,74 +1,48 @@ 'use strict' -const promisify = require('promisify-es6') const multiaddr = require('multiaddr') const PeerId = require('peer-id') +const configure = require('../lib/configure') -module.exports = (send) => { - return promisify((opts, callback) => { - if (typeof (opts) === 'function') { - callback = opts - opts = {} - } - const verbose = opts.v || opts.verbose - send({ - path: 'swarm/peers', - qs: opts - }, (err, response) => { - if (err) { - return callback(err) - } - const peerInfo = parsePeersResponse(verbose, response) - callback(null, peerInfo) - }) - }) -} +module.exports = configure(({ ky }) => { + return async options => { + options = options || {} -function parsePeersResponse (verbose, response) { - // go-ipfs <= 0.4.4 - if (Array.isArray(response.Strings)) { - return response.Strings.map(parseLegacyPeer.bind(null, verbose)) - } - // go-ipfs >= 0.4.5 - if (Array.isArray(response.Peers)) { - return response.Peers.map(parsePeer.bind(null, verbose)) - } - return [] -} + const searchParams = new URLSearchParams(options.searchParams) + if (options.direction != null) searchParams.append('direction', options.direction) + if (options.latency != null) searchParams.append('latency', options.latency) + if (options.streams != null) searchParams.append('streams', options.streams) + if (options.verbose != null) searchParams.append('verbose', options.verbose) -function parseLegacyPeer (verbose, peer) { - const res = {} - try { - if (verbose) { - const parts = peer.split(' ') - res.addr = multiaddr(parts[0]) - res.latency = parts[1] - } else { - res.addr = multiaddr(peer) - } - res.peer = PeerId.createFromB58String(res.addr.getPeerId()) - } catch (error) { - res.error = error - res.rawPeerInfo = peer - } - return res -} + const res = await ky.post('swarm/peers', { + timeout: options.timeout, + signal: options.signal, + headers: options.headers, + searchParams + }).json() -function parsePeer (verbose, peer) { - const res = {} - try { - res.addr = multiaddr(peer.Addr) - res.peer = PeerId.createFromB58String(peer.Peer) - res.muxer = peer.Muxer - } catch (error) { - res.error = error - res.rawPeerInfo = peer - } - if (peer.Latency) { - res.latency = peer.Latency - } - if (peer.Streams) { - res.streams = peer.Streams + return (res.Peers || []).map(peer => { + const info = {} + try { + info.addr = multiaddr(peer.Addr) + info.peer = PeerId.createFromB58String(peer.Peer) + } catch (error) { + info.error = error + info.rawPeerInfo = peer + } + if (peer.Muxer) { + info.muxer = peer.Muxer + } + if (peer.Latency) { + info.latency = peer.Latency + } + if (peer.Streams) { + info.streams = peer.Streams + } + if (peer.Direction != null) { + info.direction = peer.Direction + } + return info + }) } - return res -} +}) diff --git a/src/update.js b/src/update.js index aee1a64a6..91bea6f7f 100644 --- a/src/update.js +++ b/src/update.js @@ -1,41 +1,16 @@ 'use strict' -const promisify = require('promisify-es6') -const moduleConfig = require('./utils/module-config') +const configure = require('./lib/configure') -module.exports = (arg) => { - const send = moduleConfig(arg) +module.exports = configure(({ ky }) => { + return options => { + options = options || {} - return { - apply: promisify((opts, callback) => { - if (typeof (opts) === 'function') { - callback = opts - opts = {} - } - send({ - path: 'update', - qs: opts - }, callback) - }), - check: promisify((opts, callback) => { - if (typeof (opts) === 'function') { - callback = opts - opts = {} - } - send({ - path: 'update/check', - qs: opts - }, callback) - }), - log: promisify((opts, callback) => { - if (typeof (opts) === 'function') { - callback = opts - opts = {} - } - send({ - path: 'update/log', - qs: opts - }, callback) - }) + return ky.post('update', { + timeout: options.timeout, + signal: options.signal, + headers: options.headers, + searchParams: options.searchParams + }).text() } -} +}) diff --git a/src/utils/clean-cid.js b/src/utils/clean-cid.js deleted file mode 100644 index 1767c9ac2..000000000 --- a/src/utils/clean-cid.js +++ /dev/null @@ -1,17 +0,0 @@ -'use strict' - -const CID = require('cids') - -module.exports = function (cid) { - if (Buffer.isBuffer(cid)) { - return new CID(cid).toString() - } - if (CID.isCID(cid)) { - return cid.toString() - } - if (typeof cid !== 'string') { - throw new Error('unexpected cid type: ' + typeof cid) - } - new CID(cid.split('/')[0]) // eslint-disable-line no-new - return cid -} diff --git a/src/utils/clean-multihash.js b/src/utils/clean-multihash.js deleted file mode 100644 index 230135ad7..000000000 --- a/src/utils/clean-multihash.js +++ /dev/null @@ -1,21 +0,0 @@ -'use strict' - -const bs58 = require('bs58') -const CID = require('cids') -const isIPFS = require('is-ipfs') - -module.exports = function (multihash) { - if (Buffer.isBuffer(multihash)) { - multihash = bs58.encode(multihash) - } - if (CID.isCID(multihash)) { - multihash = multihash.toBaseEncodedString() - } - if (typeof multihash !== 'string') { - throw new Error('unexpected multihash type: ' + typeof multihash) - } - if (!isIPFS.multihash(multihash.split('/')[0])) { - throw new Error('not valid multihash') - } - return multihash -} diff --git a/src/utils/default-config.js b/src/utils/default-config.js deleted file mode 100644 index 5ae6ae82e..000000000 --- a/src/utils/default-config.js +++ /dev/null @@ -1,13 +0,0 @@ -'use strict' - -const pkg = require('../../package.json') - -exports = module.exports = () => { - return { - 'api-path': '/api/v0/', - 'user-agent': `/node-${pkg.name}/${pkg.version}/`, - host: 'localhost', - port: '5001', - protocol: 'http' - } -} diff --git a/src/utils/load-commands.js b/src/utils/load-commands.js deleted file mode 100644 index a4a6dcd07..000000000 --- a/src/utils/load-commands.js +++ /dev/null @@ -1,161 +0,0 @@ -'use strict' - -const nodeify = require('promise-nodeify') -const callbackify = require('callbackify') -const all = require('async-iterator-all') -const { concatify, collectify, pullify, streamify } = require('../lib/converters') -const toPullStream = require('async-iterator-to-pull-stream') -const pull = require('pull-stream/pull') -const map = require('pull-stream/throughs/map') -const toStream = require('it-to-stream') -const BufferList = require('bl/BufferList') - -function requireCommands (send, config) { - const add = require('../add')(config) - const addFromFs = require('../add-from-fs')(config) - const addFromURL = require('../add-from-url')(config) - const cat = require('../cat')(config) - const get = require('../get')(config) - const ls = require('../ls')(config) - const refs = require('../refs')(config) - - const cmds = { - add: (input, options, callback) => { - if (typeof options === 'function') { - callback = options - options = {} - } - return nodeify(collectify(add)(input, options), callback) - }, - addReadableStream: streamify.transform(add), - addPullStream: pullify.transform(add), - addFromFs: (path, options, callback) => { - if (typeof options === 'function') { - callback = options - options = {} - } - return nodeify(collectify(addFromFs)(path, options), callback) - }, - addFromURL: (url, options, callback) => { - if (typeof options === 'function') { - callback = options - options = {} - } - return nodeify(collectify(addFromURL)(url, options), callback) - }, - addFromStream: (input, options, callback) => { - if (typeof options === 'function') { - callback = options - options = {} - } - return nodeify(collectify(add)(input, options), callback) - }, - _addAsyncIterator: add, - cat: callbackify.variadic((path, options) => concatify(cat)(path, options)), - catReadableStream: streamify.readable(cat), - catPullStream: pullify.source(cat), - _catAsyncIterator: cat, - get: callbackify.variadic(async (path, options) => { - const output = [] - - for await (const entry of get(path, options)) { - if (entry.content) { - entry.content = new BufferList(await all(entry.content)).slice() - } - - output.push(entry) - } - - return output - }), - getReadableStream: streamify.readable((path, options) => (async function * () { - for await (const file of get(path, options)) { - if (file.content) { - const { content } = file - file.content = toStream((async function * () { - for await (const chunk of content) { - yield chunk.slice() // Convert bl to Buffer - } - })()) - } - - yield file - } - })()), - getPullStream: (path, options) => { - return pull( - toPullStream(get(path, options)), - map(file => { - if (file.content) { - file.content = pull( - toPullStream(file.content), - map(chunk => chunk.slice()) // Convert bl to Buffer - ) - } - - return file - }) - ) - }, - _getAsyncIterator: get, - ls: callbackify.variadic((path, options) => collectify(ls)(path, options)), - lsReadableStream: streamify.readable(ls), - lsPullStream: pullify.source(ls), - _lsAsyncIterator: ls, - object: require('../object')(config), - refs: callbackify.variadic((path, options) => collectify(refs)(path, options)), - refsReadableStream: streamify.readable(refs), - refsPullStream: pullify.source(refs), - _refsAsyncIterator: refs, - getEndpointConfig: require('../get-endpoint-config')(config), - bitswap: require('../bitswap')(config), - block: require('../block')(config), - bootstrap: require('../bootstrap')(config), - config: require('../config')(config), - dag: require('../dag')(config), - dht: require('../dht')(config), - diag: require('../diag')(config), - files: require('../files')(config), - pin: require('../pin')(config) - } - - Object.assign(cmds.refs, { - local: callbackify.variadic(options => collectify(refs.local)(options)), - localReadableStream: streamify.readable(refs.local), - localPullStream: pullify.source(refs.local), - _localAsyncIterator: refs.local - }) - - const subCmds = { - // Network - name: require('../name'), - ping: require('../ping'), - pingReadableStream: require('../ping-readable-stream'), - pingPullStream: require('../ping-pull-stream'), - swarm: require('../swarm'), - pubsub: require('../pubsub'), - dns: require('../dns'), - - // Miscellaneous - commands: require('../commands'), - id: require('../id'), - key: require('../key'), - log: require('../log'), - mount: require('../mount'), - repo: require('../repo'), - stop: require('../stop'), - shutdown: require('../stop'), - stats: require('../stats'), - update: require('../update'), - version: require('../version'), - resolve: require('../resolve') - } - - Object.keys(subCmds).forEach((file) => { - cmds[file] = subCmds[file](send, config) - }) - - return cmds -} - -module.exports = requireCommands diff --git a/src/utils/module-config.js b/src/utils/module-config.js deleted file mode 100644 index 4e1b0e6a1..000000000 --- a/src/utils/module-config.js +++ /dev/null @@ -1,22 +0,0 @@ -'use strict' - -const getConfig = require('./default-config') -const sendRequest = require('./send-request') -const multiaddr = require('multiaddr') - -module.exports = (arg) => { - const config = getConfig() - - if (typeof arg === 'function') { - return arg - } else if (typeof arg === 'object') { - return sendRequest(arg) - } else if (typeof arg === 'string') { - const maddr = multiaddr(arg).nodeAddress() - config.host = maddr.address - config.port = maddr.port - return sendRequest(config) - } else { - throw new Error('Argument must be a send function or a config object.') - } -} diff --git a/src/utils/multipart.js b/src/utils/multipart.js deleted file mode 100644 index 78bead247..000000000 --- a/src/utils/multipart.js +++ /dev/null @@ -1,121 +0,0 @@ -'use strict' - -const Transform = require('readable-stream').Transform -const isNode = require('detect-node') - -const PADDING = '--' -const NEW_LINE = '\r\n' -const NEW_LINE_BUFFER = Buffer.from(NEW_LINE) - -class Multipart extends Transform { - constructor (options) { - super(Object.assign({}, options, { objectMode: true, highWaterMark: 1 })) - - this._boundary = this._generateBoundary() - this._files = [] - this._draining = false - } - - _flush () { - this.push(Buffer.from(PADDING + this._boundary + PADDING + NEW_LINE)) - this.push(null) - } - - _generateBoundary () { - var boundary = '--------------------------' - for (var i = 0; i < 24; i++) { - boundary += Math.floor(Math.random() * 10).toString(16) - } - - return boundary - } - - _transform (file, encoding, callback) { - if (Buffer.isBuffer(file)) { - this.push(file) - return callback() // early - } - // not a buffer, must be a file - this._files.push(file) - this._maybeDrain(callback) - } - - _maybeDrain (callback) { - if (!this._draining) { - if (this._files.length) { - this._draining = true - const file = this._files.shift() - this._pushFile(file, (err) => { - this._draining = false - if (err) { - this.emit('error', err) - } else { - this._maybeDrain(callback) - } - }) - } else { - this.emit('drained all files') - callback() - } - } else { - this.once('drained all files', callback) - } - } - - _pushFile (file, callback) { - const leading = this._leading(file.headers || {}) - - this.push(leading) - - const content = file.content || Buffer.alloc(0) - - if (Buffer.isBuffer(content)) { - this.push(content) - this.push(NEW_LINE_BUFFER) - return callback() // early - } - - // From now on we assume content is a stream - content.once('error', this.emit.bind(this, 'error')) - - content.once('end', () => { - this.push(NEW_LINE_BUFFER) - callback() - - // TODO: backpressure!!! wait once self is drained so we can proceed - // This does not work - // this.once('drain', () => { - // callback() - // }) - }) - - content.on('data', (data) => { - const drained = this.push(data) - // Only do the drain dance on Node.js. - // In browserland, the underlying stream - // does NOT drain because the request is only sent - // once this stream ends. - if (!drained && isNode) { - content.pause() - this.once('drain', () => content.resume()) - } - }) - } - - _leading (headers) { - var leading = [PADDING + this._boundary] - - Object.keys(headers).forEach((header) => { - leading.push(header + ': ' + headers[header]) - }) - - leading.push('') - leading.push('') - - const leadingStr = leading.join(NEW_LINE) - - return Buffer.from(leadingStr) - } -} - -module.exports = Multipart diff --git a/src/utils/ping-message-converter.js b/src/utils/ping-message-converter.js deleted file mode 100644 index 79d9fc3be..000000000 --- a/src/utils/ping-message-converter.js +++ /dev/null @@ -1,23 +0,0 @@ -'use strict' - -// Converts IPFS API ping messages to lowercase -// -// { -// Success: true, -// Text: 'foobar', -// Time: 0 -// } -// - -module.exports = function pingMessageConverter (obj) { - if (!isPingMessage(obj)) throw new Error('Invalid ping message received') - return { - success: obj.Success, - time: obj.Time, - text: obj.Text - } -} - -function isPingMessage (obj) { - return obj && typeof obj.Success === 'boolean' -} diff --git a/src/utils/ping-message-stream.js b/src/utils/ping-message-stream.js deleted file mode 100644 index 944e2d9cf..000000000 --- a/src/utils/ping-message-stream.js +++ /dev/null @@ -1,27 +0,0 @@ -'use strict' - -const TransformStream = require('readable-stream').Transform -const pingMessageConverter = require('./ping-message-converter') - -class PingMessageStream extends TransformStream { - constructor (options) { - const opts = Object.assign(options || {}, { objectMode: true }) - super(opts) - } - - _transform (obj, enc, callback) { - try { - const msg = pingMessageConverter(obj) - this.push(msg) - - if (!msg.success) { - throw new Error(msg.text) - } - } catch (err) { - return callback(err) - } - callback() - } -} - -module.exports = PingMessageStream diff --git a/src/utils/prepare-file.js b/src/utils/prepare-file.js deleted file mode 100644 index 9a02f8338..000000000 --- a/src/utils/prepare-file.js +++ /dev/null @@ -1,153 +0,0 @@ -'use strict' - -const isNode = require('detect-node') -const flatmap = require('flatmap') -const { Readable } = require('readable-stream') -const kindOf = require('kind-of') -const { isSource } = require('is-pull-stream') -const isStream = require('is-stream') -const pullToStream = require('pull-to-stream') -const { supportsFileReader } = require('ipfs-utils/src/supports') -const streamFromFileReader = require('ipfs-utils/src/streams/stream-from-filereader') - -function loadPaths (opts, file) { - const path = require('path') - const fs = require('fs') - const glob = require('glob') - - const followSymlinks = opts.followSymlinks != null ? opts.followSymlinks : true - - file = path.resolve(file) - const stats = fs.statSync(file) - - if (stats.isDirectory() && !opts.recursive) { - throw new Error('Can only add directories using --recursive') - } - - if (stats.isDirectory() && opts.recursive) { - // glob requires a POSIX filename - file = file.split(path.sep).join('/') - const fullDir = file + (file.endsWith('/') ? '' : '/') - let dirName = fullDir.split('/') - dirName = dirName[dirName.length - 2] + '/' - const mg = new glob.sync.GlobSync('**/*', { - cwd: file, - follow: followSymlinks, - dot: opts.hidden, - ignore: opts.ignore - }) - - return mg.found - .map((name) => { - const fqn = fullDir + name - // symlinks - if (mg.symlinks[fqn] === true) { - return { - path: dirName + name, - symlink: true, - dir: false, - content: fs.readlinkSync(fqn) - } - } - - // files - if (mg.cache[fqn] === 'FILE') { - return { - path: dirName + name, - symlink: false, - dir: false, - content: fs.createReadStream(fqn) - } - } - - // directories - if (mg.cache[fqn] === 'DIR' || mg.cache[fqn] instanceof Array) { - return { - path: dirName + name, - symlink: false, - dir: true - } - } - // files inside symlinks and others - }) - // filter out null files - .filter(Boolean) - } - - return { - path: path.basename(file), - content: fs.createReadStream(file) - } -} - -function contentToStream (content) { - if (supportsFileReader && kindOf(content) === 'file') { - return streamFromFileReader(content) - } - - if (kindOf(content) === 'buffer') { - return new Readable({ - read () { - this.push(content) - this.push(null) - } - }) - } - - if (isSource(content)) { - return pullToStream.readable(content) - } - - if (isStream.readable(content)) { - return content - } - - throw new Error(`Input not supported. Expected Buffer|ReadableStream|PullStream|File got ${kindOf(content)}. Check the documentation for more info https://github.com/ipfs/interface-js-ipfs-core/blob/master/SPEC/FILES.md#add`) -} - -function prepareFile (file, opts) { - const files = [].concat(file) - - return flatmap(files, (file) => { - // add from fs with file path - if (typeof file === 'string') { - if (!isNode) { - throw new Error('Can only add file paths in node') - } - - return loadPaths(opts, file) - } - - // add with object syntax { path : , content: {}) - } - - static fromStream (track, stream) { - const prog = new ProgressStream({ track }) - return stream.pipe(prog) - } - - _transform (chunk, encoding, callback) { - if (chunk && - typeof chunk.Bytes !== 'undefined' && - typeof chunk.Hash === 'undefined') { - this._track(chunk.Bytes) - return callback() - } - - callback(null, chunk) - } -} - -module.exports = ProgressStream diff --git a/src/utils/send-files-stream.js b/src/utils/send-files-stream.js deleted file mode 100644 index 09c55d376..000000000 --- a/src/utils/send-files-stream.js +++ /dev/null @@ -1,161 +0,0 @@ -'use strict' - -const { Duplex } = require('readable-stream') -const eachSeries = require('async/eachSeries') -const isStream = require('is-stream') -const once = require('once') -const prepareFile = require('./prepare-file') -const Multipart = require('./multipart') - -function headers (file, i) { - const filename = file.path - ? encodeURIComponent(file.path) - : '' - - const header = { 'Content-Disposition': `form-data; name="data${i}"; filename="${filename}"` } - - if (!file.content) { - header['Content-Type'] = 'application/x-directory' - } else if (file.symlink) { - header['Content-Type'] = 'application/symlink' - } else { - header['Content-Type'] = 'application/octet-stream' - } - - return header -} - -module.exports = (send, path) => { - return (options) => { - let ended = false - let writing = false - - options = options ? Object.assign({}, options, options.qs) : {} - - const multipart = new Multipart() - - const retStream = new Duplex({ objectMode: true }) - - retStream._read = (n) => {} - - retStream._write = (file, enc, _next) => { - const next = once(_next) - try { - const files = prepareFile(file, options) - .map((file, i) => Object.assign({ headers: headers(file, i) }, file)) - - writing = true - eachSeries( - files, - (file, cb) => multipart.write(file, enc, cb), - (err) => { - writing = false - if (err) { - return next(err) - } - if (ended) { - multipart.end() - } - next() - }) - } catch (err) { - next(err) - } - } - - retStream.once('finish', () => { - if (!ended) { - ended = true - if (!writing) { - multipart.end() - } - } - }) - - const qs = options.qs || {} - - qs['cid-version'] = propOrProp(options, 'cid-version', 'cidVersion') - qs['raw-leaves'] = propOrProp(options, 'raw-leaves', 'rawLeaves') - qs['only-hash'] = propOrProp(options, 'only-hash', 'onlyHash') - qs['wrap-with-directory'] = propOrProp(options, 'wrap-with-directory', 'wrapWithDirectory') - qs.pin = propOrProp(options, 'pin') - qs.preload = propOrProp(options, 'preload') - qs.hash = propOrProp(options, 'hash', 'hashAlg') - - if (options.strategy === 'trickle' || options.trickle) { - qs.trickle = 'true' - } - - const args = { - path: path, - qs: qs, - args: options.args, - multipart: true, - multipartBoundary: multipart._boundary, - stream: true, - recursive: true, - progress: options.progress - } - - multipart.on('error', (err) => { - retStream.emit('error', err) - }) - - const request = send(args, (err, response) => { - if (err) { - return retStream.emit('error', err) - } - - if (!response) { - // no response, which means everything is ok, so we end the retStream - return retStream.push(null) // early - } - - if (!isStream(response)) { - retStream.push(response) - retStream.push(null) - return - } - - response.on('error', (err) => retStream.emit('error', err)) - - if (options.converter) { - response.on('data', (d) => { - if (d.Bytes && options.progress) { - options.progress(d.Bytes) - } - }) - - const Converter = options.converter - const convertedResponse = new Converter() - convertedResponse.once('end', () => retStream.push(null)) - convertedResponse.on('data', (d) => retStream.push(d)) - response.pipe(convertedResponse) - } else { - response.on('data', (d) => { - if (d.Bytes && options.progress) { - options.progress(d.Bytes) - } - retStream.push(d) - }) - response.once('end', () => retStream.push(null)) - } - }) - - // signal the multipart that the underlying stream has drained and that - // it can continue producing data.. - request.on('drain', () => multipart.emit('drain')) - - multipart.pipe(request) - - return retStream - } -} - -function propOrProp (source, prop1, prop2) { - if (prop1 in source) { - return source[prop1] - } else if (prop2 in source) { - return source[prop2] - } -} diff --git a/src/utils/send-one-file-multiple-results.js b/src/utils/send-one-file-multiple-results.js deleted file mode 100644 index 180a9ad34..000000000 --- a/src/utils/send-one-file-multiple-results.js +++ /dev/null @@ -1,18 +0,0 @@ -'use strict' - -const once = require('once') -const ConcatStream = require('concat-stream') -const SendFilesStream = require('./send-files-stream') - -module.exports = (send, path) => { - const sendFilesStream = SendFilesStream(send, path) - return (file, options, _callback) => { - const callback = once(_callback) - const stream = sendFilesStream(options) - const concat = ConcatStream((results) => callback(null, results)) - stream.once('error', callback) - stream.pipe(concat) - stream.write(file) - stream.end() - } -} diff --git a/src/utils/send-one-file.js b/src/utils/send-one-file.js deleted file mode 100644 index 7b510f19d..000000000 --- a/src/utils/send-one-file.js +++ /dev/null @@ -1,15 +0,0 @@ -'use strict' - -const SendOneFileMultipleResults = require('./send-one-file-multiple-results') - -module.exports = (send, path) => { - const sendFile = SendOneFileMultipleResults(send, path) - return (file, options, callback) => { - sendFile(file, options, (err, results) => { - if (err) { - return callback(err) - } - callback(null, results[0]) - }) - } -} diff --git a/src/utils/send-request.js b/src/utils/send-request.js deleted file mode 100644 index 1645969f2..000000000 --- a/src/utils/send-request.js +++ /dev/null @@ -1,239 +0,0 @@ -'use strict' - -const Qs = require('qs') -const qsDefaultEncoder = require('qs/lib/utils').encode -const isNode = require('detect-node') -const ndjson = require('ndjson') -const pump = require('pump') -const once = require('once') -const { getRequest } = require('iso-stream-http') -const streamToValue = require('./stream-to-value') -const streamToJsonValue = require('./stream-to-json-value') -const log = require('debug')('ipfs-http-client:request') - -// -- Internal - -function hasJSONHeaders (res) { - return res.headers['content-type'] && - res.headers['content-type'].indexOf('application/json') === 0 -} - -function parseError (res, cb) { - const error = new Error(`Server responded with ${res.statusCode}`) - error.statusCode = res.statusCode - - if (!hasJSONHeaders(res)) { - return streamToValue(res, (err, data) => { // eslint-disable-line handle-callback-err - // the `err` here refers to errors in stream processing, which - // we ignore here, since we already have a valid `error` response - // from the server above that we have to report to the caller. - if (data && data.length) { - error.message = data.toString() - } - cb(error) - }) - } - - streamToJsonValue(res, (err, payload) => { - if (err) { - return cb(err) - } - - if (payload) { - error.code = payload.Code - error.message = payload.Message || payload.toString() - error.type = payload.Type - } - cb(error) - }) -} - -function onRes (buffer, cb) { - return (res) => { - const stream = Boolean(res.headers['x-stream-output']) - const chunkedObjects = Boolean(res.headers['x-chunked-output']) - const isJson = hasJSONHeaders(res) - - if (res.req) { - log(res.req.method, `${res.req.getHeaders().host}${res.req.path}`, res.statusCode, res.statusMessage) - } else { - log(res.url, res.statusCode, res.statusMessage) - } - - if (res.statusCode >= 400 || !res.statusCode) { - return parseError(res, cb) - } - - // Return the response stream directly - if (stream && !buffer) { - return cb(null, res) - } - - // Return a stream of JSON objects - if (chunkedObjects && isJson) { - const outputStream = ndjson.parse() - pump(res, outputStream) - res.on('end', () => { - let err = res.trailers['x-stream-error'] - if (err) { - // Not all errors are JSON - try { - err = JSON.parse(err) - } catch (e) { - err = { Message: err } - } - outputStream.emit('error', new Error(err.Message)) - } - }) - return cb(null, outputStream) - } - - // Return a JSON object - if (isJson) { - return streamToJsonValue(res, cb) - } - - // Return a value - return streamToValue(res, cb) - } -} - -function requestAPI (config, options, callback) { - callback = once(callback) - options.qs = options.qs || {} - - if (Array.isArray(options.path)) { - options.path = options.path.join('/') - } - if (options.args && !Array.isArray(options.args)) { - options.args = [options.args] - } - if (options.args) { - options.qs.arg = options.args - } - if (options.progress) { - options.qs.progress = true - } - - if (options.qs.r) { - options.qs.recursive = options.qs.r - // From IPFS 0.4.0, it throws an error when both r and recursive are passed - delete options.qs.r - } - - options.qs['stream-channels'] = true - - if (options.stream) { - options.buffer = false - } - - // this option is only used internally, not passed to daemon - delete options.qs.followSymlinks - - const method = 'POST' - const headers = Object.assign({}, config.headers) - - if (isNode) { - // Browsers do not allow you to modify the user agent - headers['User-Agent'] = config['user-agent'] - } - - if (options.multipart) { - if (!options.multipartBoundary) { - return callback(new Error('No multipartBoundary')) - } - - headers['Content-Type'] = `multipart/form-data; boundary=${options.multipartBoundary}` - } - - const qs = Qs.stringify(options.qs, { - arrayFormat: 'repeat', - encoder: data => { - // TODO: future releases of qs will provide the default - // encoder as a 2nd argument to this function; it will - // no longer be necessary to import qsDefaultEncoder - if (Buffer.isBuffer(data)) { - let uriEncoded = '' - for (const byte of data) { - // https://tools.ietf.org/html/rfc3986#page-14 - // ALPHA (%41-%5A and %61-%7A), DIGIT (%30-%39), hyphen (%2D), period (%2E), underscore (%5F), or tilde (%7E) - if ( - (byte >= 0x41 && byte <= 0x5A) || - (byte >= 0x61 && byte <= 0x7A) || - (byte >= 0x30 && byte <= 0x39) || - (byte === 0x2D) || - (byte === 0x2E) || - (byte === 0x5F) || - (byte === 0x7E) - ) { - uriEncoded += String.fromCharCode(byte) - } else { - const hex = byte.toString(16) - // String.prototype.padStart() not widely supported yet - const padded = hex.length === 1 ? `0${hex}` : hex - uriEncoded += `%${padded}` - } - } - return uriEncoded - } - return qsDefaultEncoder(data) - } - }) - const reqOptions = { - hostname: config.host, - path: `${config['api-path']}${options.path}?${qs}`, - port: config.port, - method: method, - headers: headers, - protocol: `${config.protocol}:` - } - - const req = getRequest(reqOptions, onRes(options.buffer, callback)) - - req.on('error', (err) => { - callback(err) - }) - - if (!options.stream) { - req.end() - } - - return req -} - -// -// -- Module Interface - -exports = module.exports = (config) => { - /* - * options: { - * path: // API path (like /add or /config) - type: string - * args: // Arguments to the command - type: object - * qs: // Opts as query string opts to the command --something - type: object - * files: // files to be sent - type: string, buffer or array of strings or buffers - * buffer: // buffer the request before sending it - type: bool - * } - */ - const send = (options, callback) => { - if (typeof options !== 'object') { - return callback(new Error('no options were passed')) - } - - return requestAPI(config, options, callback) - } - - // Send a HTTP request and pass via a transform function - // to convert the response data to wanted format before - // returning it to the callback. - // Eg. send.andTransform({}, (e) => JSON.parse(e), (err, res) => ...) - send.andTransform = (options, transform, callback) => { - return send(options, (err, res) => { - if (err) { - return callback(err) - } - transform(res, callback) - }) - } - - return send -} diff --git a/src/utils/stream-to-json-value.js b/src/utils/stream-to-json-value.js deleted file mode 100644 index 2ae83e50d..000000000 --- a/src/utils/stream-to-json-value.js +++ /dev/null @@ -1,34 +0,0 @@ -'use strict' - -const streamToValue = require('./stream-to-value') - -/* - Converts a stream to a single JSON value -*/ -function streamToJsonValue (res, cb) { - streamToValue(res, (err, data) => { - if (err) { - return cb(err) - } - - if (!data || data.length === 0) { - return cb() - } - - // TODO: check if needed, afaik JSON.parse can parse Buffers - if (Buffer.isBuffer(data)) { - data = data.toString() - } - - let res - try { - res = JSON.parse(data) - } catch (err) { - return cb(new Error(`Invalid JSON: ${data}`)) - } - - cb(null, res) - }) -} - -module.exports = streamToJsonValue diff --git a/src/utils/stream-to-value-with-transformer.js b/src/utils/stream-to-value-with-transformer.js deleted file mode 100644 index 402148667..000000000 --- a/src/utils/stream-to-value-with-transformer.js +++ /dev/null @@ -1,18 +0,0 @@ -'use strict' - -const streamToValue = require('./stream-to-value') - -function streamToValueWithTransformer (response, transformer, callback) { - if (typeof response.pipe === 'function') { - streamToValue(response, (err, res) => { - if (err) { - return callback(err) - } - transformer(res, callback) - }) - } else { - transformer(response, callback) - } -} - -module.exports = streamToValueWithTransformer diff --git a/src/utils/stream-to-value.js b/src/utils/stream-to-value.js deleted file mode 100644 index d28fd6130..000000000 --- a/src/utils/stream-to-value.js +++ /dev/null @@ -1,18 +0,0 @@ -'use strict' - -const pump = require('pump') -const concat = require('concat-stream') - -/* - Concatenate a stream to a single value. -*/ -function streamToValue (response, callback) { - let data - pump( - response, - concat((d) => { data = d }), - (err) => callback(err, data) - ) -} - -module.exports = streamToValue diff --git a/src/version.js b/src/version.js index 438cdd000..8faee147a 100644 --- a/src/version.js +++ b/src/version.js @@ -1,30 +1,19 @@ 'use strict' -const promisify = require('promisify-es6') -const moduleConfig = require('./utils/module-config') +const configure = require('./lib/configure') +const toCamel = require('./lib/object-to-camel') -module.exports = (arg) => { - const send = moduleConfig(arg) +module.exports = configure(({ ky }) => { + return async options => { + options = options || {} - return promisify((opts, callback) => { - if (typeof opts === 'function') { - callback = opts - opts = {} - } + const res = await ky.post('version', { + timeout: options.timeout, + signal: options.signal, + headers: options.headers, + searchParams: options.searchParams + }).json() - send({ - path: 'version', - qs: opts - }, (err, result) => { - if (err) { - return callback(err) - } - const version = { - version: result.Version, - commit: result.Commit, - repo: result.Repo - } - callback(null, version) - }) - }) -} + return toCamel(res) + } +}) diff --git a/test/constructor.spec.js b/test/constructor.spec.js index e4a7eb1aa..60bfc9f33 100644 --- a/test/constructor.spec.js +++ b/test/constructor.spec.js @@ -44,15 +44,6 @@ describe('ipfs-http-client constructor tests', () => { expectConfig(ipfs, { host, port, protocol }) }) - it('multiaddr dns4 string, explicit https in opts', () => { - const host = 'foo.com' - const port = '1001' - const protocol = 'https' - const addr = `/dns4/${host}/tcp/${port}` - const ipfs = ipfsClient(addr, { protocol }) - expectConfig(ipfs, { host, port, protocol }) - }) - it('multiaddr ipv4 string (implicit http)', () => { const host = '101.101.101.101' const port = '1001' @@ -82,7 +73,7 @@ describe('ipfs-http-client constructor tests', () => { it('host and port strings', () => { const host = '1.1.1.1' const port = '9999' - const ipfs = ipfsClient(host, port) + const ipfs = ipfsClient({ host, port }) expectConfig(ipfs, { host, port }) }) @@ -90,14 +81,14 @@ describe('ipfs-http-client constructor tests', () => { const host = '10.100.100.255' const port = '9999' const apiPath = '/future/api/v1/' - const ipfs = ipfsClient(host, port, { 'api-path': apiPath }) - expectConfig(ipfs, { host, port, apiPath }) + const ipfs = ipfsClient({ host, port, apiPath }) + expectConfig(ipfs, { host, port, apiPath: apiPath.slice(0, -1) }) }) it('throws on invalid multiaddr', () => { expect(() => ipfsClient('/dns4')).to.throw('invalid address') expect(() => ipfsClient('/hello')).to.throw('no protocol with name') - expect(() => ipfsClient('/dns4/ipfs.io')).to.throw('multiaddr must have a valid format') + expect(() => ipfsClient('/dns4/ipfs.io')).to.throw() }) }) @@ -134,7 +125,7 @@ async function clientWorks (client) { function expectConfig (ipfs, { host, port, protocol, apiPath }) { const conf = ipfs.getEndpointConfig() expect(conf.host).to.be.oneOf([host, 'localhost', '']) - expect(conf.port).to.be.oneOf([port, '5001', 80]) + expect(conf.port).to.be.oneOf([port, '5001', '80']) expect(conf.protocol).to.equal(protocol || 'http') - expect(conf['api-path']).to.equal(apiPath || '/api/v0/') + expect(conf['api-path']).to.equal(apiPath || '/api/v0') } diff --git a/test/custom-headers.spec.js b/test/custom-headers.spec.js index 0780c23b9..ce14a01e5 100644 --- a/test/custom-headers.spec.js +++ b/test/custom-headers.spec.js @@ -4,23 +4,13 @@ const isNode = require('detect-node') const { expect } = require('interface-ipfs-core/src/utils/mocha') const ipfsClient = require('../src') -const f = require('./utils/factory') describe('custom headers', function () { // do not test in browser if (!isNode) { return } - this.timeout(50 * 1000) // slow CI let ipfs - let ipfsd // initialize ipfs with custom headers - before(async () => { - ipfsd = await f.spawn({ - initOptions: { - bits: 1024, - profile: 'test' - } - }) - + before(() => { ipfs = ipfsClient({ host: 'localhost', port: 6001, @@ -37,6 +27,7 @@ describe('custom headers', function () { req.on('data', () => {}) req.on('end', () => { res.writeHead(200) + res.write(JSON.stringify({})) res.end() // ensure custom headers are present expect(req.headers.authorization).to.equal('Bearer ' + 'YOLO') @@ -48,16 +39,10 @@ describe('custom headers', function () { server.listen(6001, () => { ipfs.id((err, res) => { if (err) { - throw new Error('Unexpected error.') + throw err } // this call is used to test that headers are being sent. }) }) }) - - after(async () => { - if (ipfsd) { - await ipfsd.stop() - } - }) }) diff --git a/test/endpoint-config.spec.js b/test/endpoint-config.spec.js index c867717b9..a44de3e1c 100644 --- a/test/endpoint-config.spec.js +++ b/test/endpoint-config.spec.js @@ -3,43 +3,16 @@ 'use strict' const { expect } = require('interface-ipfs-core/src/utils/mocha') -const isNode = require('detect-node') const ipfsClient = require('../src') -const f = require('./utils/factory') describe('.getEndpointConfig', () => { - if (!isNode) { return } - - let ipfsd - let ipfs - - before(async function () { - this.timeout(20 * 1000) // slow CI - - ipfsd = await f.spawn({ - initOptions: { - bits: 1024, - profile: 'test' - } - }) - ipfs = ipfsClient(ipfsd.apiAddr) - }) - - after(async function () { - this.timeout(10 * 1000) - - if (ipfsd) { - await ipfsd.stop() - } - }) - it('should return the endpoint configuration', function () { + const ipfs = ipfsClient('https://127.0.0.1:5501/ipfs/api/') const endpoint = ipfs.getEndpointConfig() expect(endpoint.host).to.equal('127.0.0.1') - expect(endpoint.protocol).to.equal('http') - expect(endpoint['api-path']).to.equal('/api/v0/') - // changes per test run so we just assert it exists. - expect(endpoint).to.have.property('port') + expect(endpoint.protocol).to.equal('https') + expect(endpoint['api-path']).to.equal('/ipfs/api') + expect(endpoint.port).to.equal('5501') }) }) diff --git a/test/lib.configure.spec.js b/test/lib.configure.spec.js index 8cb56be5f..550165035 100644 --- a/test/lib.configure.spec.js +++ b/test/lib.configure.spec.js @@ -10,7 +10,7 @@ describe('lib/configure', () => { it('should accept no config', () => { configure(config => { if (isBrowser || isWebWorker) { - expect(config.apiAddr).to.eql('') + expect(config.apiAddr).to.eql(location.origin) } else { expect(config.apiAddr).to.eql('http://localhost:5001') } @@ -24,10 +24,17 @@ describe('lib/configure', () => { })(input) }) + it('should accept string url', () => { + const input = 'http://127.0.0.1:5001' + configure(config => { + expect(config.apiAddr).to.eql('http://127.0.0.1:5001') + })(input) + }) + it('should accept multiaddr instance', () => { - const input = Multiaddr('/ip4/127.0.0.1') + const input = Multiaddr('/ip4/127.0.0.1/tcp/5001') configure(config => { - expect(config.apiAddr).to.eql('http://127.0.0.1') + expect(config.apiAddr).to.eql('http://127.0.0.1:5001') })(input) }) diff --git a/test/log.spec.js b/test/log.spec.js index a9dbc0274..7f8e2c608 100644 --- a/test/log.spec.js +++ b/test/log.spec.js @@ -37,20 +37,11 @@ describe('.log', function () { } }, 1000) - const res = await ipfs.log.tail() - - return new Promise((resolve, reject) => { - res.on('error', (err) => { - reject(err) - }) - - res.once('data', (obj) => { - clearInterval(i) - expect(obj).to.be.an('object') - res.end() - resolve() - }) - }) + for await (const message of ipfs.log.tail()) { + clearInterval(i) + expect(message).to.be.an('object') + break + } }) it('.log.ls', async () => { @@ -65,7 +56,7 @@ describe('.log', function () { expect(res).to.exist() expect(res).to.be.an('object') - expect(res).to.not.have.property('Error') - expect(res).to.have.property('Message') + expect(res).to.not.have.property('error') + expect(res).to.have.property('message') }) }) diff --git a/test/node/swarm.js b/test/node/swarm.js index 27d377904..9e0252a2c 100644 --- a/test/node/swarm.js +++ b/test/node/swarm.js @@ -29,24 +29,6 @@ describe('.swarm.peers', function () { expect(scope.isDone()).to.equal(true) }) - it('handles a go-ipfs <= 0.4.4 peer response', async () => { - const response = { Strings: ['/ip4/73.109.217.59/tcp/49311/ipfs/QmWjxEGC7BthJrCf7QTModrcsRweHbupdPTY4oGMVoDZXm'] } - - const scope = nock(apiUrl) - .post('/api/v0/swarm/peers') - .query(true) - .reply(200, response) - - const res = await ipfs.swarm.peers() - - expect(res).to.be.a('array') - expect(res.length).to.equal(1) - expect(res[0].error).to.not.exist() - expect(res[0].addr.toString()).to.equal('/ip4/73.109.217.59/tcp/49311/ipfs/QmWjxEGC7BthJrCf7QTModrcsRweHbupdPTY4oGMVoDZXm') - expect(res[0].peer.toB58String()).to.equal('QmWjxEGC7BthJrCf7QTModrcsRweHbupdPTY4oGMVoDZXm') - expect(scope.isDone()).to.equal(true) - }) - it('handles an ip6 quic peer', async () => { const response = { Peers: [{ Addr: '/ip6/2001:8a0:7ac5:4201:3ac9:86ff:fe31:7095/udp/4001/quic', Peer: 'QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC', Latency: '', Muxer: '', Streams: null }] } diff --git a/test/ping.spec.js b/test/ping.spec.js index 46c58c890..10c131b75 100644 --- a/test/ping.spec.js +++ b/test/ping.spec.js @@ -6,7 +6,6 @@ const pull = require('pull-stream/pull') const collect = require('pull-stream/sinks/collect') const ipfsClient = require('../src') -const PingMessageStream = require('../src/utils/ping-message-stream') const f = require('./utils/factory') // Determine if a ping response object is a pong, or something else, like a status message @@ -58,23 +57,20 @@ describe('.ping', function () { } }) - it('.ping with default n', async () => { + it('.ping with default count', async () => { const res = await ipfs.ping(otherId) - expect(res).to.be.an('array') - expect(res.filter(isPong)).to.have.lengthOf(1) + expect(res.filter(isPong)).to.have.lengthOf(10) res.forEach(packet => { expect(packet).to.have.keys('success', 'time', 'text') expect(packet.time).to.be.a('number') }) - const resultMsg = res.find(packet => packet.text.includes('Average latency')) expect(resultMsg).to.exist() }) it('.ping with count = 2', async () => { const res = await ipfs.ping(otherId, { count: 2 }) - expect(res).to.be.an('array') expect(res.filter(isPong)).to.have.lengthOf(2) res.forEach(packet => { @@ -85,44 +81,13 @@ describe('.ping', function () { expect(resultMsg).to.exist() }) - it('.ping with n = 2', async () => { - const res = await ipfs.ping(otherId, { n: 2 }) - - expect(res).to.be.an('array') - expect(res.filter(isPong)).to.have.lengthOf(2) - res.forEach(packet => { - expect(packet).to.have.keys('success', 'time', 'text') - expect(packet.time).to.be.a('number') - }) - const resultMsg = res.find(packet => packet.text.includes('Average latency')) - expect(resultMsg).to.exist() - }) - - it('.ping fails with count & n', async function () { - this.timeout(20 * 1000) - - await expect(ipfs.ping(otherId, { count: 2, n: 2 })).to.be.rejected() - }) - - it('.ping with Promises', async () => { - const res = await ipfs.ping(otherId) - expect(res).to.be.an('array') - expect(res.filter(isPong)).to.have.lengthOf(1) - res.forEach(packet => { - expect(packet).to.have.keys('success', 'time', 'text') - expect(packet.time).to.be.a('number') - }) - const resultMsg = res.find(packet => packet.text.includes('Average latency')) - expect(resultMsg).to.exist() - }) - it('.pingPullStream', (done) => { pull( - ipfs.pingPullStream(otherId), + ipfs.pingPullStream(otherId, { count: 2 }), collect((err, data) => { expect(err).to.not.exist() expect(data).to.be.an('array') - expect(data.filter(isPong)).to.have.lengthOf(1) + expect(data.filter(isPong)).to.have.lengthOf(2) data.forEach(packet => { expect(packet).to.have.keys('success', 'time', 'text') expect(packet.time).to.be.a('number') @@ -136,7 +101,7 @@ describe('.ping', function () { it('.pingReadableStream', (done) => { let packetNum = 0 - ipfs.pingReadableStream(otherId) + ipfs.pingReadableStream(otherId, { count: 2 }) .on('data', data => { expect(data).to.be.an('object') expect(data).to.have.keys('success', 'time', 'text') @@ -146,15 +111,8 @@ describe('.ping', function () { expect(err).not.to.exist() }) .on('end', () => { - expect(packetNum).to.equal(1) + expect(packetNum).to.equal(2) done() }) }) - - it('message conversion fails if invalid message is received', () => { - const messageConverter = new PingMessageStream() - expect(() => { - messageConverter.write({ some: 'InvalidMessage' }) - }).to.throw('Invalid ping message received') - }) }) diff --git a/test/sub-modules.spec.js b/test/sub-modules.spec.js index 62d05ce8e..ee8f6d93b 100644 --- a/test/sub-modules.spec.js +++ b/test/sub-modules.spec.js @@ -2,14 +2,10 @@ 'use strict' const { expect } = require('interface-ipfs-core/src/utils/mocha') -const defaultConfig = require('../src/utils/default-config.js') -const config = defaultConfig() -config.host = 'test' -config.port = '1111' describe('submodules', () => { it('bitswap', () => { - const bitswap = require('../src/bitswap')(config) + const bitswap = require('../src/bitswap')() expect(bitswap.wantlist).to.be.a('function') expect(bitswap.stat).to.be.a('function') @@ -17,7 +13,7 @@ describe('submodules', () => { }) it('block', () => { - const block = require('../src/block')(config) + const block = require('../src/block')() expect(block.get).to.be.a('function') expect(block.stat).to.be.a('function') @@ -25,7 +21,7 @@ describe('submodules', () => { }) it('bootstrap', () => { - const bootstrap = require('../src/bootstrap')(config) + const bootstrap = require('../src/bootstrap')() expect(bootstrap.add).to.be.a('function') expect(bootstrap.rm).to.be.a('function') @@ -33,7 +29,7 @@ describe('submodules', () => { }) it('config', () => { - const cfg = require('../src/config')(config) + const cfg = require('../src/config')() expect(cfg.get).to.be.a('function') expect(cfg.set).to.be.a('function') @@ -44,7 +40,7 @@ describe('submodules', () => { }) it('dht', () => { - const dht = require('../src/dht')(config) + const dht = require('../src/dht')() expect(dht.get).to.be.a('function') expect(dht.put).to.be.a('function') @@ -55,21 +51,21 @@ describe('submodules', () => { }) it('id', () => { - const id = require('../src/id')(config) + const id = require('../src/id')() expect(id).to.be.a('function') }) it('version', () => { - const version = require('../src/version')(config) + const version = require('../src/version')() expect(version).to.be.a('function') }) it('ping', () => { - const ping = require('../src/ping')(config) - const pingPullStream = require('../src/ping-pull-stream')(config) - const pingReadableStream = require('../src/ping-readable-stream')(config) + const ping = require('../src')().ping + const pingPullStream = require('../src')().pingPullStream + const pingReadableStream = require('../src')().pingReadableStream expect(ping).to.be.a('function') expect(pingPullStream).to.be.a('function') @@ -77,7 +73,7 @@ describe('submodules', () => { }) it('log', () => { - const log = require('../src/log')(config) + const log = require('../src/log')() expect(log.ls).to.be.a('function') expect(log.tail).to.be.a('function') @@ -85,21 +81,21 @@ describe('submodules', () => { }) it('key', () => { - const key = require('../src/key')(config) + const key = require('../src/key')() expect(key.gen).to.be.a('function') expect(key.list).to.be.a('function') }) it('name', () => { - const name = require('../src/name')(config) + const name = require('../src/name')() expect(name.publish).to.be.a('function') expect(name.resolve).to.be.a('function') }) it('pin', () => { - const pin = require('../src/pin')(config) + const pin = require('../src/pin')() expect(pin.add).to.be.a('function') expect(pin.rm).to.be.a('function') @@ -107,14 +103,14 @@ describe('submodules', () => { }) it('repo', () => { - const repo = require('../src/repo')(config) + const repo = require('../src/repo')() expect(repo.gc).to.be.a('function') expect(repo.stat).to.be.a('function') }) it('stats', () => { - const stats = require('../src/stats')(config) + const stats = require('../src/stats')() expect(stats.bitswap).to.be.a('function') expect(stats.bw).to.be.a('function') @@ -122,7 +118,7 @@ describe('submodules', () => { }) it('swarm', () => { - const swarm = require('../src/swarm')(config) + const swarm = require('../src/swarm')() expect(swarm.peers).to.be.a('function') expect(swarm.connect).to.be.a('function') @@ -132,7 +128,7 @@ describe('submodules', () => { }) it('diag', () => { - const diag = require('../src/diag')(config) + const diag = require('../src/diag')() expect(diag.net).to.be.a('function') expect(diag.sys).to.be.a('function') @@ -140,7 +136,7 @@ describe('submodules', () => { }) it('object', () => { - const object = require('../src/object')(config) + const object = require('../src/object')() expect(object.get).to.be.a('function') expect(object.put).to.be.a('function') @@ -155,7 +151,7 @@ describe('submodules', () => { }) it('pubsub', () => { - const pubsub = require('../src/pubsub')(config) + const pubsub = require('../src/pubsub')() expect(pubsub.subscribe).to.be.a('function') expect(pubsub.unsubscribe).to.be.a('function') @@ -165,7 +161,7 @@ describe('submodules', () => { }) it('files regular API', () => { - const filesRegular = require('../src')(config) + const filesRegular = require('../src')() expect(filesRegular.add).to.be.a('function') expect(filesRegular.addReadableStream).to.be.a('function') @@ -191,7 +187,7 @@ describe('submodules', () => { }) it('files MFS API', () => { - const files = require('../src/files')(config) + const files = require('../src/files')() expect(files.cp).to.be.a('function') expect(files.ls).to.be.a('function') @@ -204,13 +200,13 @@ describe('submodules', () => { }) it('commands', () => { - const commands = require('../src/commands')(config) + const commands = require('../src/commands')() expect(commands).to.be.a('function') }) it('mount', () => { - const mount = require('../src/mount')(config) + const mount = require('../src/mount')() expect(mount).to.be.a('function') }) From 496811b2ead8377227ec872dd256cc6c09c38356 Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Fri, 22 Nov 2019 14:37:48 +0000 Subject: [PATCH 189/233] chore: update contributors --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 8fc450b79..423109411 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ipfs-http-client", - "version": "39.0.2", + "version": "40.0.0", "description": "A client library for the IPFS HTTP API", "keywords": [ "ipfs" @@ -101,7 +101,6 @@ "Alan Shaw ", "Alan Shaw ", "Alex Mingoia ", - "Alex Potsides ", "Antonio Tenorio-Fornés ", "Bruno Barbieri ", "Clemo ", @@ -174,6 +173,7 @@ "Victor Bjelkholm ", "Volker Mische ", "Zhiyuan Lin ", + "achingbrain ", "dirkmc ", "dmitriy ryajov ", "elsehow ", From 79ff53241e0b72730eb94a2b5a1793a33c97c687 Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Fri, 22 Nov 2019 14:37:49 +0000 Subject: [PATCH 190/233] chore: release version v40.0.0 --- CHANGELOG.md | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 049e2b123..0f0de1f04 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,57 @@ + +# [40.0.0](https://github.com/ipfs/js-ipfs-http-client/compare/v39.0.2...v40.0.0) (2019-11-22) + + +### Code Refactoring + +* async await roundup ([#1173](https://github.com/ipfs/js-ipfs-http-client/issues/1173)) ([3e5967a](https://github.com/ipfs/js-ipfs-http-client/commit/3e5967a)), closes [#1103](https://github.com/ipfs/js-ipfs-http-client/issues/1103) +* convert config API to async await ([#1155](https://github.com/ipfs/js-ipfs-http-client/issues/1155)) ([621973c](https://github.com/ipfs/js-ipfs-http-client/commit/621973c)) +* move files to root level ([#1150](https://github.com/ipfs/js-ipfs-http-client/issues/1150)) ([559a97d](https://github.com/ipfs/js-ipfs-http-client/commit/559a97d)) + + +### Features + +* support name.resolve of peerid as cid ([#1145](https://github.com/ipfs/js-ipfs-http-client/issues/1145)) ([2d9afc8](https://github.com/ipfs/js-ipfs-http-client/commit/2d9afc8)) + + +### Reverts + +* chore: update multiaddr to version 7.2.0 ([#1136](https://github.com/ipfs/js-ipfs-http-client/issues/1136)) ([#1143](https://github.com/ipfs/js-ipfs-http-client/issues/1143)) ([4131d09](https://github.com/ipfs/js-ipfs-http-client/commit/4131d09)) + + +### BREAKING CHANGES + +* The `log.tail` method now returns an async iterator that yields log messages. Use it like: + +```js +for await (const message of ipfs.log.tail()) { + console.log(message) +} +``` +* The response to a call to `log.level` now returns an object that has camel cased keys. i.e. `Message` and `Error` properties have changed to `message` and `error`. +* Dropped support for go-ipfs <= 0.4.4 in `swarm.peers` response. +* The signature for `ipfs.mount` has changed from `ipfs.mount([ipfsPath], [ipnsPath])` to `ipfs.mount([options])`. Where `options` is an optional object that may contain two boolean properties `ipfsPath` and `ipnsPath`. The response object has also changed to be camel case. See https://docs.ipfs.io/reference/api/http/#api-v0-mount. +* Default ping `count` of 1 in client has been removed. The default ping count is now whatever the IPFS node defaults it to (currently 10). If you specifically need 1 ping message then please pass `count: 1` in options for `ipfs.ping()`. +* Multi parameter constructor options are no longer supported. To create a new IPFS HTTP client, pass a single parameter to the constructor. The parameter can be one of: + +* String, formatted as one of: + * Multiaddr e.g. /ip4/127.0.0.1/tcp/5001 + * URL e.g. http://127.0.0.1:5001 +* [Multiaddr](https://www.npmjs.com/package/multiaddr) instance +* Object, in format of either: + * Address and path e.g. `{ apiAddr: '/ip4/127.0.0.1/tcp/5001': apiPath: '/api/v0' }` (Note: `apiAddr` can also be a string in URL form or a Multiaddr instance) + * Node.js style address e.g. `{ host: '127.0.0.1', port: 5001, protocol: 'http' }` +* Errors returned from request failures are now all [`HTTPError`](https://github.com/sindresorhus/ky/blob/c0d9d2bb07e4c122a08f019b39e9c55a4c9324f3/index.js#L117-L123)s which carry a `response` property. This is a [`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response) that can be used to inspect _all_ information relating to the HTTP response. This means that the `err.status` or `err.statusCode` property should now be accessed via `err.response.status`. + +License: MIT +Signed-off-by: Alan Shaw +* files in `src/files-regular` have moved to `src`. The `src/files-mfs` directory has been renamed to `src/files`. If you were previously requiring files from these directories e.g. `require('ipfs-http-client/src/files-regular/add')` then please be aware that they have moved. + +License: MIT +Signed-off-by: Alan Shaw + + + ## [39.0.2](https://github.com/ipfs/js-ipfs-http-client/compare/v39.0.1...v39.0.2) (2019-10-23) From 876ae7ca685d5e97a2ed3337f2f38d08e5d8c560 Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Fri, 22 Nov 2019 14:42:51 +0000 Subject: [PATCH 191/233] docs: tweak formatting in changelog for v40 --- CHANGELOG.md | 32 ++++++++++++-------------------- 1 file changed, 12 insertions(+), 20 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0f0de1f04..cb5bff527 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,34 +22,26 @@ ### BREAKING CHANGES * The `log.tail` method now returns an async iterator that yields log messages. Use it like: - -```js -for await (const message of ipfs.log.tail()) { - console.log(message) -} -``` + ```js + for await (const message of ipfs.log.tail()) { + console.log(message) + } + ``` * The response to a call to `log.level` now returns an object that has camel cased keys. i.e. `Message` and `Error` properties have changed to `message` and `error`. * Dropped support for go-ipfs <= 0.4.4 in `swarm.peers` response. * The signature for `ipfs.mount` has changed from `ipfs.mount([ipfsPath], [ipnsPath])` to `ipfs.mount([options])`. Where `options` is an optional object that may contain two boolean properties `ipfsPath` and `ipnsPath`. The response object has also changed to be camel case. See https://docs.ipfs.io/reference/api/http/#api-v0-mount. * Default ping `count` of 1 in client has been removed. The default ping count is now whatever the IPFS node defaults it to (currently 10). If you specifically need 1 ping message then please pass `count: 1` in options for `ipfs.ping()`. * Multi parameter constructor options are no longer supported. To create a new IPFS HTTP client, pass a single parameter to the constructor. The parameter can be one of: - -* String, formatted as one of: - * Multiaddr e.g. /ip4/127.0.0.1/tcp/5001 - * URL e.g. http://127.0.0.1:5001 -* [Multiaddr](https://www.npmjs.com/package/multiaddr) instance -* Object, in format of either: - * Address and path e.g. `{ apiAddr: '/ip4/127.0.0.1/tcp/5001': apiPath: '/api/v0' }` (Note: `apiAddr` can also be a string in URL form or a Multiaddr instance) - * Node.js style address e.g. `{ host: '127.0.0.1', port: 5001, protocol: 'http' }` + * String, formatted as one of: + * Multiaddr e.g. /ip4/127.0.0.1/tcp/5001 + * URL e.g. http://127.0.0.1:5001 + * [Multiaddr](https://www.npmjs.com/package/multiaddr) instance + * Object, in format of either: + * Address and path e.g. `{ apiAddr: '/ip4/127.0.0.1/tcp/5001': apiPath: '/api/v0' }` (Note: `apiAddr` can also be a string in URL form or a Multiaddr instance) + * Node.js style address e.g. `{ host: '127.0.0.1', port: 5001, protocol: 'http' }` * Errors returned from request failures are now all [`HTTPError`](https://github.com/sindresorhus/ky/blob/c0d9d2bb07e4c122a08f019b39e9c55a4c9324f3/index.js#L117-L123)s which carry a `response` property. This is a [`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response) that can be used to inspect _all_ information relating to the HTTP response. This means that the `err.status` or `err.statusCode` property should now be accessed via `err.response.status`. - -License: MIT -Signed-off-by: Alan Shaw * files in `src/files-regular` have moved to `src`. The `src/files-mfs` directory has been renamed to `src/files`. If you were previously requiring files from these directories e.g. `require('ipfs-http-client/src/files-regular/add')` then please be aware that they have moved. -License: MIT -Signed-off-by: Alan Shaw - From 64a44f5ce63a4d97a787753a47ffef3f5e740ed8 Mon Sep 17 00:00:00 2001 From: Pedro Santos Date: Wed, 27 Nov 2019 06:41:14 +0000 Subject: [PATCH 192/233] chore: change interface tests to async node creation (#1176) * chore: change interface tests to async node creation * chore: update interface-ipfs-core dep * chore: code review changes --- package.json | 2 +- test/interface.spec.js | 11 +++++------ test/utils/interface-common-factory.js | 21 ++++++++++++--------- 3 files changed, 18 insertions(+), 16 deletions(-) diff --git a/package.json b/package.json index 423109411..955cb94af 100644 --- a/package.json +++ b/package.json @@ -84,7 +84,7 @@ "cross-env": "^6.0.0", "detect-node": "^2.0.4", "go-ipfs-dep": "^0.4.22", - "interface-ipfs-core": "^0.121.0", + "interface-ipfs-core": "^0.122.0", "ipfsd-ctl": "^0.47.1", "ndjson": "^1.5.0", "nock": "^11.4.0", diff --git a/test/interface.spec.js b/test/interface.spec.js index 760962b38..dc41ec325 100644 --- a/test/interface.spec.js +++ b/test/interface.spec.js @@ -7,7 +7,7 @@ const CommonFactory = require('./utils/interface-common-factory') const isWindows = process.platform && process.platform === 'win32' describe('interface-ipfs-core tests', () => { - const defaultCommonFactory = CommonFactory.create() + const defaultCommonFactory = CommonFactory.createAsync() tests.bitswap(defaultCommonFactory, { skip: [ @@ -172,7 +172,7 @@ describe('interface-ipfs-core tests', () => { ] }) - tests.name(CommonFactory.create({ + tests.name(CommonFactory.createAsync({ spawnOptions: { args: ['--offline'] } @@ -186,8 +186,7 @@ describe('interface-ipfs-core tests', () => { ] }) - // TODO: uncomment after https://github.com/ipfs/interface-ipfs-core/pull/361 being merged and a new release - tests.namePubsub(CommonFactory.create({ + tests.namePubsub(CommonFactory.createAsync({ spawnOptions: { args: ['--enable-namesys-pubsub'], initOptions: { bits: 1024, profile: 'test' } @@ -228,7 +227,7 @@ describe('interface-ipfs-core tests', () => { ] }) - tests.pubsub(CommonFactory.create({ + tests.pubsub(CommonFactory.createAsync({ spawnOptions: { args: ['--enable-pubsub-experiment'], initOptions: { bits: 1024, profile: 'test' } @@ -251,5 +250,5 @@ describe('interface-ipfs-core tests', () => { tests.stats(defaultCommonFactory) - tests.swarm(CommonFactory.createAsync()) + tests.swarm(defaultCommonFactory) }) diff --git a/test/utils/interface-common-factory.js b/test/utils/interface-common-factory.js index 4a47fda42..bd4720b6e 100644 --- a/test/utils/interface-common-factory.js +++ b/test/utils/interface-common-factory.js @@ -6,10 +6,14 @@ const IPFSFactory = require('ipfsd-ctl') const ipfsClient = require('../../src') const merge = require('merge-options') +const DEFAULT_FACTORY_OPTIONS = { + IpfsClient: ipfsClient +} + function createFactory (options) { options = options || {} - options.factoryOptions = options.factoryOptions || { IpfsClient: ipfsClient } + options.factoryOptions = options.factoryOptions || { ...DEFAULT_FACTORY_OPTIONS } options.spawnOptions = options.spawnOptions || { initOptions: { bits: 1024, profile: 'test' } } const ipfsFactory = IPFSFactory.create(options.factoryOptions) @@ -52,19 +56,18 @@ function createFactory (options) { } } -function createAsync (createFactoryOptions, createSpawnOptions) { +function createAsync (options = {}) { return () => { const nodes = [] - const setup = async (factoryOptions = {}, spawnOptions) => { + const setup = async (setupOptions = {}) => { const ipfsFactory = IPFSFactory.create(merge( - { IpfsClient: ipfsClient }, - factoryOptions, - createFactoryOptions + options.factoryOptions ? {} : { ...DEFAULT_FACTORY_OPTIONS }, + setupOptions.factoryOptions, + options.factoryOptions )) const node = await ipfsFactory.spawn(merge( - { initOptions: { profile: 'test' } }, - spawnOptions, - createSpawnOptions + setupOptions.spawnOptions, + options.spawnOptions || { initOptions: { profile: 'test' } } )) nodes.push(node) From cb39a69ca527c452d9a104bdc4bd331969c61a9c Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" <23040076+greenkeeper[bot]@users.noreply.github.com> Date: Wed, 27 Nov 2019 06:41:54 +0000 Subject: [PATCH 193/233] chore(package): update it-glob to version 0.0.7 (#1182) --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 955cb94af..7d562b413 100644 --- a/package.json +++ b/package.json @@ -60,7 +60,7 @@ "ipld-dag-pb": "^0.18.1", "ipld-raw": "^4.0.0", "is-ipfs": "~0.6.1", - "it-glob": "0.0.6", + "it-glob": "0.0.7", "it-tar": "^1.1.1", "it-to-stream": "^0.1.1", "iterable-ndjson": "^1.1.0", From 2f3763f682eb4cbca5c1cd773d363491063a7483 Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Wed, 27 Nov 2019 15:51:06 +0000 Subject: [PATCH 194/233] fix: pin ls with multiple CIDs (#1184) Fixes `pin.ls` with multiple CIDs, which was inadvertently unsupported since it wasn't documented but was being tested for in js-ipfs CLI tests. https://github.com/ipfs/interface-js-ipfs-core/pull/563 adds a test and documents the feature. --- package.json | 2 +- src/pin/ls.js | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 7d562b413..1b7d098b4 100644 --- a/package.json +++ b/package.json @@ -84,7 +84,7 @@ "cross-env": "^6.0.0", "detect-node": "^2.0.4", "go-ipfs-dep": "^0.4.22", - "interface-ipfs-core": "^0.122.0", + "interface-ipfs-core": "^0.123.0", "ipfsd-ctl": "^0.47.1", "ndjson": "^1.5.0", "nock": "^11.4.0", diff --git a/src/pin/ls.js b/src/pin/ls.js index cd1cc07f1..9c42fd71d 100644 --- a/src/pin/ls.js +++ b/src/pin/ls.js @@ -9,10 +9,12 @@ module.exports = configure(({ ky }) => { path = null } + path = path || [] + path = Array.isArray(path) ? path : [path] options = options || {} const searchParams = new URLSearchParams(options.searchParams) - if (path) searchParams.set('arg', `${path}`) + path.forEach(p => searchParams.append('arg', `${p}`)) if (options.type) searchParams.set('type', options.type) const { Keys } = await ky.post('pin/ls', { From fd7cc4c26e6ad22311a6dc3f66ecb0e744f37608 Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Wed, 27 Nov 2019 15:54:41 +0000 Subject: [PATCH 195/233] chore: update contributors --- package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 1b7d098b4..99103fa69 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ipfs-http-client", - "version": "40.0.0", + "version": "40.0.1", "description": "A client library for the IPFS HTTP API", "keywords": [ "ipfs" @@ -157,6 +157,7 @@ "Níckolas Goline ", "Oli Evans ", "Orie Steele ", + "Pedro Santos ", "Pedro Teixeira ", "Pete Thomas ", "Richard Littauer ", From d95b8f16a6060c501e217ccb2835feba670ed9ce Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Wed, 27 Nov 2019 15:54:42 +0000 Subject: [PATCH 196/233] chore: release version v40.0.1 --- CHANGELOG.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index cb5bff527..0d8658a5f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,13 @@ + +## [40.0.1](https://github.com/ipfs/js-ipfs-http-client/compare/v40.0.0...v40.0.1) (2019-11-27) + + +### Bug Fixes + +* pin ls with multiple CIDs ([#1184](https://github.com/ipfs/js-ipfs-http-client/issues/1184)) ([2f3763f](https://github.com/ipfs/js-ipfs-http-client/commit/2f3763f)) + + + # [40.0.0](https://github.com/ipfs/js-ipfs-http-client/compare/v39.0.2...v40.0.0) (2019-11-22) From f77819c4c366a471c22bb6de08a2b133c835cf43 Mon Sep 17 00:00:00 2001 From: sarthak khandelwal Date: Fri, 29 Nov 2019 20:51:13 +0530 Subject: [PATCH 197/233] docs: switch license to dual MIT and Apache 2 (#1179) --- COPYRIGHT | 5 +++++ LICENSE-APACHE | 5 +++++ LICENSE => LICENSE-MIT | 0 package.json | 2 +- 4 files changed, 11 insertions(+), 1 deletion(-) create mode 100644 COPYRIGHT create mode 100644 LICENSE-APACHE rename LICENSE => LICENSE-MIT (100%) diff --git a/COPYRIGHT b/COPYRIGHT new file mode 100644 index 000000000..b8b0a702d --- /dev/null +++ b/COPYRIGHT @@ -0,0 +1,5 @@ +This project is transitioning from an MIT-only license to a dual MIT/Apache-2.0 license. +Unless otherwise noted, all code contributed prior to 2019-11-26 and not contributed by +a user listed in [this signoff issue](https://github.com/ipfs/js-ipfs-http-client/issues/1189) is +licensed under MIT-only. All new contributions (and past contributions since 2019-11-29) +are licensed under a dual MIT/Apache-2.0 license. diff --git a/LICENSE-APACHE b/LICENSE-APACHE new file mode 100644 index 000000000..14478a3b6 --- /dev/null +++ b/LICENSE-APACHE @@ -0,0 +1,5 @@ +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. diff --git a/LICENSE b/LICENSE-MIT similarity index 100% rename from LICENSE rename to LICENSE-MIT diff --git a/package.json b/package.json index 99103fa69..88c175538 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ ], "homepage": "https://github.com/ipfs/js-ipfs-http-client", "bugs": "https://github.com/ipfs/js-ipfs-http-client/issues", - "license": "MIT", + "license": "(Apache-2.0 OR MIT)", "leadMaintainer": "Alan Shaw ", "files": [ "src", From e8a32a781b9b9df76fa102d790e381f9014e6ef5 Mon Sep 17 00:00:00 2001 From: Pedro Santos Date: Mon, 2 Dec 2019 11:14:42 +0000 Subject: [PATCH 198/233] refactor: use echo-server start and stop functions as promises (#1191) * refactor: use echo-server start and stop functions as promises * chore: update interface-ipfs-core version --- .aegir.js | 11 ++++------- package.json | 3 +-- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/.aegir.js b/.aegir.js index 847d73a9b..69e938893 100644 --- a/.aegir.js +++ b/.aegir.js @@ -1,13 +1,10 @@ 'use strict' -const promisify = require('promisify-es6') const createServer = require('ipfsd-ctl').createServer const EchoServer = require('interface-ipfs-core/src/utils/echo-http-server') const server = createServer() const echoServer = EchoServer.createServer() -const echoServerStart = promisify(echoServer.start) -const echoServerStop = promisify(echoServer.stop) module.exports = { bundlesize: { maxSize: '246kB' }, webpack: { @@ -27,20 +24,20 @@ module.exports = { }, hooks: { node: { - pre: () => echoServerStart(), - post: () => echoServerStop() + pre: () => echoServer.start(), + post: () => echoServer.stop() }, browser: { pre: () => { return Promise.all([ server.start(), - echoServerStart() + echoServer.start() ]) }, post: () => { return Promise.all([ server.stop(), - echoServerStop() + echoServer.stop() ]) } } diff --git a/package.json b/package.json index 88c175538..25e596d77 100644 --- a/package.json +++ b/package.json @@ -84,11 +84,10 @@ "cross-env": "^6.0.0", "detect-node": "^2.0.4", "go-ipfs-dep": "^0.4.22", - "interface-ipfs-core": "^0.123.0", + "interface-ipfs-core": "^0.124.0", "ipfsd-ctl": "^0.47.1", "ndjson": "^1.5.0", "nock": "^11.4.0", - "promisify-es6": "^1.0.3", "pull-stream": "^3.6.14", "pump": "^3.0.0", "stream-equal": "^1.1.1" From d158d2a5a753284235434ebda7f42ec20f95a8b0 Mon Sep 17 00:00:00 2001 From: Daniel Constantin Date: Mon, 2 Dec 2019 13:47:49 +0200 Subject: [PATCH 199/233] chore: fix supported engines (#1193) --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 25e596d77..2ebbffb98 100644 --- a/package.json +++ b/package.json @@ -93,7 +93,7 @@ "stream-equal": "^1.1.1" }, "engines": { - "node": ">=8.3.0", + "node": ">=10.3.0", "npm": ">=3.0.0" }, "contributors": [ From fff35c811dd4eab05870d04d588c13c693975a05 Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Fri, 6 Dec 2019 15:48:55 +0000 Subject: [PATCH 200/233] docs: add missing breaking change info to v40 --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0d8658a5f..7c50e3d72 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -51,6 +51,8 @@ * Node.js style address e.g. `{ host: '127.0.0.1', port: 5001, protocol: 'http' }` * Errors returned from request failures are now all [`HTTPError`](https://github.com/sindresorhus/ky/blob/c0d9d2bb07e4c122a08f019b39e9c55a4c9324f3/index.js#L117-L123)s which carry a `response` property. This is a [`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response) that can be used to inspect _all_ information relating to the HTTP response. This means that the `err.status` or `err.statusCode` property should now be accessed via `err.response.status`. * files in `src/files-regular` have moved to `src`. The `src/files-mfs` directory has been renamed to `src/files`. If you were previously requiring files from these directories e.g. `require('ipfs-http-client/src/files-regular/add')` then please be aware that they have moved. +* Kebab case options are no longer supported. Please use camel case option names as defined in the [`interface-ipfs-core`](https://github.com/ipfs/interface-js-ipfs-core/tree/master/SPEC) docs. e.g. the `allow-offline` option to `name.publish` should be passed as `allowOffline`. + * Note that you can pass [additional query string parameters](https://github.com/ipfs/js-ipfs-http-client#additional-options) in the `searchParams` option available to all API methods. From 47093d53724fdad3b1b9f569a8a11877b6a4cf40 Mon Sep 17 00:00:00 2001 From: Alex Potsides Date: Fri, 6 Dec 2019 20:51:05 +0000 Subject: [PATCH 201/233] feat: expose import concurrency controls (#1187) --- package.json | 2 +- src/add/index.js | 2 ++ src/index.js | 2 +- src/lib/converters.js | 2 +- 4 files changed, 5 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 2ebbffb98..791fe0a2b 100644 --- a/package.json +++ b/package.json @@ -42,7 +42,6 @@ }, "dependencies": { "abort-controller": "^3.0.0", - "async-iterator-all": "^1.0.0", "async-iterator-to-pull-stream": "^1.3.0", "bignumber.js": "^9.0.0", "bl": "^4.0.0", @@ -60,6 +59,7 @@ "ipld-dag-pb": "^0.18.1", "ipld-raw": "^4.0.0", "is-ipfs": "~0.6.1", + "it-all": "^1.0.1", "it-glob": "0.0.7", "it-tar": "^1.1.1", "it-to-stream": "^0.1.1", diff --git a/src/add/index.js b/src/add/index.js index b1a8bb2a1..df6afbad3 100644 --- a/src/add/index.js +++ b/src/add/index.js @@ -29,6 +29,8 @@ module.exports = configure(({ ky }) => { if (options.trickle != null) searchParams.set('trickle', options.trickle) if (options.wrapWithDirectory != null) searchParams.set('wrap-with-directory', options.wrapWithDirectory) if (options.preload != null) searchParams.set('preload', options.preload) + if (options.fileImportConcurrency != null) searchParams.set('file-import-concurrency', options.fileImportConcurrency) + if (options.blockWriteConcurrency != null) searchParams.set('block-write-concurrency', options.blockWriteConcurrency) const res = await ky.post('add', { timeout: options.timeout, diff --git a/src/index.js b/src/index.js index d9dc89630..939f5986f 100644 --- a/src/index.js +++ b/src/index.js @@ -11,7 +11,7 @@ const PeerId = require('peer-id') const PeerInfo = require('peer-info') const nodeify = require('promise-nodeify') const callbackify = require('callbackify') -const all = require('async-iterator-all') +const all = require('it-all') const toPullStream = require('async-iterator-to-pull-stream') const toStream = require('it-to-stream') const BufferList = require('bl/BufferList') diff --git a/src/lib/converters.js b/src/lib/converters.js index a1ed8a010..4f42b3175 100644 --- a/src/lib/converters.js +++ b/src/lib/converters.js @@ -1,7 +1,7 @@ 'use strict' const toPull = require('async-iterator-to-pull-stream') -const all = require('async-iterator-all') +const all = require('it-all') const toStream = require('it-to-stream') const { Buffer } = require('buffer') From cfb5245aa3b8fb0527d2f61b2d4b99731bae9ab7 Mon Sep 17 00:00:00 2001 From: achingbrain Date: Tue, 10 Dec 2019 16:30:45 +0000 Subject: [PATCH 202/233] chore: update contributors --- package.json | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 791fe0a2b..abaf35d69 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ipfs-http-client", - "version": "40.0.1", + "version": "40.1.0", "description": "A client library for the IPFS HTTP API", "keywords": [ "ipfs" @@ -100,10 +100,12 @@ "Alan Shaw ", "Alan Shaw ", "Alex Mingoia ", + "Alex Potsides ", "Antonio Tenorio-Fornés ", "Bruno Barbieri ", "Clemo ", "Connor Keenan ", + "Daniel Constantin ", "Danny ", "David Braun ", "David Dias ", @@ -156,6 +158,7 @@ "Níckolas Goline ", "Oli Evans ", "Orie Steele ", + "Pedro Santos ", "Pedro Santos ", "Pedro Teixeira ", "Pete Thomas ", @@ -173,7 +176,6 @@ "Victor Bjelkholm ", "Volker Mische ", "Zhiyuan Lin ", - "achingbrain ", "dirkmc ", "dmitriy ryajov ", "elsehow ", @@ -188,6 +190,7 @@ "phillmac ", "priecint ", "samuli ", + "sarthak khandelwal ", "shunkin ", "victorbjelkholm ", "Łukasz Magiera ", From 70c78d1f7e62d0890f98c799fab103d283da9e64 Mon Sep 17 00:00:00 2001 From: achingbrain Date: Tue, 10 Dec 2019 16:30:45 +0000 Subject: [PATCH 203/233] chore: release version v40.1.0 --- CHANGELOG.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7c50e3d72..af8c75cd7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,13 @@ + +# [40.1.0](https://github.com/ipfs/js-ipfs-http-client/compare/v40.0.1...v40.1.0) (2019-12-10) + + +### Features + +* expose import concurrency controls ([#1187](https://github.com/ipfs/js-ipfs-http-client/issues/1187)) ([47093d5](https://github.com/ipfs/js-ipfs-http-client/commit/47093d5)) + + + ## [40.0.1](https://github.com/ipfs/js-ipfs-http-client/compare/v40.0.0...v40.0.1) (2019-11-27) From 23421f397e4ae80ac9e9264ee6662b2cc0e34791 Mon Sep 17 00:00:00 2001 From: Hugo Dias Date: Wed, 11 Dec 2019 19:29:12 +0000 Subject: [PATCH 204/233] refactor: use new ipfsd-ctl setup (#1127) * fix: use new ipfsd-ctl setup * chore: add correct branches * fix: support new ctl * fix: update to the latest ctl api * fix: use proper module * fix: override properly * chore: bump ipfsd-ctl, interface-core --- package.json | 4 +- test/commands.spec.js | 16 +-- test/constructor.spec.js | 12 +- test/dag.spec.js | 16 +-- test/diag.spec.js | 16 +-- test/files-mfs.spec.js | 16 +-- test/get.spec.js | 17 +-- test/interface.spec.js | 146 ++++++++++++------------- test/key.spec.js | 17 +-- test/log.spec.js | 16 +-- test/ping.spec.js | 30 +---- test/repo.spec.js | 16 +-- test/stats.spec.js | 16 +-- test/utils/factory.js | 14 ++- test/utils/interface-common-factory.js | 92 ---------------- 15 files changed, 106 insertions(+), 338 deletions(-) delete mode 100644 test/utils/interface-common-factory.js diff --git a/package.json b/package.json index abaf35d69..f0253c933 100644 --- a/package.json +++ b/package.json @@ -84,8 +84,8 @@ "cross-env": "^6.0.0", "detect-node": "^2.0.4", "go-ipfs-dep": "^0.4.22", - "interface-ipfs-core": "^0.124.0", - "ipfsd-ctl": "^0.47.1", + "interface-ipfs-core": "~0.125.0", + "ipfsd-ctl": "^1.0.0", "ndjson": "^1.5.0", "nock": "^11.4.0", "pull-stream": "^3.6.14", diff --git a/test/commands.spec.js b/test/commands.spec.js index 2f7b1f5e3..9e68a1e01 100644 --- a/test/commands.spec.js +++ b/test/commands.spec.js @@ -2,30 +2,18 @@ 'use strict' const { expect } = require('interface-ipfs-core/src/utils/mocha') -const ipfsClient = require('../src') const f = require('./utils/factory') describe('.commands', function () { this.timeout(60 * 1000) - let ipfsd let ipfs before(async () => { - ipfsd = await f.spawn({ - initOptions: { - bits: 1024, - profile: 'test' - } - }) - ipfs = ipfsClient(ipfsd.apiAddr) + ipfs = (await f.spawn()).api }) - after(async () => { - if (ipfsd) { - await ipfsd.stop() - } - }) + after(() => f.clean()) it('lists commands', async () => { const res = await ipfs.commands() diff --git a/test/constructor.spec.js b/test/constructor.spec.js index 60bfc9f33..a1a000c84 100644 --- a/test/constructor.spec.js +++ b/test/constructor.spec.js @@ -93,24 +93,18 @@ describe('ipfs-http-client constructor tests', () => { }) describe('integration', () => { - let apiAddr let ipfsd before(async function () { this.timeout(60 * 1000) // slow CI - ipfsd = await f.spawn({ initOptions: { bits: 1024, profile: 'test' } }) - apiAddr = ipfsd.apiAddr.toString() + ipfsd = await f.spawn() }) - after(async () => { - if (ipfsd) { - await ipfsd.stop() - } - }) + after(() => f.clean()) it('can connect to an ipfs http api', async () => { - await clientWorks(ipfsClient(apiAddr)) + await clientWorks(ipfsClient(ipfsd.apiAddr)) }) }) }) diff --git a/test/dag.spec.js b/test/dag.spec.js index cd58002ad..de9217d13 100644 --- a/test/dag.spec.js +++ b/test/dag.spec.js @@ -6,29 +6,17 @@ const { expect } = require('interface-ipfs-core/src/utils/mocha') const { DAGNode } = require('ipld-dag-pb') const CID = require('cids') -const ipfsClient = require('../src') const f = require('./utils/factory') -let ipfsd let ipfs describe('.dag', function () { this.timeout(20 * 1000) before(async function () { - ipfsd = await f.spawn({ - initOptions: { - bits: 1024, - profile: 'test' - } - }) - ipfs = ipfsClient(ipfsd.apiAddr) + ipfs = (await f.spawn()).api }) - after(async () => { - if (ipfsd) { - await ipfsd.stop() - } - }) + after(() => f.clean()) it('should be able to put and get a DAG node with format dag-pb', async () => { const data = Buffer.from('some data') diff --git a/test/diag.spec.js b/test/diag.spec.js index e42716214..37a1911e7 100644 --- a/test/diag.spec.js +++ b/test/diag.spec.js @@ -3,7 +3,6 @@ const { expect } = require('interface-ipfs-core/src/utils/mocha') const platform = require('browser-process-platform') -const ipfsClient = require('../src') const f = require('./utils/factory') describe('.diag', function () { @@ -12,24 +11,13 @@ describe('.diag', function () { // go-ipfs does not support these on Windows if (platform === 'win32') { return } - let ipfsd let ipfs before(async () => { - ipfsd = await f.spawn({ - initOptions: { - bits: 1024, - profile: 'test' - } - }) - ipfs = ipfsClient(ipfsd.apiAddr) + ipfs = (await f.spawn()).api }) - after(async () => { - if (ipfsd) { - await ipfsd.stop() - } - }) + after(() => f.clean()) describe('api API', () => { // Disabled in go-ipfs 0.4.10 diff --git a/test/files-mfs.spec.js b/test/files-mfs.spec.js index 6ae508d1d..0e3d6b1af 100644 --- a/test/files-mfs.spec.js +++ b/test/files-mfs.spec.js @@ -10,7 +10,6 @@ const values = require('pull-stream/sources/values') const pull = require('pull-stream/pull') const collect = require('pull-stream/sinks/collect') -const ipfsClient = require('../src') const f = require('./utils/factory') const expectTimeout = require('./utils/expect-timeout') @@ -31,26 +30,15 @@ const HASH_ALGS = [ describe('.files (the MFS API part)', function () { this.timeout(20 * 1000) - let ipfsd let ipfs const expectedMultihash = 'Qma4hjFTnCasJ8PVp3mZbZK5g2vGDT4LByLJ7m8ciyRFZP' before(async () => { - ipfsd = await f.spawn({ - initOptions: { - bits: 1024, - profile: 'test' - } - }) - ipfs = ipfsClient(ipfsd.apiAddr) + ipfs = (await f.spawn()).api }) - after(async () => { - if (ipfsd) { - await ipfsd.stop() - } - }) + after(() => f.clean()) it('.add file for testing', async () => { const res = await ipfs.add(testfile) diff --git a/test/get.spec.js b/test/get.spec.js index 7c1a63e74..a6fb3aaa4 100644 --- a/test/get.spec.js +++ b/test/get.spec.js @@ -6,7 +6,6 @@ const { expect } = require('interface-ipfs-core/src/utils/mocha') const loadFixture = require('aegir/fixtures') -const ipfsClient = require('../src') const f = require('./utils/factory') describe('.get (specific go-ipfs features)', function () { @@ -21,26 +20,14 @@ describe('.get (specific go-ipfs features)', function () { data: fixture('test/fixtures/testfile.txt') } - let ipfsd let ipfs before(async () => { - ipfsd = await f.spawn({ - initOptions: { - bits: 1024, - profile: 'test' - } - }) - ipfs = ipfsClient(ipfsd.apiAddr) - + ipfs = (await f.spawn()).api await ipfs.add(smallFile.data) }) - after(async () => { - if (ipfsd) { - await ipfsd.stop() - } - }) + after(() => f.clean()) it('no compression args', async () => { const files = await ipfs.get(smallFile.cid) diff --git a/test/interface.spec.js b/test/interface.spec.js index dc41ec325..5435518cf 100644 --- a/test/interface.spec.js +++ b/test/interface.spec.js @@ -2,47 +2,41 @@ 'use strict' const tests = require('interface-ipfs-core') -const isNode = require('detect-node') -const CommonFactory = require('./utils/interface-common-factory') +const merge = require('merge-options') +const { isNode } = require('ipfs-utils/src/env') +const { createFactory } = require('ipfsd-ctl') +const { findBin } = require('ipfsd-ctl/src/utils') const isWindows = process.platform && process.platform === 'win32' -describe('interface-ipfs-core tests', () => { - const defaultCommonFactory = CommonFactory.createAsync() - - tests.bitswap(defaultCommonFactory, { - skip: [ - // bitswap.stat - { - name: 'should not get bitswap stats when offline', - reason: 'FIXME go-ipfs returns an error https://github.com/ipfs/go-ipfs/issues/4078' - }, - // bitswap.wantlist - { - name: 'should not get the wantlist when offline', - reason: 'FIXME go-ipfs returns an error https://github.com/ipfs/go-ipfs/issues/4078' - }, - // bitswap.unwant - { - name: 'should remove a key from the wantlist', - reason: 'FIXME why is this skipped?' - }, - { - name: 'should not remove a key from the wantlist when offline', - reason: 'FIXME go-ipfs returns an error https://github.com/ipfs/go-ipfs/issues/4078' - } - ] - }) +/** @typedef {import("ipfsd-ctl").ControllerOptions} ControllerOptions */ - tests.block(defaultCommonFactory, { +describe('interface-ipfs-core tests', () => { + /** @type ControllerOptions */ + const commonOptions = { + test: true, + ipfsHttpModule: { + path: require.resolve('../src'), + ref: require('../src') + }, + ipfsOptions: { + pass: 'ipfs-is-awesome-software' + }, + ipfsBin: findBin('go') + } + const commonFactory = createFactory(commonOptions) + + tests.bitswap(commonFactory) + + tests.block(commonFactory, { skip: [{ name: 'should get a block added as CIDv1 with a CIDv0', reason: 'go-ipfs does not support the `version` param' }] }) - tests.bootstrap(defaultCommonFactory) + tests.bootstrap(commonFactory) - tests.config(defaultCommonFactory, { + tests.config(commonFactory, { skip: [ // config.replace { @@ -60,7 +54,7 @@ describe('interface-ipfs-core tests', () => { ] }) - tests.dag(defaultCommonFactory, { + tests.dag(commonFactory, { skip: [ // dag.tree { @@ -87,7 +81,7 @@ describe('interface-ipfs-core tests', () => { ] }) - tests.dht(defaultCommonFactory, { + tests.dht(commonFactory, { skip: [ // dht.findpeer { @@ -107,47 +101,47 @@ describe('interface-ipfs-core tests', () => { ] }) - tests.filesRegular(defaultCommonFactory, { + tests.filesMFS(commonFactory, { skip: [ - // .addFromFs - isNode ? null : { - name: 'addFromFs', - reason: 'Not designed to run in the browser' - }, - // .catPullStream { - name: 'should export a chunk of a file', - reason: 'TODO not implemented in go-ipfs yet' + name: 'should ls directory with long option', + reason: 'TODO unskip when go-ipfs supports --long https://github.com/ipfs/go-ipfs/pull/6528' }, { - name: 'should export a chunk of a file in a Pull Stream', + name: 'should read from outside of mfs', reason: 'TODO not implemented in go-ipfs yet' }, { - name: 'should export a chunk of a file in a Readable Stream', + name: 'should ls from outside of mfs', reason: 'TODO not implemented in go-ipfs yet' } ] }) - tests.filesMFS(defaultCommonFactory, { + tests.filesRegular(commonFactory, { skip: [ + // .addFromFs + isNode ? null : { + name: 'addFromFs', + reason: 'Not designed to run in the browser' + }, + // .catPullStream { - name: 'should ls directory with long option', - reason: 'TODO unskip when go-ipfs supports --long https://github.com/ipfs/go-ipfs/pull/6528' + name: 'should export a chunk of a file', + reason: 'TODO not implemented in go-ipfs yet' }, { - name: 'should read from outside of mfs', + name: 'should export a chunk of a file in a Pull Stream', reason: 'TODO not implemented in go-ipfs yet' }, { - name: 'should ls from outside of mfs', + name: 'should export a chunk of a file in a Readable Stream', reason: 'TODO not implemented in go-ipfs yet' } ] }) - tests.key(defaultCommonFactory, { + tests.key(commonFactory, { skip: [ // key.export { @@ -162,21 +156,15 @@ describe('interface-ipfs-core tests', () => { ] }) - tests.miscellaneous(defaultCommonFactory, { - skip: [ - // stop - { - name: 'should stop the node', - reason: 'FIXME go-ipfs returns an error https://github.com/ipfs/go-ipfs/issues/4078' - } - ] - }) + tests.miscellaneous(commonFactory) - tests.name(CommonFactory.createAsync({ - spawnOptions: { - args: ['--offline'] + tests.name(createFactory(merge(commonOptions, + { + ipfsOptions: { + offline: true + } } - }), { + )), { skip: [ // stop { @@ -186,12 +174,15 @@ describe('interface-ipfs-core tests', () => { ] }) - tests.namePubsub(CommonFactory.createAsync({ - spawnOptions: { - args: ['--enable-namesys-pubsub'], - initOptions: { bits: 1024, profile: 'test' } + tests.namePubsub(createFactory(merge(commonOptions, + { + ipfsOptions: { + EXPERIMENTAL: { + ipnsPubsub: true + } + } } - }), { + )), { skip: [ // name.pubsub.cancel { @@ -206,11 +197,11 @@ describe('interface-ipfs-core tests', () => { ] }) - tests.object(defaultCommonFactory) + tests.object(commonFactory) - tests.pin(defaultCommonFactory) + tests.pin(commonFactory) - tests.ping(defaultCommonFactory, { + tests.ping(commonFactory, { skip: [ { name: 'should fail when pinging an unknown peer over pull stream', @@ -227,10 +218,9 @@ describe('interface-ipfs-core tests', () => { ] }) - tests.pubsub(CommonFactory.createAsync({ - spawnOptions: { - args: ['--enable-pubsub-experiment'], - initOptions: { bits: 1024, profile: 'test' } + tests.pubsub(createFactory(commonOptions, { + go: { + args: ['--enable-pubsub-experiment'] } }), { skip: isWindows ? [ @@ -246,9 +236,9 @@ describe('interface-ipfs-core tests', () => { ] : null }) - tests.repo(defaultCommonFactory) + tests.repo(commonFactory) - tests.stats(defaultCommonFactory) + tests.stats(commonFactory) - tests.swarm(defaultCommonFactory) + tests.swarm(commonFactory) }) diff --git a/test/key.spec.js b/test/key.spec.js index 2e4e15714..180cb795b 100644 --- a/test/key.spec.js +++ b/test/key.spec.js @@ -1,32 +1,19 @@ /* eslint-env mocha */ -/* eslint max-nested-callbacks: ["error", 8] */ 'use strict' const { expect } = require('interface-ipfs-core/src/utils/mocha') -const ipfsClient = require('../src') const f = require('./utils/factory') describe('.key', function () { this.timeout(50 * 1000) - let ipfsd let ipfs before(async () => { - ipfsd = await f.spawn({ - initOptions: { - bits: 1024, - profile: 'test' - } - }) - ipfs = ipfsClient(ipfsd.apiAddr) + ipfs = (await f.spawn()).api }) - after(async () => { - if (ipfsd) { - await ipfsd.stop() - } - }) + after(() => f.clean()) describe('.gen', () => { it('create a new rsa key', async () => { diff --git a/test/log.spec.js b/test/log.spec.js index 7f8e2c608..1a885028d 100644 --- a/test/log.spec.js +++ b/test/log.spec.js @@ -3,30 +3,18 @@ 'use strict' const { expect } = require('interface-ipfs-core/src/utils/mocha') -const ipfsClient = require('../src') const f = require('./utils/factory') describe('.log', function () { this.timeout(100 * 1000) - let ipfsd let ipfs before(async () => { - ipfsd = await f.spawn({ - initOptions: { - bits: 1024, - profile: 'test' - } - }) - ipfs = ipfsClient(ipfsd.apiAddr) + ipfs = (await f.spawn()).api }) - after(async () => { - if (ipfsd) { - await ipfsd.stop() - } - }) + after(() => f.clean()) it('.log.tail', async () => { const i = setInterval(async () => { diff --git a/test/ping.spec.js b/test/ping.spec.js index 10c131b75..01636ed60 100644 --- a/test/ping.spec.js +++ b/test/ping.spec.js @@ -5,7 +5,6 @@ const { expect } = require('interface-ipfs-core/src/utils/mocha') const pull = require('pull-stream/pull') const collect = require('pull-stream/sinks/collect') -const ipfsClient = require('../src') const f = require('./utils/factory') // Determine if a ping response object is a pong, or something else, like a status message @@ -17,29 +16,14 @@ describe('.ping', function () { this.timeout(20 * 1000) let ipfs - let ipfsd let other - let otherd let otherId before(async function () { this.timeout(30 * 1000) // slow CI - ipfsd = await f.spawn({ - initOptions: { - bits: 1024, - profile: 'test' - } - }) - ipfs = ipfsClient(ipfsd.apiAddr) - - otherd = await f.spawn({ - initOptions: { - bits: 1024, - profile: 'test' - } - }) - other = otherd.api + ipfs = (await f.spawn()).api + other = (await f.spawn()).api const ma = (await ipfs.id()).addresses[0] await other.swarm.connect(ma) @@ -47,15 +31,7 @@ describe('.ping', function () { otherId = (await other.id()).id }) - after(async () => { - if (ipfsd) { - await ipfsd.stop() - } - - if (otherd) { - await otherd.stop() - } - }) + after(() => f.clean()) it('.ping with default count', async () => { const res = await ipfs.ping(otherId) diff --git a/test/repo.spec.js b/test/repo.spec.js index 84b5a42c3..21482135d 100644 --- a/test/repo.spec.js +++ b/test/repo.spec.js @@ -2,30 +2,18 @@ 'use strict' const { expect } = require('interface-ipfs-core/src/utils/mocha') -const ipfsClient = require('../src') const f = require('./utils/factory') describe('.repo', function () { this.timeout(50 * 1000) // slow CI let ipfs - let ipfsd before(async () => { - ipfsd = await f.spawn({ - initOptions: { - bits: 1024, - profile: 'test' - } - }) - ipfs = ipfsClient(ipfsd.apiAddr) + ipfs = (await f.spawn()).api }) - after(async () => { - if (ipfsd) { - await ipfsd.stop() - } - }) + after(() => f.clean()) it('.repo.gc', async () => { const res = await ipfs.repo.gc() diff --git a/test/stats.spec.js b/test/stats.spec.js index 0b7084d0a..d60aaa330 100644 --- a/test/stats.spec.js +++ b/test/stats.spec.js @@ -2,30 +2,18 @@ 'use strict' const { expect } = require('interface-ipfs-core/src/utils/mocha') -const ipfsClient = require('../src') const f = require('./utils/factory') describe('stats', function () { this.timeout(50 * 1000) // slow CI let ipfs - let ipfsd before(async () => { - ipfsd = await f.spawn({ - initOptions: { - bits: 1024, - profile: 'test' - } - }) - ipfs = ipfsClient(ipfsd.apiAddr) + ipfs = (await f.spawn()).api }) - after(async () => { - if (ipfsd) { - await ipfsd.stop() - } - }) + after(() => f.clean()) it('.stats.bitswap', async () => { const res = await ipfs.stats.bitswap() diff --git a/test/utils/factory.js b/test/utils/factory.js index aab6296fe..d6ac161ea 100644 --- a/test/utils/factory.js +++ b/test/utils/factory.js @@ -1,5 +1,15 @@ 'use strict' +const { createFactory } = require('ipfsd-ctl') +const { findBin } = require('ipfsd-ctl/src/utils') -const IPFSFactory = require('ipfsd-ctl') +const factory = createFactory({ + test: 'true', + type: 'go', + ipfsBin: findBin('go'), + ipfsHttpModule: { + path: require.resolve('../../src'), + ref: require('../../src') + } +}) -module.exports = IPFSFactory.create() +module.exports = factory diff --git a/test/utils/interface-common-factory.js b/test/utils/interface-common-factory.js deleted file mode 100644 index bd4720b6e..000000000 --- a/test/utils/interface-common-factory.js +++ /dev/null @@ -1,92 +0,0 @@ -/* eslint-env mocha */ -'use strict' - -const each = require('async/each') -const IPFSFactory = require('ipfsd-ctl') -const ipfsClient = require('../../src') -const merge = require('merge-options') - -const DEFAULT_FACTORY_OPTIONS = { - IpfsClient: ipfsClient -} - -function createFactory (options) { - options = options || {} - - options.factoryOptions = options.factoryOptions || { ...DEFAULT_FACTORY_OPTIONS } - options.spawnOptions = options.spawnOptions || { initOptions: { bits: 1024, profile: 'test' } } - - const ipfsFactory = IPFSFactory.create(options.factoryOptions) - - return function createCommon () { - const nodes = [] - let setup, teardown - - if (options.createSetup) { - setup = options.createSetup({ ipfsFactory, nodes }, options) - } else { - setup = (callback) => { - callback(null, { - spawnNode (cb) { - ipfsFactory.spawn(options.spawnOptions) - .then((ipfsd) => { - nodes.push(ipfsd) - setImmediate(() => cb(null, ipfsd.api)) - }) - .catch(err => { - setImmediate(() => cb(err)) - }) - } - }) - } - } - - if (options.createTeardown) { - teardown = options.createTeardown({ ipfsFactory, nodes }, options) - } else { - teardown = callback => each(nodes, (node, cb) => { - node - .stop() - .then(() => setImmediate(() => cb())) - .catch(err => setImmediate(() => cb(err))) - }, callback) - } - - return { setup, teardown } - } -} - -function createAsync (options = {}) { - return () => { - const nodes = [] - const setup = async (setupOptions = {}) => { - const ipfsFactory = IPFSFactory.create(merge( - options.factoryOptions ? {} : { ...DEFAULT_FACTORY_OPTIONS }, - setupOptions.factoryOptions, - options.factoryOptions - )) - const node = await ipfsFactory.spawn(merge( - setupOptions.spawnOptions, - options.spawnOptions || { initOptions: { profile: 'test' } } - )) - nodes.push(node) - - const id = await node.api.id() - node.api.peerId = id - - return node.api - } - - const teardown = () => { - return Promise.all(nodes.map(n => n.stop())) - } - return { - setup, - teardown - } - } -} -module.exports = { - createAsync, - create: createFactory -} From 8b9fc28253c46960a4dc1142a47d47c23985b080 Mon Sep 17 00:00:00 2001 From: Jim Pick Date: Wed, 18 Dec 2019 12:14:40 -0800 Subject: [PATCH 205/233] docs: change "IPN" to "IPNS" in README (#1204) I'm assuming that's what it was supposed to be. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5c6a00070..9c6d3a3c7 100644 --- a/README.md +++ b/README.md @@ -413,7 +413,7 @@ The js-ipfs-http-client is a work in progress. As such, there's a few things you - **[Check out the existing issues](https://github.com/ipfs/js-ipfs-http-client/issues)**! - **Perform code reviews**. More eyes will help a) speed the project along b) ensure quality and c) reduce possible future bugs. - **Add tests**. There can never be enough tests. Note that interface tests exist inside [`interface-ipfs-core`](https://github.com/ipfs/interface-ipfs-core/tree/master/js/src). -- **Contribute to the [FAQ repository](https://github.com/ipfs/faq/issues)** with any questions you have about IPFS or any of the relevant technology. A good example would be asking, 'What is a merkledag tree?'. If you don't know a term, odds are, someone else doesn't either. Eventually, we should have a good understanding of where we need to improve communications and teaching together to make IPFS and IPN better. +- **Contribute to the [FAQ repository](https://github.com/ipfs/faq/issues)** with any questions you have about IPFS or any of the relevant technology. A good example would be asking, 'What is a merkledag tree?'. If you don't know a term, odds are, someone else doesn't either. Eventually, we should have a good understanding of where we need to improve communications and teaching together to make IPFS and IPNS better. **Want to hack on IPFS?** From 4cd7858de6a2812ee941eaeb4bd48f6ea6cc121c Mon Sep 17 00:00:00 2001 From: Paul Cowgill Date: Tue, 31 Dec 2019 06:02:21 -0600 Subject: [PATCH 206/233] docs: grammar fix (#1208) * Grammar fix * Same grammar fix in a different spot --- examples/bundle-browserify/README.md | 2 +- examples/bundle-webpack/README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/bundle-browserify/README.md b/examples/bundle-browserify/README.md index a185527e0..def887200 100644 --- a/examples/bundle-browserify/README.md +++ b/examples/bundle-browserify/README.md @@ -11,7 +11,7 @@ As for any js-ipfs-http-client example, **you need a running IPFS daemon**, you **Note:** If you load your app from a different domain than the one the daemon is running (most probably), you will need to set up CORS, see https://github.com/ipfs/js-ipfs-http-client#cors to learn how to do that. -A quick (and dirty way to get it done) is: +A quick (and dirty) way to get it done is: ```bash > ipfs config --json API.HTTPHeaders.Access-Control-Allow-Origin "[\"*\"]" diff --git a/examples/bundle-webpack/README.md b/examples/bundle-webpack/README.md index 3b894b7f5..c85543240 100644 --- a/examples/bundle-webpack/README.md +++ b/examples/bundle-webpack/README.md @@ -11,7 +11,7 @@ As for any js-ipfs-http-client example, **you need a running IPFS daemon**, you **Note:** If you load your app from a different domain than the one the daemon is running (most probably), you will need to set up CORS, see https://github.com/ipfs/js-ipfs-http-client#cors to learn how to do that. -A quick (and dirty way to get it done) is: +A quick (and dirty) way to get it done is: ```bash > ipfs config --json API.HTTPHeaders.Access-Control-Allow-Origin "[\"*\"]" From da9d17a38ce09d299e7180d489a56c1e276b4fb9 Mon Sep 17 00:00:00 2001 From: Alex Potsides Date: Thu, 9 Jan 2020 11:04:33 +0000 Subject: [PATCH 207/233] feat: support UnixFSv1.5 metadata (#1186) * feat: support UnixFSv1.5 metadata * fix: expose new mfs functions * refactor: send mtime and mode as headers instead of message parts * fix: include headers for directories * chore: update ipfs utils dep version * chore: update ipfs-utils dep * fix: stringify mode in browser * test: add tests for unixfs metadata * fix: fix up tests etc for optional mtime --- package.json | 4 +- src/add/form-data.browser.js | 24 +++- src/add/form-data.js | 22 +++- src/add/index.js | 14 +- src/files/chmod.js | 25 ++++ src/files/index.js | 2 + src/files/ls.js | 7 +- src/files/mkdir.js | 11 ++ src/files/stat.js | 5 +- src/files/touch.js | 29 +++++ src/files/write.js | 16 ++- src/lib/buffer-to-form-data.js | 20 ++- src/lib/mode-to-string.js | 13 ++ src/lib/mtime-to-object.js | 56 ++++++++ src/lib/object-to-camel-with-metadata.js | 24 ++++ src/ls.js | 18 ++- test/interface.spec.js | 156 +++++++++++++++++++++++ 17 files changed, 429 insertions(+), 17 deletions(-) create mode 100644 src/files/chmod.js create mode 100644 src/files/touch.js create mode 100644 src/lib/mode-to-string.js create mode 100644 src/lib/mtime-to-object.js create mode 100644 src/lib/object-to-camel-with-metadata.js diff --git a/package.json b/package.json index f0253c933..261b888c9 100644 --- a/package.json +++ b/package.json @@ -54,7 +54,7 @@ "explain-error": "^1.0.4", "form-data": "^3.0.0", "ipfs-block": "~0.8.1", - "ipfs-utils": "^0.4.0", + "ipfs-utils": "^0.4.2", "ipld-dag-cbor": "~0.15.0", "ipld-dag-pb": "^0.18.1", "ipld-raw": "^4.0.0", @@ -84,7 +84,7 @@ "cross-env": "^6.0.0", "detect-node": "^2.0.4", "go-ipfs-dep": "^0.4.22", - "interface-ipfs-core": "~0.125.0", + "interface-ipfs-core": "^0.126.0", "ipfsd-ctl": "^1.0.0", "ndjson": "^1.5.0", "nock": "^11.4.0", diff --git a/src/add/form-data.browser.js b/src/add/form-data.browser.js index 247396c42..484f67c6c 100644 --- a/src/add/form-data.browser.js +++ b/src/add/form-data.browser.js @@ -2,6 +2,7 @@ /* eslint-env browser */ const normaliseInput = require('ipfs-utils/src/files/normalise-input') +const mtimeToObject = require('../lib/mtime-to-object') exports.toFormData = async input => { const files = normaliseInput(input) @@ -9,6 +10,21 @@ exports.toFormData = async input => { let i = 0 for await (const file of files) { + const headers = {} + + if (file.mtime !== undefined && file.mtime !== null) { + const mtime = mtimeToObject(file.mtime) + + if (mtime) { + headers.mtime = mtime.secs + headers['mtime-nsecs'] = mtime.nsecs + } + } + + if (file.mode !== undefined && file.mode !== null) { + headers.mode = file.mode.toString(8).padStart(4, '0') + } + if (file.content) { // In the browser there's _currently_ no streaming upload, buffer up our // async iterator chunks and append a big Blob :( @@ -18,9 +34,13 @@ exports.toFormData = async input => { bufs.push(chunk) } - formData.append(`file-${i}`, new Blob(bufs, { type: 'application/octet-stream' }), encodeURIComponent(file.path)) + formData.append(`file-${i}`, new Blob(bufs, { type: 'application/octet-stream' }), encodeURIComponent(file.path), { + header: headers + }) } else { - formData.append(`dir-${i}`, new Blob([], { type: 'application/x-directory' }), encodeURIComponent(file.path)) + formData.append(`dir-${i}`, new Blob([], { type: 'application/x-directory' }), encodeURIComponent(file.path), { + header: headers + }) } i++ diff --git a/src/add/form-data.js b/src/add/form-data.js index 96d55f672..1ce5050da 100644 --- a/src/add/form-data.js +++ b/src/add/form-data.js @@ -5,6 +5,7 @@ const { Buffer } = require('buffer') const toStream = require('it-to-stream') const normaliseInput = require('ipfs-utils/src/files/normalise-input') const { isElectronRenderer } = require('ipfs-utils/src/env') +const mtimeToObject = require('../lib/mtime-to-object') exports.toFormData = async input => { const files = normaliseInput(input) @@ -12,6 +13,21 @@ exports.toFormData = async input => { let i = 0 for await (const file of files) { + const headers = {} + + if (file.mtime !== undefined && file.mtime !== null) { + const mtime = mtimeToObject(file.mtime) + + if (mtime) { + headers.mtime = mtime.secs + headers['mtime-nsecs'] = mtime.nsecs + } + } + + if (file.mode !== undefined && file.mode !== null) { + headers.mode = file.mode.toString(8).padStart(4, '0') + } + if (file.content) { // In Node.js, FormData can be passed a stream so no need to buffer formData.append( @@ -26,13 +42,15 @@ exports.toFormData = async input => { { filepath: encodeURIComponent(file.path), contentType: 'application/octet-stream', - knownLength: file.content.length // Send Content-Length header if known + knownLength: file.content.length, // Send Content-Length header if known + header: headers } ) } else { formData.append(`dir-${i}`, Buffer.alloc(0), { filepath: encodeURIComponent(file.path), - contentType: 'application/x-directory' + contentType: 'application/x-directory', + header: headers }) } diff --git a/src/add/index.js b/src/add/index.js index df6afbad3..546e5428d 100644 --- a/src/add/index.js +++ b/src/add/index.js @@ -52,6 +52,16 @@ module.exports = configure(({ ky }) => { } }) -function toCoreInterface ({ name, hash, size }) { - return { path: name, hash, size: parseInt(size) } +function toCoreInterface ({ name, hash, size, mode, mtime }) { + const output = { + path: name, + hash, + size: parseInt(size) + } + + if (mode !== undefined) { + output.mode = parseInt(mode, 8) + } + + return output } diff --git a/src/files/chmod.js b/src/files/chmod.js new file mode 100644 index 000000000..b4c0a11dd --- /dev/null +++ b/src/files/chmod.js @@ -0,0 +1,25 @@ +'use strict' + +const configure = require('../lib/configure') +const modeToString = require('../lib/mode-to-string') + +module.exports = configure(({ ky }) => { + return function chmod (path, mode, options) { + options = options || {} + + const searchParams = new URLSearchParams(options.searchParams) + searchParams.append('arg', path) + searchParams.append('mode', modeToString(mode)) + if (options.format) searchParams.set('format', options.format) + if (options.flush != null) searchParams.set('flush', options.flush) + if (options.hashAlg) searchParams.set('hash', options.hashAlg) + if (options.parents != null) searchParams.set('parents', options.parents) + + return ky.post('files/chmod', { + timeout: options.timeout, + signal: options.signal, + headers: options.headers, + searchParams + }).text() + } +}) diff --git a/src/files/index.js b/src/files/index.js index 25e79fcab..ee6b7d8d8 100644 --- a/src/files/index.js +++ b/src/files/index.js @@ -8,6 +8,7 @@ module.exports = config => { const read = require('./read')(config) return { + chmod: callbackify.variadic(require('./chmod')(config)), cp: callbackify.variadic(require('./cp')(config)), mkdir: callbackify.variadic(require('./mkdir')(config)), flush: callbackify.variadic(require('./flush')(config)), @@ -19,6 +20,7 @@ module.exports = config => { read: callbackify.variadic(concatify(read)), readReadableStream: streamify.readable(read), readPullStream: pullify.source(read), + touch: callbackify.variadic(require('./touch')(config)), write: callbackify.variadic(require('./write')(config)), mv: callbackify.variadic(require('./mv')(config)) } diff --git a/src/files/ls.js b/src/files/ls.js index 1baa3f656..51ee33912 100644 --- a/src/files/ls.js +++ b/src/files/ls.js @@ -4,7 +4,7 @@ const CID = require('cids') const ndjson = require('iterable-ndjson') const toIterable = require('../lib/stream-to-iterable') const configure = require('../lib/configure') -const toCamel = require('../lib/object-to-camel') +const toCamelWithMetadata = require('../lib/object-to-camel-with-metadata') module.exports = configure(({ ky }) => { return async function * ls (path, options) { @@ -32,11 +32,12 @@ module.exports = configure(({ ky }) => { // go-ipfs does not yet support the "stream" option if ('Entries' in result) { for (const entry of result.Entries || []) { - yield toCamel(entry) + yield toCamelWithMetadata(entry) } return } - yield toCamel(result) + + yield toCamelWithMetadata(result) } } }) diff --git a/src/files/mkdir.js b/src/files/mkdir.js index 0fc3c238d..3a50c7728 100644 --- a/src/files/mkdir.js +++ b/src/files/mkdir.js @@ -1,10 +1,13 @@ 'use strict' const configure = require('../lib/configure') +const modeToString = require('../lib/mode-to-string') +const mtimeToObject = require('../lib/mtime-to-object') module.exports = configure(({ ky }) => { return (path, options) => { options = options || {} + const mtime = mtimeToObject(options.mtime) const searchParams = new URLSearchParams(options.searchParams) searchParams.append('arg', path) @@ -13,6 +16,14 @@ module.exports = configure(({ ky }) => { if (options.flush != null) searchParams.set('flush', options.flush) if (options.hashAlg) searchParams.set('hash', options.hashAlg) if (options.parents != null) searchParams.set('parents', options.parents) + if (mtime) { + searchParams.set('mtime', mtime.secs) + + if (mtime.nsecs != null) { + searchParams.set('mtimeNsecs', mtime.nsecs) + } + } + if (options.mode != null) searchParams.set('mode', modeToString(options.mode)) return ky.post('files/mkdir', { timeout: options.timeout, diff --git a/src/files/stat.js b/src/files/stat.js index 98026283e..1b4af061b 100644 --- a/src/files/stat.js +++ b/src/files/stat.js @@ -1,7 +1,7 @@ 'use strict' const configure = require('../lib/configure') -const toCamel = require('../lib/object-to-camel') +const toCamelWithMetadata = require('../lib/object-to-camel-with-metadata') module.exports = configure(({ ky }) => { return async (path, options) => { @@ -27,6 +27,7 @@ module.exports = configure(({ ky }) => { }).json() res.WithLocality = res.WithLocality || false - return toCamel(res) + + return toCamelWithMetadata(res) } }) diff --git a/src/files/touch.js b/src/files/touch.js new file mode 100644 index 000000000..b38aca905 --- /dev/null +++ b/src/files/touch.js @@ -0,0 +1,29 @@ +'use strict' + +const configure = require('../lib/configure') +const mtimeToObject = require('../lib/mtime-to-object') + +module.exports = configure(({ ky }) => { + return function touch (path, options) { + options = options || {} + const mtime = mtimeToObject(options.mtime) + + const searchParams = new URLSearchParams(options.searchParams) + searchParams.append('arg', path) + if (mtime) { + searchParams.set('mtime', mtime.secs) + searchParams.set('mtimeNsecs', mtime.nsecs) + } + if (options.format) searchParams.set('format', options.format) + if (options.flush != null) searchParams.set('flush', options.flush) + if (options.hashAlg) searchParams.set('hash', options.hashAlg) + if (options.parents != null) searchParams.set('parents', options.parents) + + return ky.post('files/touch', { + timeout: options.timeout, + signal: options.signal, + headers: options.headers, + searchParams + }).text() + } +}) diff --git a/src/files/write.js b/src/files/write.js index 77a772ea6..e31f0a8a2 100644 --- a/src/files/write.js +++ b/src/files/write.js @@ -2,10 +2,13 @@ const configure = require('../lib/configure') const toFormData = require('../lib/buffer-to-form-data') +const modeToString = require('../lib/mode-to-string') +const mtimeToObject = require('../lib/mtime-to-object') module.exports = configure(({ ky }) => { return async (path, input, options) => { options = options || {} + const mtime = mtimeToObject(options.mtime) const searchParams = new URLSearchParams(options.searchParams) searchParams.set('arg', path) @@ -18,13 +21,24 @@ module.exports = configure(({ ky }) => { if (options.parents != null) searchParams.set('parents', options.parents) if (options.rawLeaves != null) searchParams.set('raw-leaves', options.rawLeaves) if (options.truncate != null) searchParams.set('truncate', options.truncate) + if (mtime) { + searchParams.set('mtime', mtime.secs) + + if (mtime.nsecs != null) { + searchParams.set('mtimeNsecs', mtime.nsecs) + } + } const res = await ky.post('files/write', { timeout: options.timeout, signal: options.signal, headers: options.headers, searchParams, - body: toFormData(input) // TODO: support inputs other than buffer as per spec + body: toFormData(input, { + mode: options.mode != null ? modeToString(options.mode) : undefined, + mtime: mtime ? mtime.secs : undefined, + mtimeNsecs: mtime ? mtime.nsecs : undefined + }) // TODO: support inputs other than buffer as per spec }) return res.text() diff --git a/src/lib/buffer-to-form-data.js b/src/lib/buffer-to-form-data.js index 41f03383e..1a4830361 100644 --- a/src/lib/buffer-to-form-data.js +++ b/src/lib/buffer-to-form-data.js @@ -3,9 +3,25 @@ const FormData = require('form-data') const { isElectronRenderer } = require('ipfs-utils/src/env') -module.exports = buf => { +module.exports = (buf, { mode, mtime, mtimeNsecs } = {}) => { + const headers = {} + + if (mode != null) { + headers.mode = mode + } + + if (mtime != null) { + headers.mtime = mtime + + if (mtimeNsecs != null) { + headers['mtime-nsecs'] = mtimeNsecs + } + } + const formData = new FormData() - formData.append('file', buf) + formData.append('file', buf, { + header: headers + }) return formData } diff --git a/src/lib/mode-to-string.js b/src/lib/mode-to-string.js new file mode 100644 index 000000000..ee2742b9a --- /dev/null +++ b/src/lib/mode-to-string.js @@ -0,0 +1,13 @@ +'use strict' + +module.exports = (mode) => { + if (mode === undefined || mode === null) { + return undefined + } + + if (typeof mode === 'string' || mode instanceof String) { + return mode + } + + return mode.toString(8).padStart(4, '0') +} diff --git a/src/lib/mtime-to-object.js b/src/lib/mtime-to-object.js new file mode 100644 index 000000000..be89148f6 --- /dev/null +++ b/src/lib/mtime-to-object.js @@ -0,0 +1,56 @@ +'use strict' + +module.exports = function parseMtime (mtime) { + if (mtime == null) { + return undefined + } + + // Javascript Date + if (mtime instanceof Date) { + const ms = mtime.getTime() + const secs = Math.floor(ms / 1000) + + return { + secs: secs, + nsecs: (ms - (secs * 1000)) * 1000 + } + } + + // { secs, nsecs } + if (Object.prototype.hasOwnProperty.call(mtime, 'secs')) { + return { + secs: mtime.secs, + nsecs: mtime.nsecs + } + } + + // UnixFS TimeSpec + if (Object.prototype.hasOwnProperty.call(mtime, 'Seconds')) { + return { + secs: mtime.Seconds, + nsecs: mtime.FractionalNanoseconds + } + } + + // process.hrtime() + if (Array.isArray(mtime)) { + return { + secs: mtime[0], + nsecs: mtime[1] + } + } + /* + TODO: https://github.com/ipfs/aegir/issues/487 + + // process.hrtime.bigint() + if (typeof mtime === 'bigint') { + const secs = mtime / BigInt(1e9) + const nsecs = mtime - (secs * BigInt(1e9)) + + return { + secs: parseInt(secs), + nsecs: parseInt(nsecs) + } + } + */ +} diff --git a/src/lib/object-to-camel-with-metadata.js b/src/lib/object-to-camel-with-metadata.js new file mode 100644 index 000000000..55f16d0bb --- /dev/null +++ b/src/lib/object-to-camel-with-metadata.js @@ -0,0 +1,24 @@ +'use strict' + +const toCamel = require('./object-to-camel') + +function toCamelWithMetadata (entry) { + const file = toCamel(entry) + + if (Object.prototype.hasOwnProperty.call(file, 'mode')) { + file.mode = parseInt(file.mode, 8) + } + + if (Object.prototype.hasOwnProperty.call(file, 'mtime')) { + file.mtime = { + secs: file.mtime, + nsecs: file.mtimeNsecs || 0 + } + + delete file.mtimeNsecs + } + + return file +} + +module.exports = toCamelWithMetadata diff --git a/src/ls.js b/src/ls.js index a9cd476f9..43e92a54a 100644 --- a/src/ls.js +++ b/src/ls.js @@ -48,7 +48,7 @@ module.exports = configure(({ ky }) => { } for (const link of result) { - yield { + const entry = { name: link.Name, path: path + '/' + link.Name, size: link.Size, @@ -56,6 +56,22 @@ module.exports = configure(({ ky }) => { type: typeOf(link), depth: link.Depth || 1 } + + if (link.Mode) { + entry.mode = parseInt(link.Mode, 8) + } + + if (link.Mtime !== undefined && link.Mtime !== null) { + entry.mtime = { + secs: link.Mtime + } + + if (link.MtimeNsecs !== undefined && link.MtimeNsecs !== null) { + entry.mtime.nsecs = link.MtimeNsecs + } + } + + yield entry } } }) diff --git a/test/interface.spec.js b/test/interface.spec.js index 5435518cf..e09cac5a6 100644 --- a/test/interface.spec.js +++ b/test/interface.spec.js @@ -114,6 +114,134 @@ describe('interface-ipfs-core tests', () => { { name: 'should ls from outside of mfs', reason: 'TODO not implemented in go-ipfs yet' + }, + { + name: 'should change file mode', + reason: 'TODO not implemented in go-ipfs yet' + }, + { + name: 'should change directory mode', + reason: 'TODO not implemented in go-ipfs yet' + }, + { + name: 'should change file mode as string', + reason: 'TODO not implemented in go-ipfs yet' + }, + { + name: 'should change file mode to 0', + reason: 'TODO not implemented in go-ipfs yet' + }, + { + name: 'should update file mtime', + reason: 'TODO not implemented in go-ipfs yet' + }, + { + name: 'should update directory mtime', + reason: 'TODO not implemented in go-ipfs yet' + }, + { + name: 'should make directory and specify mode', + reason: 'TODO not implemented in go-ipfs yet' + }, + { + name: 'should make directory and specify mtime', + reason: 'TODO not implemented in go-ipfs yet' + }, + { + name: 'should write file and specify mode', + reason: 'TODO not implemented in go-ipfs yet' + }, + { + name: 'should write file and specify mtime', + reason: 'TODO not implemented in go-ipfs yet' + }, + { + name: 'should respect metadata when copying files', + reason: 'TODO not implemented in go-ipfs yet' + }, + { + name: 'should respect metadata when copying directories', + reason: 'TODO not implemented in go-ipfs yet' + }, + { + name: 'should respect metadata when copying from outside of mfs', + reason: 'TODO not implemented in go-ipfs yet' + }, + { + name: 'ls directory with long option should include metadata', + reason: 'TODO not implemented in go-ipfs yet' + }, + { + name: 'should have default mtime', + reason: 'TODO not implemented in go-ipfs yet' + }, + { + name: 'should set mtime as Date', + reason: 'TODO not implemented in go-ipfs yet' + }, + { + name: 'should set mtime as { nsecs, secs }', + reason: 'TODO not implemented in go-ipfs yet' + }, + { + name: 'should set mtime as timespec', + reason: 'TODO not implemented in go-ipfs yet' + }, + { + name: 'should set mtime as hrtime', + reason: 'TODO not implemented in go-ipfs yet' + }, + { + name: 'should make directory and have default mode', + reason: 'TODO not implemented in go-ipfs yet' + }, + { + name: 'should make directory and specify mode as string', + reason: 'TODO not implemented in go-ipfs yet' + }, + { + name: 'should make directory and specify mode as number', + reason: 'TODO not implemented in go-ipfs yet' + }, + { + name: 'should make directory and specify mtime as Date', + reason: 'TODO not implemented in go-ipfs yet' + }, + { + name: 'should make directory and specify mtime as { nsecs, secs }', + reason: 'TODO not implemented in go-ipfs yet' + }, + { + name: 'should make directory and specify mtime as timespec', + reason: 'TODO not implemented in go-ipfs yet' + }, + { + name: 'should make directory and specify mtime as hrtime', + reason: 'TODO not implemented in go-ipfs yet' + }, + { + name: 'should write file and specify mode as a string', + reason: 'TODO not implemented in go-ipfs yet' + }, + { + name: 'should write file and specify mode as a number', + reason: 'TODO not implemented in go-ipfs yet' + }, + { + name: 'should write file and specify mtime as Date', + reason: 'TODO not implemented in go-ipfs yet' + }, + { + name: 'should write file and specify mtime as { nsecs, secs }', + reason: 'TODO not implemented in go-ipfs yet' + }, + { + name: 'should write file and specify mtime as timespec', + reason: 'TODO not implemented in go-ipfs yet' + }, + { + name: 'should write file and specify mtime as hrtime', + reason: 'TODO not implemented in go-ipfs yet' } ] }) @@ -125,6 +253,30 @@ describe('interface-ipfs-core tests', () => { name: 'addFromFs', reason: 'Not designed to run in the browser' }, + { + name: 'should add with mode as string', + reason: 'TODO not implemented in go-ipfs yet' + }, + { + name: 'should add with mode as number', + reason: 'TODO not implemented in go-ipfs yet' + }, + { + name: 'should add with mtime as Date', + reason: 'TODO not implemented in go-ipfs yet' + }, + { + name: 'should add with mtime as { nsecs, secs }', + reason: 'TODO not implemented in go-ipfs yet' + }, + { + name: 'should add with mtime as timespec', + reason: 'TODO not implemented in go-ipfs yet' + }, + { + name: 'should add with mtime as hrtime', + reason: 'TODO not implemented in go-ipfs yet' + }, // .catPullStream { name: 'should export a chunk of a file', @@ -137,6 +289,10 @@ describe('interface-ipfs-core tests', () => { { name: 'should export a chunk of a file in a Readable Stream', reason: 'TODO not implemented in go-ipfs yet' + }, + { + name: 'should ls with metadata', + reason: 'TODO not implemented in go-ipfs yet' } ] }) From 0c679de76c96770e50a5813f246514e142149756 Mon Sep 17 00:00:00 2001 From: achingbrain Date: Thu, 9 Jan 2020 11:42:35 +0000 Subject: [PATCH 208/233] chore: update contributors --- package.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 261b888c9..d0b0d7783 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ipfs-http-client", - "version": "40.1.0", + "version": "40.2.0", "description": "A client library for the IPFS HTTP API", "keywords": [ "ipfs" @@ -137,6 +137,7 @@ "Jeff Downie ", "Jeromy ", "Jeromy ", + "Jim Pick ", "Joe Turgeon ", "Jonathan ", "Juan Batiz-Benet ", @@ -158,6 +159,7 @@ "Níckolas Goline ", "Oli Evans ", "Orie Steele ", + "Paul Cowgill ", "Pedro Santos ", "Pedro Santos ", "Pedro Teixeira ", From 7042ea190c032b940763975b6553853258919dd6 Mon Sep 17 00:00:00 2001 From: achingbrain Date: Thu, 9 Jan 2020 11:42:35 +0000 Subject: [PATCH 209/233] chore: release version v40.2.0 --- CHANGELOG.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index af8c75cd7..c41311373 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,13 @@ + +# [40.2.0](https://github.com/ipfs/js-ipfs-http-client/compare/v40.1.0...v40.2.0) (2020-01-09) + + +### Features + +* support UnixFSv1.5 metadata ([#1186](https://github.com/ipfs/js-ipfs-http-client/issues/1186)) ([da9d17a](https://github.com/ipfs/js-ipfs-http-client/commit/da9d17a)) + + + # [40.1.0](https://github.com/ipfs/js-ipfs-http-client/compare/v40.0.1...v40.1.0) (2019-12-10) From 8565018b890c88e73705e9cbe3573c953c395e1f Mon Sep 17 00:00:00 2001 From: achingbrain Date: Thu, 9 Jan 2020 16:59:01 +0000 Subject: [PATCH 210/233] chore: update multicodec dep to stable version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d0b0d7783..66ceca2fc 100644 --- a/package.json +++ b/package.json @@ -70,7 +70,7 @@ "multiaddr": "^6.0.6", "multiaddr-to-uri": "^5.0.0", "multibase": "~0.6.0", - "multicodec": "~0.5.1", + "multicodec": "^1.0.0", "multihashes": "~0.4.14", "parse-duration": "^0.1.1", "peer-id": "~0.12.3", From 3651baba3e1b704c5c4c862c47e45602590f5ab8 Mon Sep 17 00:00:00 2001 From: achingbrain Date: Thu, 9 Jan 2020 17:56:11 +0000 Subject: [PATCH 211/233] chore: update contributors --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 66ceca2fc..901ca797f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ipfs-http-client", - "version": "40.2.0", + "version": "40.2.1", "description": "A client library for the IPFS HTTP API", "keywords": [ "ipfs" @@ -100,7 +100,6 @@ "Alan Shaw ", "Alan Shaw ", "Alex Mingoia ", - "Alex Potsides ", "Antonio Tenorio-Fornés ", "Bruno Barbieri ", "Clemo ", @@ -178,6 +177,7 @@ "Victor Bjelkholm ", "Volker Mische ", "Zhiyuan Lin ", + "achingbrain ", "dirkmc ", "dmitriy ryajov ", "elsehow ", From ed43408d53f65c61f234acdeeb05a3acfa1b6677 Mon Sep 17 00:00:00 2001 From: achingbrain Date: Thu, 9 Jan 2020 17:56:11 +0000 Subject: [PATCH 212/233] chore: release version v40.2.1 --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c41311373..8d6712433 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ + +## [40.2.1](https://github.com/ipfs/js-ipfs-http-client/compare/v40.2.0...v40.2.1) (2020-01-09) + + + # [40.2.0](https://github.com/ipfs/js-ipfs-http-client/compare/v40.1.0...v40.2.0) (2020-01-09) From 13f8d7ae3510ef6a4156f3b947973549fb1b529f Mon Sep 17 00:00:00 2001 From: Alex Potsides Date: Sat, 11 Jan 2020 23:23:07 +0100 Subject: [PATCH 213/233] fix: return CIDs from files.flush (#1216) * fix: return CIDs from files.flush * chore: remove gh url --- package.json | 2 +- src/files/flush.js | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 901ca797f..416066e32 100644 --- a/package.json +++ b/package.json @@ -84,7 +84,7 @@ "cross-env": "^6.0.0", "detect-node": "^2.0.4", "go-ipfs-dep": "^0.4.22", - "interface-ipfs-core": "^0.126.0", + "interface-ipfs-core": "^0.127.0", "ipfsd-ctl": "^1.0.0", "ndjson": "^1.5.0", "nock": "^11.4.0", diff --git a/src/files/flush.js b/src/files/flush.js index ab2062387..34e725814 100644 --- a/src/files/flush.js +++ b/src/files/flush.js @@ -1,6 +1,7 @@ 'use strict' const configure = require('../lib/configure') +const CID = require('cids') module.exports = configure(({ ky }) => { return async (path, options) => { @@ -14,11 +15,13 @@ module.exports = configure(({ ky }) => { const searchParams = new URLSearchParams(options.searchParams) searchParams.set('arg', path) - await ky.post('files/flush', { + const res = await ky.post('files/flush', { timeout: options.timeout, signal: options.signal, headers: options.headers, searchParams - }).text() + }).json() + + return new CID(res.Cid) } }) From 4ef26cdedd81a0b82d667ac2c4c1b3fb4e4bc1e4 Mon Sep 17 00:00:00 2001 From: Alex Potsides Date: Sun, 12 Jan 2020 07:12:05 +0100 Subject: [PATCH 214/233] refactor: removes format option (#1218) BREAKING CHANGE: `format` option is no longer supported as everything is `dag-pb` all of the time. Follows on from https://github.com/ipfs/js-ipfs-mfs/pull/69 --- src/files/chmod.js | 1 - src/files/cp.js | 1 - src/files/mkdir.js | 1 - src/files/mv.js | 1 - src/files/touch.js | 1 - 5 files changed, 5 deletions(-) diff --git a/src/files/chmod.js b/src/files/chmod.js index b4c0a11dd..3979d4622 100644 --- a/src/files/chmod.js +++ b/src/files/chmod.js @@ -10,7 +10,6 @@ module.exports = configure(({ ky }) => { const searchParams = new URLSearchParams(options.searchParams) searchParams.append('arg', path) searchParams.append('mode', modeToString(mode)) - if (options.format) searchParams.set('format', options.format) if (options.flush != null) searchParams.set('flush', options.flush) if (options.hashAlg) searchParams.set('hash', options.hashAlg) if (options.parents != null) searchParams.set('parents', options.parents) diff --git a/src/files/cp.js b/src/files/cp.js index 812c8b7d7..f9ed0bb20 100644 --- a/src/files/cp.js +++ b/src/files/cp.js @@ -10,7 +10,6 @@ module.exports = configure(({ ky }) => { const searchParams = new URLSearchParams(options.searchParams) sources.forEach(src => searchParams.append('arg', CID.isCID(src) ? `/ipfs/${src}` : src)) - if (options.format) searchParams.set('format', options.format) if (options.flush != null) searchParams.set('flush', options.flush) if (options.hashAlg) searchParams.set('hash', options.hashAlg) if (options.parents != null) searchParams.set('parents', options.parents) diff --git a/src/files/mkdir.js b/src/files/mkdir.js index 3a50c7728..382c62b22 100644 --- a/src/files/mkdir.js +++ b/src/files/mkdir.js @@ -12,7 +12,6 @@ module.exports = configure(({ ky }) => { const searchParams = new URLSearchParams(options.searchParams) searchParams.append('arg', path) if (options.cidVersion != null) searchParams.set('cid-version', options.cidVersion) - if (options.format) searchParams.set('format', options.format) if (options.flush != null) searchParams.set('flush', options.flush) if (options.hashAlg) searchParams.set('hash', options.hashAlg) if (options.parents != null) searchParams.set('parents', options.parents) diff --git a/src/files/mv.js b/src/files/mv.js index fadf0c34c..78560dfeb 100644 --- a/src/files/mv.js +++ b/src/files/mv.js @@ -10,7 +10,6 @@ module.exports = configure(({ ky }) => { const searchParams = new URLSearchParams(options.searchParams) sources.forEach(src => searchParams.append('arg', CID.isCID(src) ? `/ipfs/${src}` : src)) - if (options.format) searchParams.set('format', options.format) if (options.flush != null) searchParams.set('flush', options.flush) if (options.hashAlg) searchParams.set('hash', options.hashAlg) if (options.parents != null) searchParams.set('parents', options.parents) diff --git a/src/files/touch.js b/src/files/touch.js index b38aca905..c4189ecab 100644 --- a/src/files/touch.js +++ b/src/files/touch.js @@ -14,7 +14,6 @@ module.exports = configure(({ ky }) => { searchParams.set('mtime', mtime.secs) searchParams.set('mtimeNsecs', mtime.nsecs) } - if (options.format) searchParams.set('format', options.format) if (options.flush != null) searchParams.set('flush', options.flush) if (options.hashAlg) searchParams.set('hash', options.hashAlg) if (options.parents != null) searchParams.set('parents', options.parents) From 17466baccfaf2cb5b24483c5dc7e4896799d5113 Mon Sep 17 00:00:00 2001 From: achingbrain Date: Sun, 12 Jan 2020 09:31:31 +0100 Subject: [PATCH 215/233] chore: update contributors --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 416066e32..6ba92841e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ipfs-http-client", - "version": "40.2.1", + "version": "41.0.0", "description": "A client library for the IPFS HTTP API", "keywords": [ "ipfs" @@ -100,6 +100,7 @@ "Alan Shaw ", "Alan Shaw ", "Alex Mingoia ", + "Alex Potsides ", "Antonio Tenorio-Fornés ", "Bruno Barbieri ", "Clemo ", @@ -177,7 +178,6 @@ "Victor Bjelkholm ", "Volker Mische ", "Zhiyuan Lin ", - "achingbrain ", "dirkmc ", "dmitriy ryajov ", "elsehow ", From d7eb0e8ffb15e207a8a6062e292a3b5babf35a9e Mon Sep 17 00:00:00 2001 From: achingbrain Date: Sun, 12 Jan 2020 09:31:31 +0100 Subject: [PATCH 216/233] chore: release version v41.0.0 --- CHANGELOG.md | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8d6712433..50a33bbfa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,26 @@ + +# [41.0.0](https://github.com/ipfs/js-ipfs-http-client/compare/v40.2.1...v41.0.0) (2020-01-12) + + +### Bug Fixes + +* return CIDs from files.flush ([#1216](https://github.com/ipfs/js-ipfs-http-client/issues/1216)) ([13f8d7a](https://github.com/ipfs/js-ipfs-http-client/commit/13f8d7a)) + + +### Code Refactoring + +* removes format option ([#1218](https://github.com/ipfs/js-ipfs-http-client/issues/1218)) ([4ef26cd](https://github.com/ipfs/js-ipfs-http-client/commit/4ef26cd)) + + +### BREAKING CHANGES + +* `format` option is no longer supported as everything is `dag-pb` all +of the time. + +Follows on from https://github.com/ipfs/js-ipfs-mfs/pull/69 + + + ## [40.2.1](https://github.com/ipfs/js-ipfs-http-client/compare/v40.2.0...v40.2.1) (2020-01-09) From 86eba683abebf48bd68e584287ab0225a8694eb3 Mon Sep 17 00:00:00 2001 From: Alex Potsides Date: Thu, 23 Jan 2020 07:08:16 +0000 Subject: [PATCH 217/233] test: adds tests for metadata with mfs stat and files.add (#1221) * test: adds tests for metadata with mfs stat and files.add * chore: remove gh url --- package.json | 2 +- src/add/index.js | 13 ++++++++++--- src/files/cp.js | 1 + src/files/mkdir.js | 1 + src/files/mv.js | 1 + src/files/rm.js | 1 + src/files/write.js | 1 + test/interface.spec.js | 24 ++++++++++++++++++++++++ 8 files changed, 40 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 6ba92841e..3d0e8bacb 100644 --- a/package.json +++ b/package.json @@ -84,7 +84,7 @@ "cross-env": "^6.0.0", "detect-node": "^2.0.4", "go-ipfs-dep": "^0.4.22", - "interface-ipfs-core": "^0.127.0", + "interface-ipfs-core": "^0.128.0", "ipfsd-ctl": "^1.0.0", "ndjson": "^1.5.0", "nock": "^11.4.0", diff --git a/src/add/index.js b/src/add/index.js index 546e5428d..e8b3c22f0 100644 --- a/src/add/index.js +++ b/src/add/index.js @@ -42,7 +42,7 @@ module.exports = configure(({ ky }) => { for await (let file of ndjson(toIterable(res.body))) { file = toCamel(file) - // console.log(file) + if (options.progress && file.bytes) { options.progress(file.bytes) } else { @@ -52,16 +52,23 @@ module.exports = configure(({ ky }) => { } }) -function toCoreInterface ({ name, hash, size, mode, mtime }) { +function toCoreInterface ({ name, hash, size, mode, mtime, mtimeNsecs }) { const output = { path: name, hash, size: parseInt(size) } - if (mode !== undefined) { + if (mode != null) { output.mode = parseInt(mode, 8) } + if (mtime != null) { + output.mtime = { + secs: mtime, + nsecs: mtimeNsecs || 0 + } + } + return output } diff --git a/src/files/cp.js b/src/files/cp.js index f9ed0bb20..ce68aa588 100644 --- a/src/files/cp.js +++ b/src/files/cp.js @@ -13,6 +13,7 @@ module.exports = configure(({ ky }) => { if (options.flush != null) searchParams.set('flush', options.flush) if (options.hashAlg) searchParams.set('hash', options.hashAlg) if (options.parents != null) searchParams.set('parents', options.parents) + if (options.shardSplitThreshold != null) searchParams.set('shardSplitThreshold', options.shardSplitThreshold) return ky.post('files/cp', { timeout: options.timeout, diff --git a/src/files/mkdir.js b/src/files/mkdir.js index 382c62b22..7083d4b40 100644 --- a/src/files/mkdir.js +++ b/src/files/mkdir.js @@ -15,6 +15,7 @@ module.exports = configure(({ ky }) => { if (options.flush != null) searchParams.set('flush', options.flush) if (options.hashAlg) searchParams.set('hash', options.hashAlg) if (options.parents != null) searchParams.set('parents', options.parents) + if (options.shardSplitThreshold != null) searchParams.set('shardSplitThreshold', options.shardSplitThreshold) if (mtime) { searchParams.set('mtime', mtime.secs) diff --git a/src/files/mv.js b/src/files/mv.js index 78560dfeb..5b0efbc89 100644 --- a/src/files/mv.js +++ b/src/files/mv.js @@ -13,6 +13,7 @@ module.exports = configure(({ ky }) => { if (options.flush != null) searchParams.set('flush', options.flush) if (options.hashAlg) searchParams.set('hash', options.hashAlg) if (options.parents != null) searchParams.set('parents', options.parents) + if (options.shardSplitThreshold != null) searchParams.set('shardSplitThreshold', options.shardSplitThreshold) return ky.post('files/mv', { timeout: options.timeout, diff --git a/src/files/rm.js b/src/files/rm.js index c0a5e7eab..ebfbd4061 100644 --- a/src/files/rm.js +++ b/src/files/rm.js @@ -10,6 +10,7 @@ module.exports = configure(({ ky }) => { searchParams.append('arg', path) if (options.recursive != null) searchParams.set('recursive', options.recursive) if (options.force != null) searchParams.set('force', options.force) + if (options.shardSplitThreshold != null) searchParams.set('shardSplitThreshold', options.shardSplitThreshold) return ky.post('files/rm', { timeout: options.timeout, diff --git a/src/files/write.js b/src/files/write.js index e31f0a8a2..a91c920a7 100644 --- a/src/files/write.js +++ b/src/files/write.js @@ -21,6 +21,7 @@ module.exports = configure(({ ky }) => { if (options.parents != null) searchParams.set('parents', options.parents) if (options.rawLeaves != null) searchParams.set('raw-leaves', options.rawLeaves) if (options.truncate != null) searchParams.set('truncate', options.truncate) + if (options.shardSplitThreshold != null) searchParams.set('shardSplitThreshold', options.shardSplitThreshold) if (mtime) { searchParams.set('mtime', mtime.secs) diff --git a/test/interface.spec.js b/test/interface.spec.js index e09cac5a6..796c1ae86 100644 --- a/test/interface.spec.js +++ b/test/interface.spec.js @@ -242,6 +242,30 @@ describe('interface-ipfs-core tests', () => { { name: 'should write file and specify mtime as hrtime', reason: 'TODO not implemented in go-ipfs yet' + }, + { + name: 'should stat file with mode', + reason: 'TODO not implemented in go-ipfs yet' + }, + { + name: 'should stat file with mtime', + reason: 'TODO not implemented in go-ipfs yet' + }, + { + name: 'should stat dir with mode', + reason: 'TODO not implemented in go-ipfs yet' + }, + { + name: 'should stat dir with mtime', + reason: 'TODO not implemented in go-ipfs yet' + }, + { + name: 'should stat sharded dir with mode', + reason: 'TODO not implemented in go-ipfs yet' + }, + { + name: 'should stat sharded dir with mtime', + reason: 'TODO not implemented in go-ipfs yet' } ] }) From 410de4bbcf48a6aba1dcf1a6f7e57b83e2d80a00 Mon Sep 17 00:00:00 2001 From: achingbrain Date: Thu, 23 Jan 2020 09:35:19 +0000 Subject: [PATCH 218/233] chore: update contributors --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3d0e8bacb..033449aad 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ipfs-http-client", - "version": "41.0.0", + "version": "41.0.1", "description": "A client library for the IPFS HTTP API", "keywords": [ "ipfs" From 435e1325d519ba0815df3a199bb8b5e7838018fc Mon Sep 17 00:00:00 2001 From: achingbrain Date: Thu, 23 Jan 2020 09:35:20 +0000 Subject: [PATCH 219/233] chore: release version v41.0.1 --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 50a33bbfa..55592d9dc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ + +## [41.0.1](https://github.com/ipfs/js-ipfs-http-client/compare/v41.0.0...v41.0.1) (2020-01-23) + + + # [41.0.0](https://github.com/ipfs/js-ipfs-http-client/compare/v40.2.1...v41.0.0) (2020-01-12) From 8a6bfde4a2cd1fbef03cdceb0ff987912237dd26 Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Thu, 23 Jan 2020 20:18:39 +0000 Subject: [PATCH 220/233] refactor: async iterables (#1183) TLDR; * Remove Node.js streams and pull streams * Remove callbacks * Remove `peer-info` and `peer-id` --- Now that internals are all async/await/iterables and `fetch` the next step is to bubble up that goodness to the core API, removing the multiple stream APIs and removing callback support. I'm also proposing removing `peer-info` and `peer-id`, since these drastically increase the bundle size by pulling in `libp2p-crypto`, for which 99% of it's capability is unused. In place of `peer-id` we return a `CID`, which can easily be converted to a `PeerId` instance via: ```js const peerId = PeerId.createFromCID(peerCid) ``` In place of `peer-info` we return an object `{ id: CID, addrs: Multiaddr[] }`, which can easily be converted to a `PeerInfo` like: ```js const peerInfo = new PeerInfo(PeerId.createFromCID(info.id)) info.addrs.forEach(addr => peerInfo.multiaddrs.add(addr)) ``` refs https://github.com/ipfs/js-ipfs/issues/1670 refs https://github.com/ipfs/js-ipfs/issues/2611 refs https://github.com/ipfs/interface-js-ipfs-core/issues/394 TODO: * [x] Refactor local tests * [x] Remove `addFromFs` and `addFromUrl` and export `globSource` and `urlSource` instead * [x] Refactor `interface-ipfs-core` tests * [x] Document new APIs in `interface-ipfs-core` * [x] Update README with API changes * [x] [Document upgrade path from Node.js/pull streams to async iterables](https://gist.github.com/alanshaw/04b2ddc35a6fff25c040c011ac6acf26) Depends on: * [x] https://github.com/ipfs/js-ipfs-utils/pull/15 * [x] https://github.com/ipfs/interface-js-ipfs-core/pull/567 BREAKING CHANGE: Callbacks are no longer supported on any API methods. Please use a utility such as [`callbackify`](https://www.npmjs.com/package/callbackify) on API methods that return Promises to emulate previous behaviour. BREAKING CHANGE: `PeerId` and `PeerInfo` classes are no longer statically exported from `ipfs-http-client` since they are no longer used internally. BREAKING CHANGE: `pin.add` results now contain a `cid` property (a [CID instance](https://github.com/multiformats/js-cid)) instead of a string `hash` property. BREAKING CHANGE: `pin.ls` now returns an async iterable. BREAKING CHANGE: `pin.ls` results now contain a `cid` property (a [CID instance](https://github.com/multiformats/js-cid)) instead of a string `hash` property. BREAKING CHANGE: `pin.rm` results now contain a `cid` property (a [CID instance](https://github.com/multiformats/js-cid)) instead of a string `hash` property. BREAKING CHANGE: `add` now returns an async iterable. BREAKING CHANGE: `add` results now contain a `cid` property (a [CID instance](https://github.com/multiformats/js-cid)) instead of a string `hash` property. BREAKING CHANGE: `addReadableStream`, `addPullStream` have been removed. BREAKING CHANGE: `ls` now returns an async iterable. BREAKING CHANGE: `ls` results now contain a `cid` property (whose value is a [CID instance](https://github.com/multiformats/js-cid)) instead of a `hash` property. BREAKING CHANGE: `files.ls` now returns an async iterable. BREAKING CHANGE: `files.readPullStream` and `files.readReadableStream` have been removed. BREAKING CHANGE: `files.read` now returns an async iterable. BREAKING CHANGE: `files.lsPullStream` and `files.lsReadableStream` have been removed. BREAKING CHANGE: `files.ls` now returns an async iterable. BREAKING CHANGE: `files.ls` results now contain a `cid` property (whose value is a [CID instance](https://github.com/multiformats/js-cid)) instead of a `hash` property. BREAKING CHANGE: `files.ls` no longer takes a `long` option (in core) - you will receive all data by default. BREAKING CHANGE: `files.stat` result now contains a `cid` property (whose value is a [CID instance](https://github.com/multiformats/js-cid)) instead of a `hash` property. BREAKING CHANGE: `get` now returns an async iterable. The `content` property value for objects yielded from the iterator is now an async iterable that yields [`BufferList`](https://github.com/rvagg/bl) objects. BREAKING CHANGE: `stats.bw` now returns an async iterable. BREAKING CHANGE: `addFromStream` has been removed. Use `add` instead. BREAKING CHANGE: `isIPFS` is no longer exported from the client, please `npm i is-ipfs` or include the CDN script tag `` to use this utility in your applications. BREAKING CHANGE: `addFromFs` has been removed. Please use the exported `globSource` utility and pass the result to `add`. See the [glob source documentation](https://github.com/ipfs/js-ipfs-http-client#glob-source) for more details and an example. BREAKING CHANGE: `addFromURL` has been removed. Please use the exported `urlSource` utility and pass the result to `add`. See the [URL source documentation](https://github.com/ipfs/js-ipfs-http-client#url-source) for more details and an example. BREAKING CHANGE: `name.resolve` now returns an async iterable. It yields increasingly more accurate resolved values as they are discovered until the best value is selected from the quorum of 16. The "best" resolved value is the last item yielded from the iterator. If you are interested only in this best value you could use `it-last` to extract it like so: ```js const last = require('it-last') await last(ipfs.name.resolve('/ipns/QmHash')) ``` BREAKING CHANGE: `block.rm` now returns an async iterable. BREAKING CHANGE: `block.rm` now yields objects of `{ cid: CID, error: Error }`. BREAKING CHANGE: `dht.findProvs`, `dht.provide`, `dht.put` and `dht.query` now all return an async iterable. BREAKING CHANGE: `dht.findPeer`, `dht.findProvs`, `dht.provide`, `dht.put` and `dht.query` now yield/return an object `{ id: CID, addrs: Multiaddr[] }` instead of a `PeerInfo` instance(s). BREAKING CHANGE: `refs` and `refs.local` now return an async iterable. BREAKING CHANGE: `object.data` now returns an async iterable that yields `Buffer` objects. BREAKING CHANGE: `ping` now returns an async iterable. BREAKING CHANGE: `repo.gc` now returns an async iterable. BREAKING CHANGE: `swarm.peers` now returns an array of objects with a `peer` property that is a `CID`, instead of a `PeerId` instance. BREAKING CHANGE: `swarm.addrs` now returns an array of objects `{ id: CID, addrs: Multiaddr[] }` instead of `PeerInfo` instances. BREAKING CHANGE: `block.stat` result now contains a `cid` property (whose value is a [CID instance](https://github.com/multiformats/js-cid)) instead of a `key` property. BREAKING CHANGE: `bitswap.wantlist` now returns an array of [CID](https://github.com/multiformats/js-cid) instances. BREAKING CHANGE: `bitswap.stat` result has changed - `wantlist` and `peers` values are now an array of [CID](https://github.com/multiformats/js-cid) instances. --- README.md | 107 +++++++++++----- package.json | 47 +++---- src/add-from-fs/index.browser.js | 3 - src/add-from-fs/index.js | 8 -- src/add-from-url.js | 21 ---- src/add/index.js | 5 +- src/bitswap/index.js | 10 +- src/bitswap/stat.js | 5 +- src/bitswap/wantlist.js | 2 +- src/block/index.js | 27 +--- src/block/{rm-async-iterator.js => rm.js} | 17 ++- src/block/stat.js | 3 +- src/bootstrap/index.js | 8 +- src/cat.js | 2 +- src/config/index.js | 8 +- src/config/profiles/index.js | 6 +- src/dag/index.js | 8 +- src/dht/find-peer.js | 28 +++-- src/dht/find-provs.js | 21 ++-- src/dht/get.js | 27 ++-- src/dht/index.js | 37 ++---- src/dht/provide.js | 26 ++-- src/dht/put.js | 23 ++-- src/dht/query.js | 19 ++- src/diag/index.js | 8 +- src/files/index.js | 38 ++---- src/files/ls.js | 21 ++-- src/files/read.js | 2 +- src/files/stat.js | 10 +- src/get.js | 2 +- src/index.js | 144 +++------------------- src/key/index.js | 14 +-- src/lib/converters.js | 20 --- src/lib/stream-to-iterable.js | 25 ---- src/log/index.js | 6 +- src/log/tail.js | 2 +- src/ls.js | 82 ++++++------ src/name/index.js | 6 +- src/name/pubsub/index.js | 8 +- src/name/resolve.js | 11 +- src/object/data.js | 11 +- src/object/index.js | 15 +-- src/object/patch/index.js | 10 +- src/pin/add.js | 8 +- src/pin/index.js | 8 +- src/pin/ls.js | 20 ++- src/pin/rm.js | 3 +- src/ping.js | 2 +- src/pubsub/index.js | 55 ++------- src/pubsub/subscribe.js | 6 +- src/refs/index.js | 2 +- src/refs/local.js | 2 +- src/repo/gc.js | 2 +- src/repo/index.js | 9 +- src/stats/bw.js | 2 +- src/stats/index.js | 22 +--- src/swarm/addrs.js | 12 +- src/swarm/disconnect.js | 2 +- src/swarm/index.js | 12 +- src/swarm/peers.js | 4 +- test/custom-headers.spec.js | 2 +- test/exports.spec.js | 6 - test/files-mfs.spec.js | 105 ++++++++-------- test/get.spec.js | 28 +++-- test/interface.spec.js | 143 +++++++++------------ test/lib.stream-to-iterable.spec.js | 40 ------ test/log.spec.js | 3 +- test/node/swarm.js | 4 +- test/ping.spec.js | 42 +------ test/request-api.spec.js | 73 +++++------ test/stats.spec.js | 3 +- test/sub-modules.spec.js | 19 --- test/utils/expect-timeout.js | 16 --- 73 files changed, 601 insertions(+), 957 deletions(-) delete mode 100644 src/add-from-fs/index.browser.js delete mode 100644 src/add-from-fs/index.js delete mode 100644 src/add-from-url.js rename src/block/{rm-async-iterator.js => rm.js} (76%) delete mode 100644 src/lib/converters.js delete mode 100644 src/lib/stream-to-iterable.js delete mode 100644 test/lib.stream-to-iterable.spec.js delete mode 100644 test/utils/expect-timeout.js diff --git a/README.md b/README.md index 9c6d3a3c7..88ed592f8 100644 --- a/README.md +++ b/README.md @@ -53,6 +53,8 @@ - [Additional Options](#additional-options) - [Instance Utils](#instance-utils) - [Static Types and Utils](#static-types-and-utils) + - [Glob source](#glob-source) + - [URL source](#url-source) - [Development](#development) - [Testing](#testing) - [Contribute](#contribute) @@ -210,34 +212,20 @@ const ipfs = ipfsClient({ timeout: '2m' }) - [Regular Files API](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md) - [`ipfs.add(data, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#add) - - [`ipfs.addPullStream([options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#addpullstream) - - [`ipfs.addReadableStream([options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#addreadablestream) - - [`ipfs.addFromStream(stream)`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#addfromstream) - - [`ipfs.addFromFs(path, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#addfromfs) - - [`ipfs.addFromURL(url, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#addfromurl) - [`ipfs.cat(ipfsPath, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#cat) - - [`ipfs.catPullStream(ipfsPath, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#catpullstream) - - [`ipfs.catReadableStream(ipfsPath, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#catreadablestream) - [`ipfs.get(ipfsPath, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#get) - - [`ipfs.getPullStream(ipfsPath, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#getpullstream) - - [`ipfs.getReadableStream(ipfsPath, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#getreadablestream) - [`ipfs.ls(ipfsPath)`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#ls) - - [`ipfs.lsPullStream(ipfsPath)`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#lspullstream) - - [`ipfs.lsReadableStream(ipfsPath)`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#lsreadablestream) - [MFS (mutable file system) specific](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#mutable-file-system) - - _Explore the Mutable File System through interactive coding challenges in our [ProtoSchool tutorial](https://proto.school/#/mutable-file-system/)._ - [`ipfs.files.cp([from, to])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#filescp) - [`ipfs.files.flush([path])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#filesflush) - [`ipfs.files.ls([path], [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#filesls) - [`ipfs.files.mkdir(path, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#filesmkdir) - [`ipfs.files.mv([from, to])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#filesmv) - [`ipfs.files.read(path, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#filesread) - - [`ipfs.files.readPullStream(path, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#filesreadpullstream) - - [`ipfs.files.readReadableStream(path, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#filesreadreadablestream) - [`ipfs.files.rm(path, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#filesrm) - [`ipfs.files.stat(path, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#filesstat) - [`ipfs.files.write(path, content, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#fileswrite) + _Explore the Mutable File System through interactive coding challenges in our [ProtoSchool tutorial](https://proto.school/#/mutable-file-system/)._ - [block](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/BLOCK.md) - [`ipfs.block.get(cid, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/BLOCK.md#blockget) @@ -246,20 +234,15 @@ const ipfs = ipfsClient({ timeout: '2m' }) - [refs](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/REFS.md) - [`ipfs.refs(ipfsPath, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/REFS.md#refs) - - [`ipfs.refsReadableStream(ipfsPath, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/REFS.md#refsreadablestream) - - [`ipfs.refsPullStream(ipfsPath, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/REFS.md#refspullstream) - [`ipfs.refs.local()`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/REFS.md#refslocal) - - [`ipfs.refs.localReadableStream()`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/REFS.md#refslocalreadablestream) - - [`ipfs.refs.localPullStream()`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/REFS.md#refslocalpullstream) #### Graph - [dag](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/DAG.md) - - _Explore the DAG API through interactive coding challenges in our [ProtoSchool tutorial](https://proto.school/#/basics)._ - [`ipfs.dag.get(cid, [path], [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/DAG.md#dagget) - [`ipfs.dag.put(dagNode, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/DAG.md#dagput) - [`ipfs.dag.tree(cid, [path], [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/DAG.md#dagtree) + _Explore the DAG API through interactive coding challenges in our [ProtoSchool tutorial](https://proto.school/#/basics)._ - [object](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/OBJECT.md) - [`ipfs.object.data(multihash, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/OBJECT.md#objectdata) @@ -278,9 +261,6 @@ const ipfs = ipfsClient({ timeout: '2m' }) - [`ipfs.pin.ls([hash], [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/PIN.md#pinls) - [`ipfs.pin.rm(hash, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/PIN.md#pinrm) -- refs - - `ipfs.refs.local()` - #### Network - [bootstrap](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/BOOTSTRAP.md) @@ -326,8 +306,6 @@ const ipfs = ipfsClient({ timeout: '2m' }) - [`ipfs.dns(domain)`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/MISCELLANEOUS.md#dns) - [`ipfs.id()`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/MISCELLANEOUS.md#id) - [`ipfs.ping(id, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/MISCELLANEOUS.md#ping) - - [`ipfs.pingPullStream(id, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/MISCELLANEOUS.md#pingpullstream) - - [`ipfs.pingReadableStream(id, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/MISCELLANEOUS.md#pingreadablestream) - [`ipfs.stop()`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/MISCELLANEOUS.md#stop). Alias to `ipfs.shutdown`. - [`ipfs.version()`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/MISCELLANEOUS.md#version) @@ -341,8 +319,6 @@ const ipfs = ipfsClient({ timeout: '2m' }) - [stats](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/STATS.md) - [`ipfs.stats.bitswap()`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/STATS.md#statsbitswap) - [`ipfs.stats.bw([options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/STATS.md#statsbw) - - [`ipfs.stats.bwPullStream([options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/STATS.md#statsbwpullstream) - - [`ipfs.stats.bwReadableStream([options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/STATS.md#statsbwreadablestream) - [`ipfs.stats.repo([options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/STATS.md#statsrepo) - log @@ -382,15 +358,14 @@ Call this on your client instance to return an object containing the `host`, `po Aside from the default export, `ipfs-http-client` exports various types and utilities that are included in the bundle: -- [`isIPFS`](https://www.npmjs.com/package/is-ipfs) - [`Buffer`](https://www.npmjs.com/package/buffer) -- [`PeerId`](https://www.npmjs.com/package/peer-id) -- [`PeerInfo`](https://www.npmjs.com/package/peer-info) - [`multiaddr`](https://www.npmjs.com/package/multiaddr) - [`multibase`](https://www.npmjs.com/package/multibase) - [`multicodec`](https://www.npmjs.com/package/multicodec) -- [`multihash`](https://www.npmjs.com/package/multihash) +- [`multihash`](https://www.npmjs.com/package/multihashes) - [`CID`](https://www.npmjs.com/package/cids) +- [`globSource`](https://github.com/ipfs/js-ipfs-utils/blob/master/src/files/glob-source.js) (not available in the browser) +- [`urlSource`](https://github.com/ipfs/js-ipfs-utils/blob/master/src/files/url-source.js) These can be accessed like this, for example: @@ -400,6 +375,74 @@ const { CID } = require('ipfs-http-client') import { CID } from 'ipfs-http-client' ``` +##### Glob source + +A utility to allow files on the file system to be easily added to IPFS. + +###### `globSource(path, [options])` + +- `path`: A path to a single file or directory to glob from +- `options`: Optional options +- `options.recursive`: If `path` is a directory, use option `{ recursive: true }` to add the directory and all its sub-directories. +- `options.ignore`: To exclude file globs from the directory, use option `{ ignore: ['ignore/this/folder/**', 'and/this/file'] }`. +- `options.hidden`: Hidden/dot files (files or folders starting with a `.`, for example, `.git/`) are not included by default. To add them, use the option `{ hidden: true }`. + +Returns an async iterable that yields `{ path, content }` objects suitable for passing to `ipfs.add`. + +###### Example + +```js +const IpfsHttpClient = require('ipfs-http-client') +const { globSource } = IpfsHttpClient +const ipfs = IpfsHttpClient() + +for await (const file of ipfs.add(globSource('./docs', { recursive: true }))) { + console.log(file) +} +/* +{ + path: 'docs/assets/anchor.js', + cid: CID('QmVHxRocoWgUChLEvfEyDuuD6qJ4PhdDL2dTLcpUy3dSC2'), + size: 15347 +} +{ + path: 'docs/assets/bass-addons.css', + cid: CID('QmPiLWKd6yseMWDTgHegb8T7wVS7zWGYgyvfj7dGNt2viQ'), + size: 232 +} +... +*/ +``` + +##### URL source + +A utility to allow content from the internet to be easily added to IPFS. + +###### `urlSource(url)` + +- `url`: A string URL or [`URL`](https://developer.mozilla.org/en-US/docs/Web/API/URL) instance to send HTTP GET request to + +Returns an async iterable that yields `{ path, content }` objects suitable for passing to `ipfs.add`. + +###### Example + +```js +const IpfsHttpClient = require('ipfs-http-client') +const { urlSource } = IpfsHttpClient +const ipfs = IpfsHttpClient() + +for await (const file of ipfs.add(urlSource('https://ipfs.io/images/ipfs-logo.svg'))) { + console.log(file) +} +/* +{ + path: 'ipfs-logo.svg', + cid: CID('QmTqZhR6f7jzdhLgPArDPnsbZpvvgxzCZycXK7ywkLxSyU'), + size: 3243 +} +*/ +``` + ## Development ### Testing diff --git a/package.json b/package.json index 033449aad..add5c2ebb 100644 --- a/package.json +++ b/package.json @@ -15,13 +15,9 @@ ], "main": "src/index.js", "browser": { - "glob": false, - "fs": false, - "stream": "readable-stream", - "ky-universal": "ky/umd", "./src/add/form-data.js": "./src/add/form-data.browser.js", - "./src/add-from-fs/index.js": "./src/add-from-fs/index.browser.js", - "./src/lib/buffer-to-form-data.js": "./src/lib/buffer-to-form-data.browser.js" + "./src/lib/buffer-to-form-data.js": "./src/lib/buffer-to-form-data.browser.js", + "ipfs-utils/src/files/glob-source": false }, "repository": "github:ipfs/js-ipfs-http-client", "scripts": { @@ -42,55 +38,42 @@ }, "dependencies": { "abort-controller": "^3.0.0", - "async-iterator-to-pull-stream": "^1.3.0", "bignumber.js": "^9.0.0", - "bl": "^4.0.0", "bs58": "^4.0.1", "buffer": "^5.4.2", - "callbackify": "^1.1.0", "cids": "~0.7.1", "debug": "^4.1.0", - "err-code": "^2.0.0", - "explain-error": "^1.0.4", "form-data": "^3.0.0", "ipfs-block": "~0.8.1", - "ipfs-utils": "^0.4.2", - "ipld-dag-cbor": "~0.15.0", - "ipld-dag-pb": "^0.18.1", - "ipld-raw": "^4.0.0", - "is-ipfs": "~0.6.1", - "it-all": "^1.0.1", - "it-glob": "0.0.7", + "ipfs-utils": "^0.7.1", + "ipld-dag-cbor": "^0.15.1", + "ipld-dag-pb": "^0.18.2", + "ipld-raw": "^4.0.1", "it-tar": "^1.1.1", "it-to-stream": "^0.1.1", "iterable-ndjson": "^1.1.0", "ky": "^0.15.0", "ky-universal": "^0.3.0", "merge-options": "^2.0.0", - "multiaddr": "^6.0.6", - "multiaddr-to-uri": "^5.0.0", + "multiaddr": "^7.2.1", + "multiaddr-to-uri": "^5.1.0", "multibase": "~0.6.0", "multicodec": "^1.0.0", "multihashes": "~0.4.14", "parse-duration": "^0.1.1", - "peer-id": "~0.12.3", - "peer-info": "~0.15.1", - "promise-nodeify": "^3.0.1" + "stream-to-it": "^0.2.0" }, "devDependencies": { "aegir": "^20.4.1", "async": "^3.1.0", "browser-process-platform": "~0.1.1", - "cross-env": "^6.0.0", - "detect-node": "^2.0.4", "go-ipfs-dep": "^0.4.22", - "interface-ipfs-core": "^0.128.0", - "ipfsd-ctl": "^1.0.0", - "ndjson": "^1.5.0", - "nock": "^11.4.0", - "pull-stream": "^3.6.14", - "pump": "^3.0.0", - "stream-equal": "^1.1.1" + "interface-ipfs-core": "^0.129.0", + "ipfsd-ctl": "^1.0.2", + "it-all": "^1.0.1", + "it-concat": "^1.0.0", + "it-pipe": "^1.1.0", + "nock": "^11.7.2" }, "engines": { "node": ">=10.3.0", diff --git a/src/add-from-fs/index.browser.js b/src/add-from-fs/index.browser.js deleted file mode 100644 index 81d551294..000000000 --- a/src/add-from-fs/index.browser.js +++ /dev/null @@ -1,3 +0,0 @@ -'use strict' - -module.exports = () => () => { throw new Error('unavailable in the browser') } diff --git a/src/add-from-fs/index.js b/src/add-from-fs/index.js deleted file mode 100644 index 7403f7e46..000000000 --- a/src/add-from-fs/index.js +++ /dev/null @@ -1,8 +0,0 @@ -'use strict' - -const globSource = require('ipfs-utils/src/files/glob-source') - -module.exports = (config) => { - const add = require('../add')(config) - return (path, options) => add(globSource(path, options), options) -} diff --git a/src/add-from-url.js b/src/add-from-url.js deleted file mode 100644 index deb3f4bad..000000000 --- a/src/add-from-url.js +++ /dev/null @@ -1,21 +0,0 @@ -'use strict' - -const kyDefault = require('ky-universal').default -const toIterable = require('./lib/stream-to-iterable') - -module.exports = (config) => { - const add = require('./add')(config) - - return async function * addFromURL (url, options) { - options = options || {} - - const { body } = await kyDefault.get(url) - - const input = { - path: decodeURIComponent(new URL(url).pathname.split('/').pop() || ''), - content: toIterable(body) - } - - yield * add(input, options) - } -} diff --git a/src/add/index.js b/src/add/index.js index e8b3c22f0..cd162c2f9 100644 --- a/src/add/index.js +++ b/src/add/index.js @@ -1,8 +1,9 @@ 'use strict' const ndjson = require('iterable-ndjson') +const CID = require('cids') const configure = require('../lib/configure') -const toIterable = require('../lib/stream-to-iterable') +const toIterable = require('stream-to-it/source') const { toFormData } = require('./form-data') const toCamel = require('../lib/object-to-camel') @@ -55,7 +56,7 @@ module.exports = configure(({ ky }) => { function toCoreInterface ({ name, hash, size, mode, mtime, mtimeNsecs }) { const output = { path: name, - hash, + cid: new CID(hash), size: parseInt(size) } diff --git a/src/bitswap/index.js b/src/bitswap/index.js index fb47d4da0..5c8354498 100644 --- a/src/bitswap/index.js +++ b/src/bitswap/index.js @@ -1,9 +1,7 @@ 'use strict' -const callbackify = require('callbackify') - -module.exports = (config) => ({ - wantlist: callbackify.variadic(require('./wantlist')(config)), - stat: callbackify.variadic(require('./stat')(config)), - unwant: callbackify.variadic(require('./unwant')(config)) +module.exports = config => ({ + wantlist: require('./wantlist')(config), + stat: require('./stat')(config), + unwant: require('./unwant')(config) }) diff --git a/src/bitswap/stat.js b/src/bitswap/stat.js index fee13c355..e041f5d9d 100644 --- a/src/bitswap/stat.js +++ b/src/bitswap/stat.js @@ -2,6 +2,7 @@ const configure = require('../lib/configure') const Big = require('bignumber.js') +const CID = require('cids') module.exports = configure(({ ky }) => { return async (options) => { @@ -21,8 +22,8 @@ module.exports = configure(({ ky }) => { function toCoreInterface (res) { return { provideBufLen: res.ProvideBufLen, - wantlist: res.Wantlist || [], - peers: res.Peers || [], + wantlist: (res.Wantlist || []).map(k => new CID(k['/'])), + peers: (res.Peers || []).map(p => new CID(p)), blocksReceived: new Big(res.BlocksReceived), dataReceived: new Big(res.DataReceived), blocksSent: new Big(res.BlocksSent), diff --git a/src/bitswap/wantlist.js b/src/bitswap/wantlist.js index 6b087db1b..d917d6747 100644 --- a/src/bitswap/wantlist.js +++ b/src/bitswap/wantlist.js @@ -24,6 +24,6 @@ module.exports = configure(({ ky }) => { searchParams }).json() - return res + return (res.Keys || []).map(k => new CID(k['/'])) } }) diff --git a/src/block/index.js b/src/block/index.js index 8c683dd83..f25c73366 100644 --- a/src/block/index.js +++ b/src/block/index.js @@ -1,23 +1,8 @@ 'use strict' -const nodeify = require('promise-nodeify') -const callbackify = require('callbackify') -const { collectify } = require('../lib/converters') - -module.exports = config => { - const rm = require('./rm-async-iterator')(config) - - return { - get: callbackify.variadic(require('./get')(config)), - stat: callbackify.variadic(require('./stat')(config)), - put: callbackify.variadic(require('./put')(config)), - rm: (input, options, callback) => { - if (typeof options === 'function') { - callback = options - options = {} - } - return nodeify(collectify(rm)(input, options), callback) - }, - _rmAsyncIterator: rm - } -} +module.exports = config => ({ + get: require('./get')(config), + stat: require('./stat')(config), + put: require('./put')(config), + rm: require('./rm')(config) +}) diff --git a/src/block/rm-async-iterator.js b/src/block/rm.js similarity index 76% rename from src/block/rm-async-iterator.js rename to src/block/rm.js index e44aedcd2..f8fc8c103 100644 --- a/src/block/rm-async-iterator.js +++ b/src/block/rm.js @@ -3,8 +3,7 @@ const CID = require('cids') const ndjson = require('iterable-ndjson') const configure = require('../lib/configure') -const toIterable = require('../lib/stream-to-iterable') -const toCamel = require('../lib/object-to-camel') +const toIterable = require('stream-to-it/source') module.exports = configure(({ ky }) => { return async function * rm (cid, options) { @@ -31,7 +30,19 @@ module.exports = configure(({ ky }) => { }) for await (const removed of ndjson(toIterable(res.body))) { - yield toCamel(removed) + yield toCoreInterface(removed) } } }) + +function toCoreInterface (removed) { + const out = { + cid: new CID(removed.Hash) + } + + if (removed.Error) { + out.error = new Error(removed.Error) + } + + return out +} diff --git a/src/block/stat.js b/src/block/stat.js index 9063d137c..24b4256fc 100644 --- a/src/block/stat.js +++ b/src/block/stat.js @@ -3,7 +3,6 @@ const CID = require('cids') const { Buffer } = require('buffer') const configure = require('../lib/configure') -const toCamel = require('../lib/object-to-camel') module.exports = configure(({ ky }) => { return async (cid, options) => { @@ -23,6 +22,6 @@ module.exports = configure(({ ky }) => { searchParams }).json() - return toCamel(res) + return { cid: new CID(res.Key), size: res.Size } } }) diff --git a/src/bootstrap/index.js b/src/bootstrap/index.js index 032265803..519a7161e 100644 --- a/src/bootstrap/index.js +++ b/src/bootstrap/index.js @@ -1,9 +1,7 @@ 'use strict' -const callbackify = require('callbackify') - module.exports = config => ({ - add: callbackify.variadic(require('./add')(config)), - rm: callbackify.variadic(require('./rm')(config)), - list: callbackify.variadic(require('./list')(config)) + add: require('./add')(config), + rm: require('./rm')(config), + list: require('./list')(config) }) diff --git a/src/cat.js b/src/cat.js index 32bccf59e..3d4971a1c 100644 --- a/src/cat.js +++ b/src/cat.js @@ -3,7 +3,7 @@ const CID = require('cids') const { Buffer } = require('buffer') const configure = require('./lib/configure') -const toIterable = require('./lib/stream-to-iterable') +const toIterable = require('stream-to-it/source') module.exports = configure(({ ky }) => { return async function * cat (path, options) { diff --git a/src/config/index.js b/src/config/index.js index 36621fd39..cb56190a2 100644 --- a/src/config/index.js +++ b/src/config/index.js @@ -1,10 +1,8 @@ 'use strict' -const callbackify = require('callbackify') - module.exports = config => ({ - get: callbackify.variadic(require('./get')(config)), - set: callbackify.variadic(require('./set')(config)), - replace: callbackify.variadic(require('./replace')(config)), + get: require('./get')(config), + set: require('./set')(config), + replace: require('./replace')(config), profiles: require('./profiles')(config) }) diff --git a/src/config/profiles/index.js b/src/config/profiles/index.js index 57cd1ad7f..77b68de41 100644 --- a/src/config/profiles/index.js +++ b/src/config/profiles/index.js @@ -1,8 +1,6 @@ 'use strict' -const callbackify = require('callbackify') - module.exports = config => ({ - apply: callbackify.variadic(require('./apply')(config)), - list: callbackify.variadic(require('./list')(config)) + apply: require('./apply')(config), + list: require('./list')(config) }) diff --git a/src/dag/index.js b/src/dag/index.js index 06194e4a8..3cc4d410e 100644 --- a/src/dag/index.js +++ b/src/dag/index.js @@ -1,9 +1,7 @@ 'use strict' -const callbackify = require('callbackify') - module.exports = config => ({ - get: callbackify.variadic(require('./get')(config)), - put: callbackify.variadic(require('./put')(config)), - resolve: callbackify.variadic(require('./resolve')(config)) + get: require('./get')(config), + put: require('./put')(config), + resolve: require('./resolve')(config) }) diff --git a/src/dht/find-peer.js b/src/dht/find-peer.js index 71779952c..9d8f517e5 100644 --- a/src/dht/find-peer.js +++ b/src/dht/find-peer.js @@ -1,18 +1,18 @@ 'use strict' -const PeerId = require('peer-id') -const PeerInfo = require('peer-info') +const { Buffer } = require('buffer') +const CID = require('cids') const multiaddr = require('multiaddr') const ndjson = require('iterable-ndjson') const configure = require('../lib/configure') -const toIterable = require('../lib/stream-to-iterable') +const toIterable = require('stream-to-it/source') module.exports = configure(({ ky }) => { - return async function * findPeer (peerId, options) { + return async function findPeer (peerId, options) { options = options || {} const searchParams = new URLSearchParams(options.searchParams) - searchParams.set('arg', `${peerId}`) + searchParams.set('arg', `${Buffer.isBuffer(peerId) ? new CID(peerId) : peerId}`) if (options.verbose != null) searchParams.set('verbose', options.verbose) const res = await ky.post('dht/findpeer', { @@ -23,15 +23,27 @@ module.exports = configure(({ ky }) => { }) for await (const message of ndjson(toIterable(res.body))) { + // 3 = QueryError + // https://github.com/libp2p/go-libp2p-core/blob/6e566d10f4a5447317a66d64c7459954b969bdab/routing/query.go#L18 + // https://github.com/ipfs/go-ipfs/blob/eb11f569b064b960d1aba4b5b8ca155a3bd2cb21/core/commands/dht.go#L388-L389 + if (message.Type === 3) { + throw new Error(message.Extra) + } + // 2 = FinalPeer // https://github.com/libp2p/go-libp2p-core/blob/6e566d10f4a5447317a66d64c7459954b969bdab/routing/query.go#L18 if (message.Type === 2 && message.Responses) { + // There will only be 1: + // https://github.com/ipfs/go-ipfs/blob/eb11f569b064b960d1aba4b5b8ca155a3bd2cb21/core/commands/dht.go#L395-L396 for (const { ID, Addrs } of message.Responses) { - const peerInfo = new PeerInfo(PeerId.createFromB58String(ID)) - if (Addrs) Addrs.forEach(a => peerInfo.multiaddrs.add(multiaddr(a))) - yield peerInfo + return { + id: new CID(ID), + addrs: (Addrs || []).map(a => multiaddr(a)) + } } } } + + throw new Error('not found') } }) diff --git a/src/dht/find-provs.js b/src/dht/find-provs.js index a0fc35722..7adbaf38c 100644 --- a/src/dht/find-provs.js +++ b/src/dht/find-provs.js @@ -1,18 +1,17 @@ 'use strict' -const PeerId = require('peer-id') -const PeerInfo = require('peer-info') +const CID = require('cids') const multiaddr = require('multiaddr') const ndjson = require('iterable-ndjson') const configure = require('../lib/configure') -const toIterable = require('../lib/stream-to-iterable') +const toIterable = require('stream-to-it/source') module.exports = configure(({ ky }) => { return async function * findProvs (cid, options) { options = options || {} const searchParams = new URLSearchParams(options.searchParams) - searchParams.set('arg', `${cid}`) + searchParams.set('arg', `${new CID(cid)}`) if (options.numProviders) searchParams.set('num-providers', options.numProviders) if (options.verbose != null) searchParams.set('verbose', options.verbose) @@ -24,13 +23,21 @@ module.exports = configure(({ ky }) => { }) for await (const message of ndjson(toIterable(res.body))) { + // 3 = QueryError + // https://github.com/libp2p/go-libp2p-core/blob/6e566d10f4a5447317a66d64c7459954b969bdab/routing/query.go#L18 + // https://github.com/libp2p/go-libp2p-kad-dht/blob/master/routing.go#L525-L526 + if (message.Type === 3) { + throw new Error(message.Extra) + } + // 4 = Provider // https://github.com/libp2p/go-libp2p-core/blob/6e566d10f4a5447317a66d64c7459954b969bdab/routing/query.go#L20 if (message.Type === 4 && message.Responses) { for (const { ID, Addrs } of message.Responses) { - const peerInfo = new PeerInfo(PeerId.createFromB58String(ID)) - if (Addrs) Addrs.forEach(a => peerInfo.multiaddrs.add(multiaddr(a))) - yield peerInfo + yield { + id: new CID(ID), + addrs: (Addrs || []).map(a => multiaddr(a)) + } } } } diff --git a/src/dht/get.js b/src/dht/get.js index d2cd0db22..4be7b80c2 100644 --- a/src/dht/get.js +++ b/src/dht/get.js @@ -1,30 +1,43 @@ 'use strict' +const { Buffer } = require('buffer') const ndjson = require('iterable-ndjson') +const toIterable = require('stream-to-it/source') +const encodeBufferURIComponent = require('../lib/encode-buffer-uri-component') const configure = require('../lib/configure') -const toIterable = require('../lib/stream-to-iterable') module.exports = configure(({ ky }) => { - return async function * get (key, options) { + return async function get (key, options) { options = options || {} const searchParams = new URLSearchParams(options.searchParams) - searchParams.set('arg', `${key}`) if (options.verbose != null) searchParams.set('verbose', options.verbose) - const res = await ky.post('dht/get', { + if (!Buffer.isBuffer(key)) { + throw new Error('invalid key') + } + + const res = await ky.post(`dht/get?key=${encodeBufferURIComponent(key)}&${searchParams}`, { timeout: options.timeout, signal: options.signal, - headers: options.headers, - searchParams + headers: options.headers }) for await (const message of ndjson(toIterable(res.body))) { + // 3 = QueryError + // https://github.com/libp2p/go-libp2p-core/blob/6e566d10f4a5447317a66d64c7459954b969bdab/routing/query.go#L18 + // https://github.com/ipfs/go-ipfs/blob/eb11f569b064b960d1aba4b5b8ca155a3bd2cb21/core/commands/dht.go#L472-L473 + if (message.Type === 3) { + throw new Error(message.Extra) + } + // 5 = Value // https://github.com/libp2p/go-libp2p-core/blob/6e566d10f4a5447317a66d64c7459954b969bdab/routing/query.go#L21 if (message.Type === 5) { - yield message.Extra + return message.Extra } } + + throw new Error('not found') } }) diff --git a/src/dht/index.js b/src/dht/index.js index 5478876ff..754e57b83 100644 --- a/src/dht/index.js +++ b/src/dht/index.js @@ -1,30 +1,11 @@ 'use strict' -const callbackify = require('callbackify') -const errCode = require('err-code') -const { collectify } = require('../lib/converters') - -module.exports = config => { - const get = require('./get')(config) - const findPeer = require('./find-peer')(config) - - return { - get: callbackify.variadic(async (key, options) => { - for await (const value of get(key, options)) { - return value - } - throw errCode(new Error('value not found'), 'ERR_TYPE_5_NOT_FOUND') - }), - put: callbackify.variadic(collectify(require('./put')(config))), - findProvs: callbackify.variadic(collectify(require('./find-provs')(config))), - findPeer: callbackify.variadic(async (peerId, options) => { - for await (const peerInfo of findPeer(peerId, options)) { - return peerInfo - } - throw errCode(new Error('final peer not found'), 'ERR_TYPE_2_NOT_FOUND') - }), - provide: callbackify.variadic(collectify(require('./provide')(config))), - // find closest peerId to given peerId - query: callbackify.variadic(collectify(require('./query')(config))) - } -} +module.exports = config => ({ + get: require('./get')(config), + put: require('./put')(config), + findProvs: require('./find-provs')(config), + findPeer: require('./find-peer')(config), + provide: require('./provide')(config), + // find closest peerId to given peerId + query: require('./query')(config) +}) diff --git a/src/dht/provide.js b/src/dht/provide.js index cb72f9c6d..f9013bfed 100644 --- a/src/dht/provide.js +++ b/src/dht/provide.js @@ -1,11 +1,10 @@ 'use strict' -const PeerId = require('peer-id') -const PeerInfo = require('peer-info') +const CID = require('cids') const multiaddr = require('multiaddr') const ndjson = require('iterable-ndjson') const configure = require('../lib/configure') -const toIterable = require('../lib/stream-to-iterable') +const toIterable = require('stream-to-it/source') const toCamel = require('../lib/object-to-camel') module.exports = configure(({ ky }) => { @@ -14,7 +13,7 @@ module.exports = configure(({ ky }) => { options = options || {} const searchParams = new URLSearchParams(options.searchParams) - cids.forEach(cid => searchParams.append('arg', `${cid}`)) + cids.forEach(cid => searchParams.append('arg', `${new CID(cid)}`)) if (options.recursive != null) searchParams.set('recursive', options.recursive) if (options.verbose != null) searchParams.set('verbose', options.verbose) @@ -26,13 +25,22 @@ module.exports = configure(({ ky }) => { }) for await (let message of ndjson(toIterable(res.body))) { + // 3 = QueryError + // https://github.com/libp2p/go-libp2p-core/blob/6e566d10f4a5447317a66d64c7459954b969bdab/routing/query.go#L18 + // https://github.com/ipfs/go-ipfs/blob/eb11f569b064b960d1aba4b5b8ca155a3bd2cb21/core/commands/dht.go#L283-L284 + if (message.Type === 3) { + throw new Error(message.Extra) + } + message = toCamel(message) + message.id = new CID(message.id) if (message.responses) { - message.responses = message.responses.map(({ ID, Addrs }) => { - const peerInfo = new PeerInfo(PeerId.createFromB58String(ID)) - if (Addrs) Addrs.forEach(a => peerInfo.multiaddrs.add(multiaddr(a))) - return peerInfo - }) + message.responses = message.responses.map(({ ID, Addrs }) => ({ + id: new CID(ID), + addrs: (Addrs || []).map(a => multiaddr(a)) + })) + } else { + message.responses = [] } yield message } diff --git a/src/dht/put.js b/src/dht/put.js index 49a6947aa..6d0ecf6fc 100644 --- a/src/dht/put.js +++ b/src/dht/put.js @@ -1,11 +1,11 @@ 'use strict' -const PeerId = require('peer-id') -const PeerInfo = require('peer-info') +const { Buffer } = require('buffer') +const CID = require('cids') const multiaddr = require('multiaddr') const ndjson = require('iterable-ndjson') const configure = require('../lib/configure') -const toIterable = require('../lib/stream-to-iterable') +const toIterable = require('stream-to-it/source') const encodeBufferURIComponent = require('../lib/encode-buffer-uri-component') const toCamel = require('../lib/object-to-camel') @@ -27,13 +27,20 @@ module.exports = configure(({ ky }) => { }) for await (let message of ndjson(toIterable(res.body))) { + // 3 = QueryError + // https://github.com/libp2p/go-libp2p-core/blob/6e566d10f4a5447317a66d64c7459954b969bdab/routing/query.go#L18 + // https://github.com/ipfs/go-ipfs/blob/eb11f569b064b960d1aba4b5b8ca155a3bd2cb21/core/commands/dht.go#L472-L473 + if (message.Type === 3) { + throw new Error(message.Extra) + } + message = toCamel(message) + message.id = new CID(message.id) if (message.responses) { - message.responses = message.responses.map(({ ID, Addrs }) => { - const peerInfo = new PeerInfo(PeerId.createFromB58String(ID)) - if (Addrs) Addrs.forEach(a => peerInfo.multiaddrs.add(multiaddr(a))) - return peerInfo - }) + message.responses = message.responses.map(({ ID, Addrs }) => ({ + id: new CID(ID), + addrs: (Addrs || []).map(a => multiaddr(a)) + })) } yield message } diff --git a/src/dht/query.js b/src/dht/query.js index 5aefaf90d..1628c0cc8 100644 --- a/src/dht/query.js +++ b/src/dht/query.js @@ -1,17 +1,18 @@ 'use strict' -const PeerId = require('peer-id') -const PeerInfo = require('peer-info') +const CID = require('cids') const ndjson = require('iterable-ndjson') +const multiaddr = require('multiaddr') +const toIterable = require('stream-to-it/source') const configure = require('../lib/configure') -const toIterable = require('../lib/stream-to-iterable') +const toCamel = require('../lib/object-to-camel') module.exports = configure(({ ky }) => { return async function * query (peerId, options) { options = options || {} const searchParams = new URLSearchParams(options.searchParams) - searchParams.set('arg', `${peerId}`) + searchParams.set('arg', `${Buffer.isBuffer(peerId) ? new CID(peerId) : peerId}`) if (options.verbose != null) searchParams.set('verbose', options.verbose) const res = await ky.post('dht/query', { @@ -21,8 +22,14 @@ module.exports = configure(({ ky }) => { searchParams }) - for await (const message of ndjson(toIterable(res.body))) { - yield new PeerInfo(PeerId.createFromB58String(message.ID)) + for await (let message of ndjson(toIterable(res.body))) { + message = toCamel(message) + message.id = new CID(message.id) + message.responses = (message.responses || []).map(({ ID, Addrs }) => ({ + id: new CID(ID), + addrs: (Addrs || []).map(a => multiaddr(a)) + })) + yield message } } }) diff --git a/src/diag/index.js b/src/diag/index.js index 7e48d576d..d3ac85d55 100644 --- a/src/diag/index.js +++ b/src/diag/index.js @@ -1,9 +1,7 @@ 'use strict' -const callbackify = require('callbackify') - module.exports = config => ({ - net: callbackify.variadic(require('./net')(config)), - sys: callbackify.variadic(require('./sys')(config)), - cmds: callbackify.variadic(require('./cmds')(config)) + net: require('./net')(config), + sys: require('./sys')(config), + cmds: require('./cmds')(config) }) diff --git a/src/files/index.js b/src/files/index.js index ee6b7d8d8..5dbf395a2 100644 --- a/src/files/index.js +++ b/src/files/index.js @@ -1,27 +1,15 @@ 'use strict' -const callbackify = require('callbackify') -const { collectify, streamify, pullify, concatify } = require('../lib/converters') - -module.exports = config => { - const ls = require('./ls')(config) - const read = require('./read')(config) - - return { - chmod: callbackify.variadic(require('./chmod')(config)), - cp: callbackify.variadic(require('./cp')(config)), - mkdir: callbackify.variadic(require('./mkdir')(config)), - flush: callbackify.variadic(require('./flush')(config)), - stat: callbackify.variadic(require('./stat')(config)), - rm: callbackify.variadic(require('./rm')(config)), - ls: callbackify.variadic(collectify(ls)), - lsReadableStream: streamify.readable(ls), - lsPullStream: pullify.source(ls), - read: callbackify.variadic(concatify(read)), - readReadableStream: streamify.readable(read), - readPullStream: pullify.source(read), - touch: callbackify.variadic(require('./touch')(config)), - write: callbackify.variadic(require('./write')(config)), - mv: callbackify.variadic(require('./mv')(config)) - } -} +module.exports = config => ({ + chmod: require('./chmod')(config), + cp: require('./cp')(config), + mkdir: require('./mkdir')(config), + flush: require('./flush')(config), + stat: require('./stat')(config), + rm: require('./rm')(config), + ls: require('./ls')(config), + read: require('./read')(config), + touch: require('./touch')(config), + write: require('./write')(config), + mv: require('./mv')(config) +}) diff --git a/src/files/ls.js b/src/files/ls.js index 51ee33912..f07c65c09 100644 --- a/src/files/ls.js +++ b/src/files/ls.js @@ -2,7 +2,7 @@ const CID = require('cids') const ndjson = require('iterable-ndjson') -const toIterable = require('../lib/stream-to-iterable') +const toIterable = require('stream-to-it/source') const configure = require('../lib/configure') const toCamelWithMetadata = require('../lib/object-to-camel-with-metadata') @@ -17,9 +17,11 @@ module.exports = configure(({ ky }) => { const searchParams = new URLSearchParams(options.searchParams) searchParams.set('arg', CID.isCID(path) ? `/ipfs/${path}` : path) - searchParams.set('stream', true) + searchParams.set('stream', options.stream == null ? true : options.stream) if (options.cidBase) searchParams.set('cid-base', options.cidBase) - if (options.long != null) searchParams.set('long', options.long) + searchParams.set('long', options.long == null ? true : options.long) + // TODO: remove after go-ipfs 0.5 is released + searchParams.set('l', options.long == null ? true : options.long) const res = await ky.post('files/ls', { timeout: options.timeout, @@ -32,12 +34,17 @@ module.exports = configure(({ ky }) => { // go-ipfs does not yet support the "stream" option if ('Entries' in result) { for (const entry of result.Entries || []) { - yield toCamelWithMetadata(entry) + yield toCoreInterface(toCamelWithMetadata(entry)) } - return + } else { + yield toCoreInterface(toCamelWithMetadata(result)) } - - yield toCamelWithMetadata(result) } } }) + +function toCoreInterface (entry) { + if (entry.hash) entry.cid = new CID(entry.hash) + delete entry.hash + return entry +} diff --git a/src/files/read.js b/src/files/read.js index 5a6a14acb..1800609d0 100644 --- a/src/files/read.js +++ b/src/files/read.js @@ -2,7 +2,7 @@ const { Buffer } = require('buffer') const configure = require('../lib/configure') -const toIterable = require('../lib/stream-to-iterable') +const toIterable = require('stream-to-it/source') module.exports = configure(({ ky }) => { return async function * read (path, options) { diff --git a/src/files/stat.js b/src/files/stat.js index 1b4af061b..0d8c9caa1 100644 --- a/src/files/stat.js +++ b/src/files/stat.js @@ -1,5 +1,6 @@ 'use strict' +const CID = require('cids') const configure = require('../lib/configure') const toCamelWithMetadata = require('../lib/object-to-camel-with-metadata') @@ -27,7 +28,12 @@ module.exports = configure(({ ky }) => { }).json() res.WithLocality = res.WithLocality || false - - return toCamelWithMetadata(res) + return toCoreInterface(toCamelWithMetadata(res)) } }) + +function toCoreInterface (entry) { + entry.cid = new CID(entry.hash) + delete entry.hash + return entry +} diff --git a/src/get.js b/src/get.js index 1a5ebfd93..635f8b34f 100644 --- a/src/get.js +++ b/src/get.js @@ -4,7 +4,7 @@ const configure = require('./lib/configure') const Tar = require('it-tar') const { Buffer } = require('buffer') const CID = require('cids') -const toIterable = require('./lib/stream-to-iterable') +const toIterable = require('stream-to-it/source') module.exports = configure(({ ky }) => { return async function * get (path, options) { diff --git a/src/index.js b/src/index.js index 939f5986f..320a5a9a8 100644 --- a/src/index.js +++ b/src/index.js @@ -1,159 +1,51 @@ 'use strict' -const isIPFS = require('is-ipfs') const { Buffer } = require('buffer') const CID = require('cids') const multiaddr = require('multiaddr') const multibase = require('multibase') const multicodec = require('multicodec') const multihash = require('multihashes') -const PeerId = require('peer-id') -const PeerInfo = require('peer-info') -const nodeify = require('promise-nodeify') -const callbackify = require('callbackify') -const all = require('it-all') -const toPullStream = require('async-iterator-to-pull-stream') -const toStream = require('it-to-stream') -const BufferList = require('bl/BufferList') -const { concatify, collectify, pullify, streamify } = require('./lib/converters') +const globSource = require('ipfs-utils/src/files/glob-source') +const urlSource = require('ipfs-utils/src/files/url-source') function ipfsClient (config) { - const add = require('./add')(config) - const addFromFs = require('./add-from-fs')(config) - const addFromURL = require('./add-from-url')(config) - const cat = require('./cat')(config) - const get = require('./get')(config) - const ls = require('./ls')(config) - const ping = require('./ping')(config) - const refs = require('./refs')(config) - - const api = { - add: (input, options, callback) => { - if (typeof options === 'function') { - callback = options - options = {} - } - return nodeify(collectify(add)(input, options), callback) - }, - addReadableStream: streamify.transform(add), - addPullStream: pullify.transform(add), - addFromFs: (path, options, callback) => { - if (typeof options === 'function') { - callback = options - options = {} - } - return nodeify(collectify(addFromFs)(path, options), callback) - }, - addFromURL: (url, options, callback) => { - if (typeof options === 'function') { - callback = options - options = {} - } - return nodeify(collectify(addFromURL)(url, options), callback) - }, - addFromStream: (input, options, callback) => { - if (typeof options === 'function') { - callback = options - options = {} - } - return nodeify(collectify(add)(input, options), callback) - }, - _addAsyncIterator: add, + return { + add: require('./add')(config), bitswap: require('./bitswap')(config), block: require('./block')(config), bootstrap: require('./bootstrap')(config), - cat: callbackify.variadic((path, options) => concatify(cat)(path, options)), - catReadableStream: streamify.readable(cat), - catPullStream: pullify.source(cat), - _catAsyncIterator: cat, - commands: callbackify.variadic(require('./commands')(config)), + cat: require('./cat')(config), + commands: require('./commands')(config), config: require('./config')(config), dag: require('./dag')(config), dht: require('./dht')(config), diag: require('./diag')(config), - dns: callbackify.variadic(require('./dns')(config)), + dns: require('./dns')(config), files: require('./files')(config), - get: callbackify.variadic(async (path, options) => { - const output = [] - - for await (const entry of get(path, options)) { - if (entry.content) { - entry.content = new BufferList(await all(entry.content)).slice() - } - - output.push(entry) - } - - return output - }), + get: require('./get')(config), getEndpointConfig: require('./get-endpoint-config')(config), - getReadableStream: streamify.readable(async function * (path, options) { - for await (const file of get(path, options)) { - if (file.content) { - const { content } = file - file.content = toStream((async function * () { - for await (const chunk of content) { - yield chunk.slice() // Convert bl to Buffer - } - })()) - } - - yield file - } - }), - getPullStream: pullify.source(async function * (path, options) { - for await (const file of get(path, options)) { - if (file.content) { - const { content } = file - file.content = toPullStream((async function * () { - for await (const chunk of content) { - yield chunk.slice() // Convert bl to Buffer - } - })()) - } - - yield file - } - }), - _getAsyncIterator: get, - id: callbackify.variadic(require('./id')(config)), + id: require('./id')(config), key: require('./key')(config), log: require('./log')(config), - ls: callbackify.variadic((path, options) => collectify(ls)(path, options)), - lsReadableStream: streamify.readable(ls), - lsPullStream: pullify.source(ls), - _lsAsyncIterator: ls, - mount: callbackify.variadic(require('./mount')(config)), + ls: require('./ls')(config), + mount: require('./mount')(config), name: require('./name')(config), object: require('./object')(config), pin: require('./pin')(config), - ping: callbackify.variadic(collectify(ping)), - pingReadableStream: streamify.readable(ping), - pingPullStream: pullify.source(ping), + ping: require('./ping')(config), pubsub: require('./pubsub')(config), - refs: callbackify.variadic((path, options) => collectify(refs)(path, options)), - refsReadableStream: streamify.readable(refs), - refsPullStream: pullify.source(refs), - _refsAsyncIterator: refs, + refs: require('./refs')(config), repo: require('./repo')(config), - resolve: callbackify.variadic(require('./resolve')(config)), + resolve: require('./resolve')(config), stats: require('./stats')(config), - stop: callbackify.variadic(require('./stop')(config)), - shutdown: callbackify.variadic(require('./stop')(config)), + stop: require('./stop')(config), + shutdown: require('./stop')(config), swarm: require('./swarm')(config), - version: callbackify.variadic(require('./version')(config)) + version: require('./version')(config) } - - Object.assign(api.refs, { - local: callbackify.variadic(options => collectify(refs.local)(options)), - localReadableStream: streamify.readable(refs.local), - localPullStream: pullify.source(refs.local), - _localAsyncIterator: refs.local - }) - - return api } -Object.assign(ipfsClient, { isIPFS, Buffer, CID, multiaddr, multibase, multicodec, multihash, PeerId, PeerInfo }) +Object.assign(ipfsClient, { Buffer, CID, multiaddr, multibase, multicodec, multihash, globSource, urlSource }) module.exports = ipfsClient diff --git a/src/key/index.js b/src/key/index.js index 7293236f1..de12c732c 100644 --- a/src/key/index.js +++ b/src/key/index.js @@ -1,12 +1,10 @@ 'use strict' -const callbackify = require('callbackify') - module.exports = config => ({ - gen: callbackify.variadic(require('./gen')(config)), - list: callbackify.variadic(require('./list')(config)), - rename: callbackify.variadic(require('./rename')(config)), - rm: callbackify.variadic(require('./rm')(config)), - export: callbackify.variadic(require('./export')(config)), - import: callbackify.variadic(require('./import')(config)) + gen: require('./gen')(config), + list: require('./list')(config), + rename: require('./rename')(config), + rm: require('./rm')(config), + export: require('./export')(config), + import: require('./import')(config) }) diff --git a/src/lib/converters.js b/src/lib/converters.js deleted file mode 100644 index 4f42b3175..000000000 --- a/src/lib/converters.js +++ /dev/null @@ -1,20 +0,0 @@ -'use strict' - -const toPull = require('async-iterator-to-pull-stream') -const all = require('it-all') -const toStream = require('it-to-stream') -const { Buffer } = require('buffer') - -exports.collectify = fn => (...args) => all(fn(...args)) - -exports.concatify = fn => async (...args) => Buffer.concat(await all(fn(...args))) - -exports.pullify = { - source: fn => (...args) => toPull(fn(...args)), - transform: fn => (...args) => toPull.transform(source => fn(source, ...args)) -} - -exports.streamify = { - readable: fn => (...args) => toStream(fn(...args), { objectMode: true }), - transform: fn => (...args) => toStream.transform(source => fn(source, ...args), { objectMode: true }) -} diff --git a/src/lib/stream-to-iterable.js b/src/lib/stream-to-iterable.js deleted file mode 100644 index 5e06a99c6..000000000 --- a/src/lib/stream-to-iterable.js +++ /dev/null @@ -1,25 +0,0 @@ -'use strict' - -module.exports = function toIterable (body) { - // Node.js stream - if (body[Symbol.asyncIterator]) return body - - // Browser ReadableStream - if (body.getReader) { - return (async function * () { - const reader = body.getReader() - - try { - while (true) { - const { done, value } = await reader.read() - if (done) return - yield value - } - } finally { - reader.releaseLock() - } - })() - } - - throw new Error('unknown stream') -} diff --git a/src/log/index.js b/src/log/index.js index f7d94f910..3eea39fd5 100644 --- a/src/log/index.js +++ b/src/log/index.js @@ -1,9 +1,7 @@ 'use strict' -const callbackify = require('callbackify') - module.exports = config => ({ tail: require('./tail')(config), - ls: callbackify.variadic(require('./ls')(config)), - level: callbackify.variadic(require('./level')(config)) + ls: require('./ls')(config), + level: require('./level')(config) }) diff --git a/src/log/tail.js b/src/log/tail.js index 00708e9b9..74b72b2c2 100644 --- a/src/log/tail.js +++ b/src/log/tail.js @@ -2,7 +2,7 @@ const ndjson = require('iterable-ndjson') const configure = require('../lib/configure') -const toIterable = require('../lib/stream-to-iterable') +const toIterable = require('stream-to-it/source') module.exports = configure(({ ky }) => { return async function * tail (options) { diff --git a/src/ls.js b/src/ls.js index 43e92a54a..ec7e37dfb 100644 --- a/src/ls.js +++ b/src/ls.js @@ -2,6 +2,8 @@ const { Buffer } = require('buffer') const CID = require('cids') +const ndjson = require('iterable-ndjson') +const toIterable = require('stream-to-it/source') const configure = require('./lib/configure') module.exports = configure(({ ky }) => { @@ -10,18 +12,11 @@ module.exports = configure(({ ky }) => { const searchParams = new URLSearchParams() searchParams.set('arg', `${Buffer.isBuffer(path) ? new CID(path) : path}`) + searchParams.set('stream', options.stream == null ? true : options.stream) - if (options.long !== undefined) { - searchParams.set('long', options.long) - } - - if (options.unsorted !== undefined) { - searchParams.set('unsorted', options.unsorted) - } - - if (options.recursive !== undefined) { - searchParams.set('recursive', options.recursive) - } + if (options.long != null) searchParams.set('long', options.long) + if (options.unsorted != null) searchParams.set('unsorted', options.unsorted) + if (options.recursive != null) searchParams.set('recursive', options.recursive) const res = await ky.post('ls', { timeout: options.timeout, @@ -30,48 +25,49 @@ module.exports = configure(({ ky }) => { searchParams }) - let result = await res.json() - - result = result.Objects - if (!result) { - throw new Error('expected .Objects in results') - } - - result = result[0] - if (!result) { - throw new Error('expected one array in results.Objects') - } + for await (let result of ndjson(toIterable(res.body))) { + result = result.Objects - result = result.Links - if (!Array.isArray(result)) { - throw new Error('expected one array in results.Objects[0].Links') - } + if (!result) { + throw new Error('expected .Objects in results') + } - for (const link of result) { - const entry = { - name: link.Name, - path: path + '/' + link.Name, - size: link.Size, - hash: link.Hash, - type: typeOf(link), - depth: link.Depth || 1 + result = result[0] + if (!result) { + throw new Error('expected one array in results.Objects') } - if (link.Mode) { - entry.mode = parseInt(link.Mode, 8) + result = result.Links + if (!Array.isArray(result)) { + throw new Error('expected one array in results.Objects[0].Links') } - if (link.Mtime !== undefined && link.Mtime !== null) { - entry.mtime = { - secs: link.Mtime + for (const link of result) { + const entry = { + name: link.Name, + path: path + '/' + link.Name, + size: link.Size, + cid: new CID(link.Hash), + type: typeOf(link), + depth: link.Depth || 1 } - if (link.MtimeNsecs !== undefined && link.MtimeNsecs !== null) { - entry.mtime.nsecs = link.MtimeNsecs + if (link.Mode) { + entry.mode = parseInt(link.Mode, 8) } - } - yield entry + if (link.Mtime !== undefined && link.Mtime !== null) { + entry.mtime = { + secs: link.Mtime + } + + if (link.MtimeNsecs !== undefined && link.MtimeNsecs !== null) { + entry.mtime.nsecs = link.MtimeNsecs + } + } + + yield entry + } } } }) diff --git a/src/name/index.js b/src/name/index.js index 7a6837b82..65d1acca2 100644 --- a/src/name/index.js +++ b/src/name/index.js @@ -1,9 +1,7 @@ 'use strict' -const callbackify = require('callbackify') - module.exports = config => ({ - publish: callbackify.variadic(require('./publish')(config)), - resolve: callbackify.variadic(require('./resolve')(config)), + publish: require('./publish')(config), + resolve: require('./resolve')(config), pubsub: require('./pubsub')(config) }) diff --git a/src/name/pubsub/index.js b/src/name/pubsub/index.js index 70db19874..14ffd8852 100644 --- a/src/name/pubsub/index.js +++ b/src/name/pubsub/index.js @@ -1,9 +1,7 @@ 'use strict' -const callbackify = require('callbackify') - module.exports = config => ({ - cancel: callbackify.variadic(require('./cancel')(config)), - state: callbackify.variadic(require('./state')(config)), - subs: callbackify.variadic(require('./subs')(config)) + cancel: require('./cancel')(config), + state: require('./state')(config), + subs: require('./subs')(config) }) diff --git a/src/name/resolve.js b/src/name/resolve.js index b6e8db47e..e7eb20b4f 100644 --- a/src/name/resolve.js +++ b/src/name/resolve.js @@ -1,13 +1,16 @@ 'use strict' +const ndjson = require('iterable-ndjson') const configure = require('../lib/configure') +const toIterable = require('stream-to-it/source') module.exports = configure(({ ky }) => { - return async (path, options) => { + return async function * (path, options) { options = options || {} const searchParams = new URLSearchParams(options.searchParams) searchParams.set('arg', path) + searchParams.set('stream', options.stream == null ? true : options.stream) if (options.dhtRecordCount != null) searchParams.set('dht-record-count', options.dhtRecordCount) if (options.dhtTimeout != null) searchParams.set('dht-timeout', options.dhtTimeout) if (options.noCache != null) searchParams.set('nocache', options.noCache) @@ -18,8 +21,10 @@ module.exports = configure(({ ky }) => { signal: options.signal, headers: options.headers, searchParams - }).json() + }) - return res.Path + for await (const result of ndjson(toIterable(res.body))) { + yield result.Path + } } }) diff --git a/src/object/data.js b/src/object/data.js index 48291f722..5f40e0450 100644 --- a/src/object/data.js +++ b/src/object/data.js @@ -3,24 +3,21 @@ const { Buffer } = require('buffer') const CID = require('cids') const configure = require('../lib/configure') -const toIterable = require('../lib/stream-to-iterable') module.exports = configure(({ ky }) => { - return async function * data (cid, options) { + return async function data (cid, options) { options = options || {} const searchParams = new URLSearchParams(options.searchParams) searchParams.set('arg', `${Buffer.isBuffer(cid) ? new CID(cid) : cid}`) - const res = await ky.post('object/data', { + const data = await ky.post('object/data', { timeout: options.timeout, signal: options.signal, headers: options.headers, searchParams - }) + }).arrayBuffer() - for await (const chunk of toIterable(res.body)) { - yield Buffer.from(chunk) - } + return Buffer.from(data) } }) diff --git a/src/object/index.js b/src/object/index.js index dac85598c..ee7c85dd6 100644 --- a/src/object/index.js +++ b/src/object/index.js @@ -1,14 +1,11 @@ 'use strict' -const callbackify = require('callbackify') -const { concatify } = require('../lib/converters') - module.exports = config => ({ - data: callbackify.variadic(concatify(require('./data')(config))), - get: callbackify.variadic(require('./get')(config)), - links: callbackify.variadic(require('./links')(config)), - new: callbackify.variadic(require('./new')(config)), + data: require('./data')(config), + get: require('./get')(config), + links: require('./links')(config), + new: require('./new')(config), patch: require('./patch')(config), - put: callbackify.variadic(require('./put')(config)), - stat: callbackify.variadic(require('./stat')(config)) + put: require('./put')(config), + stat: require('./stat')(config) }) diff --git a/src/object/patch/index.js b/src/object/patch/index.js index 5711200ec..f886e288f 100644 --- a/src/object/patch/index.js +++ b/src/object/patch/index.js @@ -1,10 +1,8 @@ 'use strict' -const callbackify = require('callbackify') - module.exports = config => ({ - addLink: callbackify.variadic(require('./add-link')(config)), - appendData: callbackify.variadic(require('./append-data')(config)), - rmLink: callbackify.variadic(require('./rm-link')(config)), - setData: callbackify.variadic(require('./set-data')(config)) + addLink: require('./add-link')(config), + appendData: require('./append-data')(config), + rmLink: require('./rm-link')(config), + setData: require('./set-data')(config) }) diff --git a/src/pin/add.js b/src/pin/add.js index 74eb47a2d..41b119fe8 100644 --- a/src/pin/add.js +++ b/src/pin/add.js @@ -1,13 +1,15 @@ 'use strict' +const CID = require('cids') const configure = require('../lib/configure') module.exports = configure(({ ky }) => { - return async (path, options) => { + return async (paths, options) => { + paths = Array.isArray(paths) ? paths : [paths] options = options || {} const searchParams = new URLSearchParams(options.searchParams) - searchParams.set('arg', `${path}`) + paths.forEach(path => searchParams.append('arg', `${path}`)) if (options.recursive != null) searchParams.set('recursive', options.recursive) const res = await ky.post('pin/add', { @@ -17,6 +19,6 @@ module.exports = configure(({ ky }) => { searchParams }).json() - return (res.Pins || []).map(hash => ({ hash })) + return (res.Pins || []).map(cid => ({ cid: new CID(cid) })) } }) diff --git a/src/pin/index.js b/src/pin/index.js index c62d3a46a..ad43057ec 100644 --- a/src/pin/index.js +++ b/src/pin/index.js @@ -1,9 +1,7 @@ 'use strict' -const callbackify = require('callbackify') - module.exports = config => ({ - add: callbackify.variadic(require('./add')(config)), - rm: callbackify.variadic(require('./rm')(config)), - ls: callbackify.variadic(require('./ls')(config)) + add: require('./add')(config), + rm: require('./rm')(config), + ls: require('./ls')(config) }) diff --git a/src/pin/ls.js b/src/pin/ls.js index 9c42fd71d..f9e0968ac 100644 --- a/src/pin/ls.js +++ b/src/pin/ls.js @@ -1,9 +1,12 @@ 'use strict' +const ndjson = require('iterable-ndjson') +const CID = require('cids') const configure = require('../lib/configure') +const toIterable = require('stream-to-it/source') module.exports = configure(({ ky }) => { - return async (path, options) => { + return async function * ls (path, options) { if (path && path.type) { options = path path = null @@ -14,16 +17,25 @@ module.exports = configure(({ ky }) => { options = options || {} const searchParams = new URLSearchParams(options.searchParams) + searchParams.set('stream', options.stream == null ? true : options.stream) path.forEach(p => searchParams.append('arg', `${p}`)) if (options.type) searchParams.set('type', options.type) - const { Keys } = await ky.post('pin/ls', { + const res = await ky.post('pin/ls', { timeout: options.timeout, signal: options.signal, headers: options.headers, searchParams - }).json() + }) - return Object.keys(Keys).map(hash => ({ hash, type: Keys[hash].Type })) + for await (const pin of ndjson(toIterable(res.body))) { + if (pin.Keys) { // non-streaming response + for (const cid of Object.keys(pin.Keys)) { + yield { cid: new CID(cid), type: pin.Keys[cid].Type } + } + return + } + yield { cid: new CID(pin.Cid), type: pin.Type } + } } }) diff --git a/src/pin/rm.js b/src/pin/rm.js index 9f75307ff..83fbca93c 100644 --- a/src/pin/rm.js +++ b/src/pin/rm.js @@ -1,5 +1,6 @@ 'use strict' +const CID = require('cids') const configure = require('../lib/configure') module.exports = configure(({ ky }) => { @@ -17,6 +18,6 @@ module.exports = configure(({ ky }) => { searchParams }).json() - return (res.Pins || []).map(hash => ({ hash })) + return (res.Pins || []).map(cid => ({ cid: new CID(cid) })) } }) diff --git a/src/ping.js b/src/ping.js index 33b275617..332120934 100644 --- a/src/ping.js +++ b/src/ping.js @@ -2,7 +2,7 @@ const ndjson = require('iterable-ndjson') const configure = require('./lib/configure') -const toIterable = require('./lib/stream-to-iterable') +const toIterable = require('stream-to-it/source') const toCamel = require('./lib/object-to-camel') module.exports = configure(({ ky }) => { diff --git a/src/pubsub/index.js b/src/pubsub/index.js index 2738bd5ac..e369bb6f3 100644 --- a/src/pubsub/index.js +++ b/src/pubsub/index.js @@ -1,50 +1,9 @@ 'use strict' -const nodeify = require('promise-nodeify') - -// This file is temporary and for compatibility with legacy usage -module.exports = (send, options) => { - if (typeof send !== 'function') { - options = send - } - - const ls = require('./ls')(options) - const peers = require('./peers')(options) - const publish = require('./publish')(options) - const subscribe = require('./subscribe')(options) - const unsubscribe = require('./unsubscribe')(options) - - return { - ls: (options, callback) => { - if (typeof options === 'function') { - callback = options - options = {} - } - return nodeify(ls(options), callback) - }, - peers: (topic, options, callback) => { - if (typeof options === 'function') { - callback = options - options = {} - } - return nodeify(peers(topic, options), callback) - }, - publish: (topic, data, options, callback) => { - if (typeof options === 'function') { - callback = options - options = {} - } - return nodeify(publish(topic, data, options), callback) - }, - subscribe: (topic, handler, options, callback) => { - if (typeof options === 'function') { - callback = options - options = {} - } - return nodeify(subscribe(topic, handler, options), callback) - }, - unsubscribe: (topic, handler, callback) => { - return nodeify(unsubscribe(topic, handler), callback) - } - } -} +module.exports = config => ({ + ls: require('./ls')(config), + peers: require('./peers')(config), + publish: require('./publish')(config), + subscribe: require('./subscribe')(config), + unsubscribe: require('./unsubscribe')(config) +}) diff --git a/src/pubsub/subscribe.js b/src/pubsub/subscribe.js index 7950a274a..188a91664 100644 --- a/src/pubsub/subscribe.js +++ b/src/pubsub/subscribe.js @@ -1,12 +1,11 @@ 'use strict' const ndjson = require('iterable-ndjson') -const explain = require('explain-error') const bs58 = require('bs58') const { Buffer } = require('buffer') const log = require('debug')('ipfs-http-client:pubsub:subscribe') const configure = require('../lib/configure') -const toIterable = require('../lib/stream-to-iterable') +const toIterable = require('stream-to-it/source') const SubscriptionTracker = require('./subscription-tracker') module.exports = configure((config) => { @@ -71,7 +70,8 @@ async function readMessages (msgStream, { onMessage, onEnd, onError }) { topicIDs: msg.topicIDs }) } catch (err) { - onError(explain(err, 'Failed to parse pubsub message'), false, msg) // Not fatal + err.message = `Failed to parse pubsub message: ${err.message}` + onError(err, false, msg) // Not fatal } } } catch (err) { diff --git a/src/refs/index.js b/src/refs/index.js index b15f2cd0c..05a636feb 100644 --- a/src/refs/index.js +++ b/src/refs/index.js @@ -4,7 +4,7 @@ const configure = require('../lib/configure') const { Buffer } = require('buffer') const CID = require('cids') const ndjson = require('iterable-ndjson') -const toIterable = require('../lib/stream-to-iterable') +const toIterable = require('stream-to-it/source') const toCamel = require('../lib/object-to-camel') module.exports = config => { diff --git a/src/refs/local.js b/src/refs/local.js index afa1630ea..98e0fce40 100644 --- a/src/refs/local.js +++ b/src/refs/local.js @@ -2,7 +2,7 @@ const configure = require('../lib/configure') const ndjson = require('iterable-ndjson') -const toIterable = require('../lib/stream-to-iterable') +const toIterable = require('stream-to-it/source') const toCamel = require('../lib/object-to-camel') module.exports = configure(({ ky }) => { diff --git a/src/repo/gc.js b/src/repo/gc.js index 3d92dee4c..fc60a46bc 100644 --- a/src/repo/gc.js +++ b/src/repo/gc.js @@ -3,7 +3,7 @@ const CID = require('cids') const ndjson = require('iterable-ndjson') const configure = require('../lib/configure') -const toIterable = require('../lib/stream-to-iterable') +const toIterable = require('stream-to-it/source') module.exports = configure(({ ky }) => { return async function * gc (peerId, options) { diff --git a/src/repo/index.js b/src/repo/index.js index fe58504ad..4785f55db 100644 --- a/src/repo/index.js +++ b/src/repo/index.js @@ -1,10 +1,7 @@ 'use strict' -const callbackify = require('callbackify') -const { collectify } = require('../lib/converters') - module.exports = config => ({ - gc: callbackify.variadic(collectify(require('./gc')(config))), - stat: callbackify.variadic(require('./stat')(config)), - version: callbackify.variadic(require('./version')(config)) + gc: require('./gc')(config), + stat: require('./stat')(config), + version: require('./version')(config) }) diff --git a/src/stats/bw.js b/src/stats/bw.js index f68ad23ba..12bc6d44a 100644 --- a/src/stats/bw.js +++ b/src/stats/bw.js @@ -3,7 +3,7 @@ const ndjson = require('iterable-ndjson') const Big = require('bignumber.js') const configure = require('../lib/configure') -const toIterable = require('../lib/stream-to-iterable') +const toIterable = require('stream-to-it/source') module.exports = configure(({ ky }) => { return async function * bw (options) { diff --git a/src/stats/index.js b/src/stats/index.js index 4351d79e2..d13a534a7 100644 --- a/src/stats/index.js +++ b/src/stats/index.js @@ -1,19 +1,7 @@ 'use strict' -const callbackify = require('callbackify') -const { streamify, pullify } = require('../lib/converters') - -module.exports = config => { - const bw = require('./bw')(config) - return { - bitswap: callbackify.variadic(require('../bitswap/stat')(config)), - bw: callbackify.variadic(async options => { - for await (const stats of bw(options)) { - return stats - } - }), - bwReadableStream: streamify.readable(bw), - bwPullStream: pullify.source(bw), - repo: callbackify.variadic(require('../repo/stat')(config)) - } -} +module.exports = config => ({ + bitswap: require('../bitswap/stat')(config), + bw: require('./bw')(config), + repo: require('../repo/stat')(config) +}) diff --git a/src/swarm/addrs.js b/src/swarm/addrs.js index a786d32cb..25bd98d02 100644 --- a/src/swarm/addrs.js +++ b/src/swarm/addrs.js @@ -1,7 +1,6 @@ 'use strict' -const PeerInfo = require('peer-info') -const PeerId = require('peer-id') +const CID = require('cids') const multiaddr = require('multiaddr') const configure = require('../lib/configure') @@ -16,10 +15,9 @@ module.exports = configure(({ ky }) => { searchParams: options.searchParams }).json() - return Object.keys(res.Addrs).map(id => { - const peerInfo = new PeerInfo(PeerId.createFromB58String(id)) - res.Addrs[id].forEach(addr => peerInfo.multiaddrs.add(multiaddr(addr))) - return peerInfo - }) + return Object.keys(res.Addrs).map(id => ({ + id: new CID(id), + addrs: (res.Addrs[id] || []).map(a => multiaddr(a)) + })) } }) diff --git a/src/swarm/disconnect.js b/src/swarm/disconnect.js index a3d60d172..e83ca0dd4 100644 --- a/src/swarm/disconnect.js +++ b/src/swarm/disconnect.js @@ -8,7 +8,7 @@ module.exports = configure(({ ky }) => { options = options || {} const searchParams = new URLSearchParams(options.searchParams) - addrs.forEach(addr => searchParams.append('arg', addr)) + addrs.forEach(addr => searchParams.append('arg', `${addr}`)) const res = await ky.post('swarm/disconnect', { timeout: options.timeout, diff --git a/src/swarm/index.js b/src/swarm/index.js index e86a7c22c..84648439d 100644 --- a/src/swarm/index.js +++ b/src/swarm/index.js @@ -1,11 +1,9 @@ 'use strict' -const callbackify = require('callbackify') - module.exports = config => ({ - addrs: callbackify.variadic(require('./addrs')(config)), - connect: callbackify.variadic(require('./connect')(config)), - disconnect: callbackify.variadic(require('./disconnect')(config)), - localAddrs: callbackify.variadic(require('./localAddrs')(config)), - peers: callbackify.variadic(require('./peers')(config)) + addrs: require('./addrs')(config), + connect: require('./connect')(config), + disconnect: require('./disconnect')(config), + localAddrs: require('./localAddrs')(config), + peers: require('./peers')(config) }) diff --git a/src/swarm/peers.js b/src/swarm/peers.js index 3b897348c..f10035e06 100644 --- a/src/swarm/peers.js +++ b/src/swarm/peers.js @@ -1,7 +1,7 @@ 'use strict' const multiaddr = require('multiaddr') -const PeerId = require('peer-id') +const CID = require('cids') const configure = require('../lib/configure') module.exports = configure(({ ky }) => { @@ -25,7 +25,7 @@ module.exports = configure(({ ky }) => { const info = {} try { info.addr = multiaddr(peer.Addr) - info.peer = PeerId.createFromB58String(peer.Peer) + info.peer = new CID(peer.Peer) } catch (error) { info.error = error info.rawPeerInfo = peer diff --git a/test/custom-headers.spec.js b/test/custom-headers.spec.js index ce14a01e5..5e88b72a6 100644 --- a/test/custom-headers.spec.js +++ b/test/custom-headers.spec.js @@ -1,7 +1,7 @@ /* eslint-env mocha */ 'use strict' -const isNode = require('detect-node') +const { isNode } = require('ipfs-utils/src/env') const { expect } = require('interface-ipfs-core/src/utils/mocha') const ipfsClient = require('../src') diff --git a/test/exports.spec.js b/test/exports.spec.js index f97707e13..0df770da6 100644 --- a/test/exports.spec.js +++ b/test/exports.spec.js @@ -1,28 +1,22 @@ /* eslint-env mocha, browser */ 'use strict' -const isIPFS = require('is-ipfs') const CID = require('cids') const multiaddr = require('multiaddr') const multibase = require('multibase') const multicodec = require('multicodec') const multihash = require('multihashes') -const PeerId = require('peer-id') -const PeerInfo = require('peer-info') const { expect } = require('interface-ipfs-core/src/utils/mocha') const IpfsHttpClient = require('../') describe('exports', () => { it('should export the expected types and utilities', () => { - expect(IpfsHttpClient.isIPFS).to.equal(isIPFS) expect(IpfsHttpClient.Buffer).to.equal(Buffer) expect(IpfsHttpClient.CID).to.equal(CID) expect(IpfsHttpClient.multiaddr).to.equal(multiaddr) expect(IpfsHttpClient.multibase).to.equal(multibase) expect(IpfsHttpClient.multicodec).to.equal(multicodec) expect(IpfsHttpClient.multihash).to.equal(multihash) - expect(IpfsHttpClient.PeerId).to.equal(PeerId) - expect(IpfsHttpClient.PeerInfo).to.equal(PeerInfo) }) }) diff --git a/test/files-mfs.spec.js b/test/files-mfs.spec.js index 0e3d6b1af..edc7698e1 100644 --- a/test/files-mfs.spec.js +++ b/test/files-mfs.spec.js @@ -5,13 +5,11 @@ const { expect } = require('interface-ipfs-core/src/utils/mocha') const loadFixture = require('aegir/fixtures') const mh = require('multihashes') -const CID = require('cids') -const values = require('pull-stream/sources/values') -const pull = require('pull-stream/pull') -const collect = require('pull-stream/sinks/collect') +const all = require('it-all') +const pipe = require('it-pipe') +const { TimeoutError } = require('ky-universal') const f = require('./utils/factory') -const expectTimeout = require('./utils/expect-timeout') const testfile = loadFixture('test/fixtures/testfile.txt') @@ -41,10 +39,10 @@ describe('.files (the MFS API part)', function () { after(() => f.clean()) it('.add file for testing', async () => { - const res = await ipfs.add(testfile) + const res = await all(ipfs.add(testfile)) expect(res).to.have.length(1) - expect(res[0].hash).to.equal(expectedMultihash) + expect(res[0].cid.toString()).to.equal(expectedMultihash) expect(res[0].path).to.equal(expectedMultihash) }) @@ -54,10 +52,10 @@ describe('.files (the MFS API part)', function () { const expectedBufferMultihash = 'QmWfVY9y3xjsixTgbd9AorQxH7VtMpzfx2HaWtsoUYecaX' const file = Buffer.from('hello') - const res = await ipfs.add(file) + const res = await all(ipfs.add(file)) expect(res).to.have.length(1) - expect(res[0].hash).to.equal(expectedBufferMultihash) + expect(res[0].cid.toString()).to.equal(expectedBufferMultihash) expect(res[0].path).to.equal(expectedBufferMultihash) }) @@ -65,10 +63,10 @@ describe('.files (the MFS API part)', function () { const expectedHash = 'QmWfVY9y3xjsixTgbd9AorQxH7VtMpzfx2HaWtsoUYecaX' const content = Buffer.from('hello') - const res = await ipfs.add([{ path: '', content }]) + const res = await all(ipfs.add([{ path: '', content }])) expect(res).to.have.length(1) - expect(res[0].hash).to.equal(expectedHash) + expect(res[0].cid.toString()).to.equal(expectedHash) expect(res[0].path).to.equal(expectedHash) }) @@ -76,39 +74,40 @@ describe('.files (the MFS API part)', function () { const expectedCid = 'bafybeifogzovjqrcxvgt7g36y7g63hvwvoakledwk4b2fr2dl4wzawpnny' const options = { cidVersion: 1, rawLeaves: false } - const res = await ipfs.add(testfile, options) + const res = await all(ipfs.add(testfile, options)) expect(res).to.have.length(1) - expect(res[0].hash).to.equal(expectedCid) + expect(res[0].cid.toString()).to.equal(expectedCid) expect(res[0].path).to.equal(expectedCid) }) it('.add with only-hash=true', async () => { const content = String(Math.random() + Date.now()) - const files = await ipfs.add(Buffer.from(content), { onlyHash: true }) + const files = await all(ipfs.add(Buffer.from(content), { onlyHash: true })) expect(files).to.have.length(1) // 'ipfs.object.get()' should timeout because content wasn't actually added - await expectTimeout(ipfs.object.get(files[0].hash), 4000) + return expect(ipfs.object.get(files[0].cid, { timeout: 2000 })) + .to.be.rejectedWith(TimeoutError) }) it('.add with options', async () => { - const res = await ipfs.add(testfile, { pin: false }) + const res = await all(ipfs.add(testfile, { pin: false })) expect(res).to.have.length(1) - expect(res[0].hash).to.equal(expectedMultihash) + expect(res[0].cid.toString()).to.equal(expectedMultihash) expect(res[0].path).to.equal(expectedMultihash) }) it('.add pins by default', async () => { const newContent = Buffer.from(String(Math.random())) - const initialPins = await ipfs.pin.ls() + const initialPins = await all(ipfs.pin.ls()) - await ipfs.add(newContent) + await all(ipfs.add(newContent)) - const pinsAfterAdd = await ipfs.pin.ls() + const pinsAfterAdd = await all(ipfs.pin.ls()) expect(pinsAfterAdd.length).to.eql(initialPins.length + 1) }) @@ -116,11 +115,11 @@ describe('.files (the MFS API part)', function () { it('.add with pin=false', async () => { const newContent = Buffer.from(String(Math.random())) - const initialPins = await ipfs.pin.ls() + const initialPins = await all(ipfs.pin.ls()) - await ipfs.add(newContent, { pin: false }) + await all(ipfs.add(newContent, { pin: false })) - const pinsAfterAdd = await ipfs.pin.ls() + const pinsAfterAdd = await all(ipfs.pin.ls()) expect(pinsAfterAdd.length).to.eql(initialPins.length) }) @@ -134,10 +133,10 @@ describe('.files (the MFS API part)', function () { } const options = { hashAlg: name, rawLeaves: false } - const res = await ipfs.add([file], options) + const res = await all(ipfs.add([file], options)) expect(res).to.have.length(1) - const cid = new CID(res[0].hash) + const { cid } = res[0] expect(mh.decode(cid.multihash).name).to.equal(name) }) }) @@ -151,7 +150,7 @@ describe('.files (the MFS API part)', function () { progress = p } - const res = await ipfs.add(testfile, { progress: progressHandler }) + const res = await all(ipfs.add(testfile, { progress: progressHandler })) expect(res).to.have.length(1) expect(progress).to.be.equal(testfile.byteLength) @@ -168,7 +167,7 @@ describe('.files (the MFS API part)', function () { } // TODO: needs to be using a big file - const res = await ipfs.add(testfile, { progress: progressHandler }) + const res = await all(ipfs.add(testfile, { progress: progressHandler })) expect(res).to.have.length(1) expect(progress).to.be.equal(testfile.byteLength) @@ -185,7 +184,7 @@ describe('.files (the MFS API part)', function () { } // TODO: needs to be using a directory - const res = await ipfs.add(testfile, { progress: progressHandler }) + const res = await all(ipfs.add(testfile, { progress: progressHandler })) expect(res).to.have.length(1) expect(progress).to.be.equal(testfile.byteLength) @@ -193,7 +192,7 @@ describe('.files (the MFS API part)', function () { }) it('.add without progress options', async () => { - const res = await ipfs.add(testfile) + const res = await all(ipfs.add(testfile)) expect(res).to.have.length(1) }) @@ -207,44 +206,35 @@ describe('.files (the MFS API part)', function () { } const options = { hashAlg: name, rawLeaves: false } - const res = await ipfs.add([file], options) + const res = await all(ipfs.add([file], options)) expect(res).to.have.length(1) - const cid = new CID(res[0].hash) + const { cid } = res[0] expect(mh.decode(cid.multihash).name).to.equal(name) }) }) - it('.addPullStream with object chunks and pull stream content', (done) => { + it('.add with object chunks and iterable content', async () => { const expectedCid = 'QmRf22bZar3WKmojipms22PkXH1MZGmvsqzQtuSvQE3uhm' - pull( - values([{ content: values([Buffer.from('test')]) }]), - ipfs.addPullStream(), - collect((err, res) => { - expect(err).to.not.exist() - - expect(res).to.have.length(1) - expect(res[0]).to.deep.equal({ path: expectedCid, hash: expectedCid, size: 12 }) - done() - }) + const res = await pipe( + [{ content: [Buffer.from('test')] }], + ipfs.add, + all ) - }) - - it('.add with pull stream', async () => { - const expectedCid = 'QmRf22bZar3WKmojipms22PkXH1MZGmvsqzQtuSvQE3uhm' - const res = await ipfs.add(values([Buffer.from('test')])) expect(res).to.have.length(1) - expect(res[0]).to.deep.equal({ path: expectedCid, hash: expectedCid, size: 12 }) + res[0].cid = res[0].cid.toString() + expect(res[0]).to.deep.equal({ path: expectedCid, cid: expectedCid, size: 12 }) }) - it('.add with array of objects with pull stream content', async () => { + it('.add with iterable', async () => { const expectedCid = 'QmRf22bZar3WKmojipms22PkXH1MZGmvsqzQtuSvQE3uhm' - const res = await ipfs.add([{ content: values([Buffer.from('test')]) }]) + const res = await all(ipfs.add([Buffer.from('test')])) expect(res).to.have.length(1) - expect(res[0]).to.eql({ path: expectedCid, hash: expectedCid, size: 12 }) + res[0].cid = res[0].cid.toString() + expect(res[0]).to.deep.equal({ path: expectedCid, cid: expectedCid, size: 12 }) }) it('files.mkdir', async () => { @@ -315,7 +305,7 @@ describe('.files (the MFS API part)', function () { await ipfs.files.write(file, Buffer.from('Hello, world'), { create: true }) - const files = await ipfs.files.ls(folder) + const files = await all(ipfs.files.ls(folder)) expect(files.length).to.equal(1) }) @@ -324,7 +314,7 @@ describe('.files (the MFS API part)', function () { const folder = `test-folder-${Math.random()}` await ipfs.files.mkdir(`/${folder}`) - const files = await ipfs.files.ls() + const files = await all(ipfs.files.ls()) expect(files.find(file => file.name === folder)).to.be.ok() }) @@ -334,7 +324,7 @@ describe('.files (the MFS API part)', function () { create: true }) - const buf = await ipfs.files.read('/test-folder/test-file-2.txt') + const buf = Buffer.concat(await all(ipfs.files.read('/test-folder/test-file-2.txt'))) expect(buf.toString()).to.be.equal('hello world') }) @@ -342,7 +332,7 @@ describe('.files (the MFS API part)', function () { it('files.write without options', async () => { await ipfs.files.write('/test-folder/test-file-2.txt', Buffer.from('hello world')) - const buf = await ipfs.files.read('/test-folder/test-file-2.txt') + const buf = Buffer.concat(await all(ipfs.files.read('/test-folder/test-file-2.txt'))) expect(buf.toString()).to.be.equal('hello world') }) @@ -357,9 +347,10 @@ describe('.files (the MFS API part)', function () { }) const stats = await ipfs.files.stat(file) + stats.cid = stats.cid.toString() expect(stats).to.deep.equal({ - hash: 'QmQhouoDPAnzhVM148yCa9CbUXK65wSEAZBtgrLGHtmdmP', + cid: 'QmQhouoDPAnzhVM148yCa9CbUXK65wSEAZBtgrLGHtmdmP', size: 12, cumulativeSize: 70, blocks: 1, @@ -383,7 +374,7 @@ describe('.files (the MFS API part)', function () { await ipfs.files.write(file, testfile, { create: true }) - const buf = await ipfs.files.read(file) + const buf = Buffer.concat(await all(ipfs.files.read(file))) expect(Buffer.from(buf)).to.deep.equal(testfile) }) diff --git a/test/get.spec.js b/test/get.spec.js index a6fb3aaa4..c303179c8 100644 --- a/test/get.spec.js +++ b/test/get.spec.js @@ -5,6 +5,8 @@ const { expect } = require('interface-ipfs-core/src/utils/mocha') const loadFixture = require('aegir/fixtures') +const all = require('it-all') +const concat = require('it-concat') const f = require('./utils/factory') @@ -24,35 +26,37 @@ describe('.get (specific go-ipfs features)', function () { before(async () => { ipfs = (await f.spawn()).api - await ipfs.add(smallFile.data) + await all(ipfs.add(smallFile.data)) }) after(() => f.clean()) it('no compression args', async () => { - const files = await ipfs.get(smallFile.cid) + const files = await all(ipfs.get(smallFile.cid)) expect(files).to.be.length(1) - expect(files[0].content.toString()).to.contain(smallFile.data.toString()) + const content = await concat(files[0].content) + expect(content.toString()).to.contain(smallFile.data.toString()) }) it('archive true', async () => { - const files = await ipfs.get(smallFile.cid, { archive: true }) + const files = await all(ipfs.get(smallFile.cid, { archive: true })) expect(files).to.be.length(1) - expect(files[0].content.toString()).to.contain(smallFile.data.toString()) + const content = await concat(files[0].content) + expect(content.toString()).to.contain(smallFile.data.toString()) }) it('err with out of range compression level', async () => { - await expect(ipfs.get(smallFile.cid, { + await expect(all(ipfs.get(smallFile.cid, { compress: true, compressionLevel: 10 - })).to.be.rejectedWith('compression level must be between 1 and 9') + }))).to.be.rejectedWith('compression level must be between 1 and 9') }) // TODO Understand why this test started failing it.skip('with compression level', async () => { - await ipfs.get(smallFile.cid, { compress: true, 'compression-level': 1 }) + await all(ipfs.get(smallFile.cid, { compress: true, 'compression-level': 1 })) }) it('add path containing "+"s (for testing get)', async () => { @@ -60,17 +64,17 @@ describe('.get (specific go-ipfs features)', function () { const subdir = 'tmp/c++files' const expectedCid = 'QmPkmARcqjo5fqK1V1o8cFsuaXxWYsnwCNLJUYS4KeZyff' const path = `${subdir}/${filename}` - const files = await ipfs.add([{ + const files = await all(ipfs.add([{ path, content: Buffer.from(path) - }]) + }])) - expect(files[2].hash).to.equal(expectedCid) + expect(files[2].cid.toString()).to.equal(expectedCid) }) it('get path containing "+"s', async () => { const cid = 'QmPkmARcqjo5fqK1V1o8cFsuaXxWYsnwCNLJUYS4KeZyff' - const files = await ipfs.get(cid) + const files = await all(ipfs.get(cid)) expect(files).to.be.an('array').with.lengthOf(3) expect(files[0]).to.have.property('path', cid) diff --git a/test/interface.spec.js b/test/interface.spec.js index 796c1ae86..ebec1b0e9 100644 --- a/test/interface.spec.js +++ b/test/interface.spec.js @@ -3,7 +3,6 @@ const tests = require('interface-ipfs-core') const merge = require('merge-options') -const { isNode } = require('ipfs-utils/src/env') const { createFactory } = require('ipfsd-ctl') const { findBin } = require('ipfsd-ctl/src/utils') const isWindows = process.platform && process.platform === 'win32' @@ -25,6 +24,43 @@ describe('interface-ipfs-core tests', () => { } const commonFactory = createFactory(commonOptions) + tests.root(commonFactory, { + skip: [ + { + name: 'should add with mode as string', + reason: 'TODO not implemented in go-ipfs yet' + }, + { + name: 'should add with mode as number', + reason: 'TODO not implemented in go-ipfs yet' + }, + { + name: 'should add with mtime as Date', + reason: 'TODO not implemented in go-ipfs yet' + }, + { + name: 'should add with mtime as { nsecs, secs }', + reason: 'TODO not implemented in go-ipfs yet' + }, + { + name: 'should add with mtime as timespec', + reason: 'TODO not implemented in go-ipfs yet' + }, + { + name: 'should add with mtime as hrtime', + reason: 'TODO not implemented in go-ipfs yet' + }, + { + name: 'should export a chunk of a file', + reason: 'TODO not implemented in go-ipfs yet' + }, + { + name: 'should ls with metadata', + reason: 'TODO not implemented in go-ipfs yet' + } + ] + }) + tests.bitswap(commonFactory) tests.block(commonFactory, { @@ -34,7 +70,18 @@ describe('interface-ipfs-core tests', () => { }] }) - tests.bootstrap(commonFactory) + tests.bootstrap(commonFactory, { + skip: [{ + name: 'should return a list containing the bootstrap peer when called with a valid arg (ip4)', + reason: 'TODO unskip when go-ipfs switches to p2p for libp2p keys' + }, { + name: 'should prevent duplicate inserts of bootstrap peers', + reason: 'TODO unskip when go-ipfs switches to p2p for libp2p keys' + }, { + name: 'should return a list containing the peer removed when called with a valid arg (ip4)', + reason: 'TODO unskip when go-ipfs switches to p2p for libp2p keys' + }] + }) tests.config(commonFactory, { skip: [ @@ -81,31 +128,21 @@ describe('interface-ipfs-core tests', () => { ] }) - tests.dht(commonFactory, { + tests.dht(commonFactory) + + tests.files(commonFactory, { skip: [ - // dht.findpeer { - name: 'should fail to find other peer if peer does not exist', - reason: 'FIXME checking what is exactly go-ipfs returning https://github.com/ipfs/go-ipfs/issues/3862#issuecomment-294168090' + name: 'should ls directory', + reason: 'TODO unskip when go-ipfs supports --long https://github.com/ipfs/go-ipfs/pull/6528' }, - // dht.findprovs { - name: 'should take options to override timeout config', - reason: 'FIXME go-ipfs does not support a timeout option' + name: 'should list a file directly', + reason: 'TODO unskip when go-ipfs supports --long https://github.com/ipfs/go-ipfs/pull/6528' }, - // dht.get - { - name: 'should get a value after it was put on another node', - reason: 'FIXME go-ipfs errors with Error: key was not found (type 6) https://github.com/ipfs/go-ipfs/issues/3862' - } - ] - }) - - tests.filesMFS(commonFactory, { - skip: [ { - name: 'should ls directory with long option', - reason: 'TODO unskip when go-ipfs supports --long https://github.com/ipfs/go-ipfs/pull/6528' + name: 'should ls directory and include metadata', + reason: 'TODO not implemented in go-ipfs yet' }, { name: 'should read from outside of mfs', @@ -167,10 +204,6 @@ describe('interface-ipfs-core tests', () => { name: 'should respect metadata when copying from outside of mfs', reason: 'TODO not implemented in go-ipfs yet' }, - { - name: 'ls directory with long option should include metadata', - reason: 'TODO not implemented in go-ipfs yet' - }, { name: 'should have default mtime', reason: 'TODO not implemented in go-ipfs yet' @@ -270,57 +303,6 @@ describe('interface-ipfs-core tests', () => { ] }) - tests.filesRegular(commonFactory, { - skip: [ - // .addFromFs - isNode ? null : { - name: 'addFromFs', - reason: 'Not designed to run in the browser' - }, - { - name: 'should add with mode as string', - reason: 'TODO not implemented in go-ipfs yet' - }, - { - name: 'should add with mode as number', - reason: 'TODO not implemented in go-ipfs yet' - }, - { - name: 'should add with mtime as Date', - reason: 'TODO not implemented in go-ipfs yet' - }, - { - name: 'should add with mtime as { nsecs, secs }', - reason: 'TODO not implemented in go-ipfs yet' - }, - { - name: 'should add with mtime as timespec', - reason: 'TODO not implemented in go-ipfs yet' - }, - { - name: 'should add with mtime as hrtime', - reason: 'TODO not implemented in go-ipfs yet' - }, - // .catPullStream - { - name: 'should export a chunk of a file', - reason: 'TODO not implemented in go-ipfs yet' - }, - { - name: 'should export a chunk of a file in a Pull Stream', - reason: 'TODO not implemented in go-ipfs yet' - }, - { - name: 'should export a chunk of a file in a Readable Stream', - reason: 'TODO not implemented in go-ipfs yet' - }, - { - name: 'should ls with metadata', - reason: 'TODO not implemented in go-ipfs yet' - } - ] - }) - tests.key(commonFactory, { skip: [ // key.export @@ -346,7 +328,6 @@ describe('interface-ipfs-core tests', () => { } )), { skip: [ - // stop { name: 'should resolve a record from peerid as cidv1 in base32', reason: 'TODO not implemented in go-ipfs yet: https://github.com/ipfs/go-ipfs/issues/5287' @@ -383,14 +364,6 @@ describe('interface-ipfs-core tests', () => { tests.ping(commonFactory, { skip: [ - { - name: 'should fail when pinging an unknown peer over pull stream', - reason: 'FIXME go-ipfs return success with text: Looking up peer ' - }, - { - name: 'should fail when pinging peer that is not available over readable stream', - reason: 'FIXME go-ipfs return success with text: Looking up peer ' - }, { name: 'should fail when pinging a peer that is not available', reason: 'FIXME go-ipfs return success with text: Looking up peer ' diff --git a/test/lib.stream-to-iterable.spec.js b/test/lib.stream-to-iterable.spec.js deleted file mode 100644 index 3ad326480..000000000 --- a/test/lib.stream-to-iterable.spec.js +++ /dev/null @@ -1,40 +0,0 @@ -/* eslint-env mocha */ -'use strict' - -const { expect } = require('interface-ipfs-core/src/utils/mocha') -const toIterable = require('../src/lib/stream-to-iterable') - -describe('lib/stream-to-iterable', () => { - it('should return input if already async iterable', () => { - const input = { [Symbol.asyncIterator] () { return this } } - expect(toIterable(input)).to.equal(input) - }) - - it('should convert reader to async iterable', async () => { - const inputData = [2, 31, 3, 4] - const input = { - getReader () { - let i = 0 - return { - read () { - return i === inputData.length - ? { done: true } - : { value: inputData[i++] } - }, - releaseLock () {} - } - } - } - - const chunks = [] - for await (const chunk of toIterable(input)) { - chunks.push(chunk) - } - - expect(chunks).to.eql(inputData) - }) - - it('should throw on unknown stream', () => { - expect(() => toIterable({})).to.throw('unknown stream') - }) -}) diff --git a/test/log.spec.js b/test/log.spec.js index 1a885028d..c56660d07 100644 --- a/test/log.spec.js +++ b/test/log.spec.js @@ -3,6 +3,7 @@ 'use strict' const { expect } = require('interface-ipfs-core/src/utils/mocha') +const all = require('it-all') const f = require('./utils/factory') describe('.log', function () { @@ -19,7 +20,7 @@ describe('.log', function () { it('.log.tail', async () => { const i = setInterval(async () => { try { - await ipfs.add(Buffer.from('just adding some data to generate logs')) + await all(ipfs.add(Buffer.from('just adding some data to generate logs'))) } catch (_) { // this can error if the test has finished and we're shutting down the node } diff --git a/test/node/swarm.js b/test/node/swarm.js index 9e0252a2c..89315f2fe 100644 --- a/test/node/swarm.js +++ b/test/node/swarm.js @@ -25,7 +25,7 @@ describe('.swarm.peers', function () { expect(res.length).to.equal(1) expect(res[0].error).to.not.exist() expect(res[0].addr.toString()).to.equal(response.Peers[0].Addr) - expect(res[0].peer.toB58String()).to.equal(response.Peers[0].Peer) + expect(res[0].peer.toString()).to.equal(response.Peers[0].Peer) expect(scope.isDone()).to.equal(true) }) @@ -43,7 +43,7 @@ describe('.swarm.peers', function () { expect(res.length).to.equal(1) expect(res[0].error).to.not.exist() expect(res[0].addr.toString()).to.equal(response.Peers[0].Addr) - expect(res[0].peer.toB58String()).to.equal(response.Peers[0].Peer) + expect(res[0].peer.toString()).to.equal(response.Peers[0].Peer) expect(scope.isDone()).to.equal(true) }) diff --git a/test/ping.spec.js b/test/ping.spec.js index 01636ed60..7076f208b 100644 --- a/test/ping.spec.js +++ b/test/ping.spec.js @@ -2,8 +2,7 @@ 'use strict' const { expect } = require('interface-ipfs-core/src/utils/mocha') -const pull = require('pull-stream/pull') -const collect = require('pull-stream/sinks/collect') +const all = require('it-all') const f = require('./utils/factory') @@ -34,7 +33,7 @@ describe('.ping', function () { after(() => f.clean()) it('.ping with default count', async () => { - const res = await ipfs.ping(otherId) + const res = await all(ipfs.ping(otherId)) expect(res).to.be.an('array') expect(res.filter(isPong)).to.have.lengthOf(10) res.forEach(packet => { @@ -46,7 +45,7 @@ describe('.ping', function () { }) it('.ping with count = 2', async () => { - const res = await ipfs.ping(otherId, { count: 2 }) + const res = await all(ipfs.ping(otherId, { count: 2 })) expect(res).to.be.an('array') expect(res.filter(isPong)).to.have.lengthOf(2) res.forEach(packet => { @@ -56,39 +55,4 @@ describe('.ping', function () { const resultMsg = res.find(packet => packet.text.includes('Average latency')) expect(resultMsg).to.exist() }) - - it('.pingPullStream', (done) => { - pull( - ipfs.pingPullStream(otherId, { count: 2 }), - collect((err, data) => { - expect(err).to.not.exist() - expect(data).to.be.an('array') - expect(data.filter(isPong)).to.have.lengthOf(2) - data.forEach(packet => { - expect(packet).to.have.keys('success', 'time', 'text') - expect(packet.time).to.be.a('number') - }) - const resultMsg = data.find(packet => packet.text.includes('Average latency')) - expect(resultMsg).to.exist() - done() - }) - ) - }) - - it('.pingReadableStream', (done) => { - let packetNum = 0 - ipfs.pingReadableStream(otherId, { count: 2 }) - .on('data', data => { - expect(data).to.be.an('object') - expect(data).to.have.keys('success', 'time', 'text') - if (isPong(data)) packetNum++ - }) - .on('error', err => { - expect(err).not.to.exist() - }) - .on('end', () => { - expect(packetNum).to.equal(2) - done() - }) - }) }) diff --git a/test/request-api.spec.js b/test/request-api.spec.js index c213193bb..1767b5914 100644 --- a/test/request-api.spec.js +++ b/test/request-api.spec.js @@ -2,16 +2,12 @@ 'use strict' const { expect } = require('interface-ipfs-core/src/utils/mocha') -const isNode = require('detect-node') +const { isNode } = require('ipfs-utils/src/env') const ipfsClient = require('../src/index.js') -const ndjson = require('ndjson') -const pump = require('pump') describe('\'deal with HTTP weirdness\' tests', () => { - it('does not crash if no content-type header is provided', (done) => { - if (!isNode) { - return done() - } + it('does not crash if no content-type header is provided', async function () { + if (!isNode) return this.skip() // go-ipfs always (currently) adds a content-type header, even if no content is present, // the standard behaviour for an http-api is to omit this header if no content is present @@ -24,12 +20,10 @@ describe('\'deal with HTTP weirdness\' tests', () => { }) }) - server.listen(6001, () => { - ipfsClient('/ip4/127.0.0.1/tcp/6001').config.replace('test/fixtures/r-config.json', (err) => { - expect(err).to.not.exist() - server.close(done) - }) - }) + await new Promise(resolve => server.listen(6001, resolve)) + await ipfsClient('/ip4/127.0.0.1/tcp/6001').config.replace('test/fixtures/r-config.json') + + server.close() }) }) @@ -39,12 +33,11 @@ describe('trailer headers', () => { if (!isNode) { return done() } const server = require('http').createServer((req, res) => { - const resStream = pump(res, ndjson.stringify()) res.setHeader('x-chunked-output', '1') res.setHeader('content-type', 'application/json') res.setHeader('Trailer', 'X-Stream-Error') res.addTrailers({ 'X-Stream-Error': JSON.stringify({ Message: 'ups, something went wrong', Code: 500 }) }) - resStream.write({ Bytes: 1 }) + res.write(JSON.stringify({ Bytes: 1 })) res.end() }) @@ -64,7 +57,7 @@ describe('trailer headers', () => { }) describe('error handling', () => { - it('should handle plain text error response', function (done) { + it('should handle plain text error response', async function () { if (!isNode) return this.skip() const server = require('http').createServer((req, res) => { @@ -78,17 +71,16 @@ describe('error handling', () => { }) }) - server.listen(6001, () => { - ipfsClient('/ip4/127.0.0.1/tcp/6001').config.replace('test/fixtures/r-config.json', (err) => { - expect(err).to.exist() - expect(err.response.status).to.equal(403) - expect(err.message).to.equal('ipfs method not allowed') - server.close(done) - }) - }) + await new Promise(resolve => server.listen(6001, resolve)) + + await expect(ipfsClient('/ip4/127.0.0.1/tcp/6001').config.replace('test/fixtures/r-config.json')) + .to.eventually.be.rejectedWith('ipfs method not allowed') + .and.to.have.nested.property('response.status').that.equals(403) + + server.close() }) - it('should handle JSON error response', function (done) { + it('should handle JSON error response', async function () { if (!isNode) return this.skip() const server = require('http').createServer((req, res) => { @@ -102,17 +94,16 @@ describe('error handling', () => { }) }) - server.listen(6001, () => { - ipfsClient('/ip4/127.0.0.1/tcp/6001').config.replace('test/fixtures/r-config.json', (err) => { - expect(err).to.exist() - expect(err.response.status).to.equal(400) - expect(err.message).to.equal('client error') - server.close(done) - }) - }) + await new Promise(resolve => server.listen(6001, resolve)) + + await expect(ipfsClient('/ip4/127.0.0.1/tcp/6001').config.replace('test/fixtures/r-config.json')) + .to.eventually.be.rejectedWith('client error') + .and.to.have.nested.property('response.status').that.equals(400) + + server.close() }) - it('should handle JSON error response with invalid JSON', function (done) { + it('should handle JSON error response with invalid JSON', async function () { if (!isNode) return this.skip() const server = require('http').createServer((req, res) => { @@ -126,12 +117,12 @@ describe('error handling', () => { }) }) - server.listen(6001, () => { - ipfsClient('/ip4/127.0.0.1/tcp/6001').config.replace('test/fixtures/r-config.json', (err) => { - expect(err).to.exist() - expect(err.message).to.include('Unexpected token M in JSON at position 2') - server.close(done) - }) - }) + await new Promise(resolve => server.listen(6001, resolve)) + + await expect(ipfsClient('/ip4/127.0.0.1/tcp/6001').config.replace('test/fixtures/r-config.json')) + .to.eventually.be.rejected() + .and.to.have.property('message').that.includes('Unexpected token M in JSON at position 2') + + server.close() }) }) diff --git a/test/stats.spec.js b/test/stats.spec.js index d60aaa330..1e5d7da25 100644 --- a/test/stats.spec.js +++ b/test/stats.spec.js @@ -2,6 +2,7 @@ 'use strict' const { expect } = require('interface-ipfs-core/src/utils/mocha') +const all = require('it-all') const f = require('./utils/factory') describe('stats', function () { @@ -31,7 +32,7 @@ describe('stats', function () { }) it('.stats.bw', async () => { - const res = await ipfs.stats.bw() + const res = (await all(ipfs.stats.bw()))[0] expect(res).to.exist() expect(res).to.have.a.property('totalIn') diff --git a/test/sub-modules.spec.js b/test/sub-modules.spec.js index ee8f6d93b..a5db456df 100644 --- a/test/sub-modules.spec.js +++ b/test/sub-modules.spec.js @@ -64,12 +64,8 @@ describe('submodules', () => { it('ping', () => { const ping = require('../src')().ping - const pingPullStream = require('../src')().pingPullStream - const pingReadableStream = require('../src')().pingReadableStream expect(ping).to.be.a('function') - expect(pingPullStream).to.be.a('function') - expect(pingReadableStream).to.be.a('function') }) it('log', () => { @@ -164,26 +160,11 @@ describe('submodules', () => { const filesRegular = require('../src')() expect(filesRegular.add).to.be.a('function') - expect(filesRegular.addReadableStream).to.be.a('function') - expect(filesRegular.addPullStream).to.be.a('function') - expect(filesRegular.addFromStream).to.be.a('function') - expect(filesRegular.addFromFs).to.be.a('function') - expect(filesRegular.addFromURL).to.be.a('function') expect(filesRegular.get).to.be.a('function') - expect(filesRegular.getReadableStream).to.be.a('function') - expect(filesRegular.getPullStream).to.be.a('function') expect(filesRegular.cat).to.be.a('function') - expect(filesRegular.catReadableStream).to.be.a('function') - expect(filesRegular.catPullStream).to.be.a('function') expect(filesRegular.ls).to.be.a('function') - expect(filesRegular.lsReadableStream).to.be.a('function') - expect(filesRegular.lsPullStream).to.be.a('function') expect(filesRegular.refs).to.be.a('function') - expect(filesRegular.refsReadableStream).to.be.a('function') - expect(filesRegular.refsPullStream).to.be.a('function') expect(filesRegular.refs.local).to.be.a('function') - expect(filesRegular.refs.localReadableStream).to.be.a('function') - expect(filesRegular.refs.localPullStream).to.be.a('function') }) it('files MFS API', () => { diff --git a/test/utils/expect-timeout.js b/test/utils/expect-timeout.js deleted file mode 100644 index 51c733075..000000000 --- a/test/utils/expect-timeout.js +++ /dev/null @@ -1,16 +0,0 @@ -'use strict' - -/** - * Resolve if @param promise hangs for at least @param ms, throw otherwise - * @param {Promise} promise promise that you expect to hang - * @param {Number} ms millis to wait - * @return {Promise} - */ -module.exports = (promise, ms) => { - return Promise.race([ - promise.then((out) => { - throw new Error('Expected Promise to timeout but it was successful.') - }), - new Promise((resolve, reject) => setTimeout(resolve, ms)) - ]) -} From e74c42f2d7a3c5616fd3e114c875e80ff0bb1998 Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Thu, 23 Jan 2020 20:25:46 +0000 Subject: [PATCH 221/233] chore: update contributors --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index add5c2ebb..5fe20ecc4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ipfs-http-client", - "version": "41.0.1", + "version": "42.0.0-pre.0", "description": "A client library for the IPFS HTTP API", "keywords": [ "ipfs" @@ -83,7 +83,6 @@ "Alan Shaw ", "Alan Shaw ", "Alex Mingoia ", - "Alex Potsides ", "Antonio Tenorio-Fornés ", "Bruno Barbieri ", "Clemo ", @@ -161,6 +160,7 @@ "Victor Bjelkholm ", "Volker Mische ", "Zhiyuan Lin ", + "achingbrain ", "dirkmc ", "dmitriy ryajov ", "elsehow ", From e9aaa750beeb000f485fb31d43d2af648676dc8e Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Thu, 23 Jan 2020 20:25:47 +0000 Subject: [PATCH 222/233] chore: release version v42.0.0-pre.0 --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 55592d9dc..709438c6b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ + +# [42.0.0-pre.0](https://github.com/ipfs/js-ipfs-http-client/compare/v41.0.1...v42.0.0-pre.0) (2020-01-23) + + + ## [41.0.1](https://github.com/ipfs/js-ipfs-http-client/compare/v41.0.0...v41.0.1) (2020-01-23) From 2a9d7657a96fad9af48dfce56f73be2697a3db6b Mon Sep 17 00:00:00 2001 From: Alex Potsides Date: Fri, 31 Jan 2020 12:46:37 +0000 Subject: [PATCH 223/233] refactor: return peer ids as strings (#1226) BREAKING CHANGE: Where `PeerID`s were previously [CID]s, now they are Strings - `ipfs.bitswap.stat().peers[n]` is now a String (was a CID) - `ipfs.dht.findPeer().id` is now a String (was a CID) - `ipfs.dht.findProvs()[n].id` is now a String (was a CID) - `ipfs.dht.provide()[n].id` is now a String (was a CID) - `ipfs.dht.put()[n].id` is now a String (was a CID) - `ipfs.dht.query()[n].id` is now a String (was a CID) - `ipfs.id().id` is now a String (was a CID) - `ipfs.id().addresses[n]` are now [Multiaddr]s (were Strings) --- package.json | 4 ++-- src/bitswap/stat.js | 2 +- src/dht/find-peer.js | 2 +- src/dht/find-provs.js | 2 +- src/dht/provide.js | 2 +- src/dht/put.js | 2 +- src/dht/query.js | 2 +- src/id.js | 9 ++++++++- src/swarm/addrs.js | 3 +-- src/swarm/peers.js | 3 +-- 10 files changed, 18 insertions(+), 13 deletions(-) diff --git a/package.json b/package.json index 5fe20ecc4..844f26807 100644 --- a/package.json +++ b/package.json @@ -68,8 +68,8 @@ "async": "^3.1.0", "browser-process-platform": "~0.1.1", "go-ipfs-dep": "^0.4.22", - "interface-ipfs-core": "^0.129.0", - "ipfsd-ctl": "^1.0.2", + "interface-ipfs-core": "^0.131.0", + "ipfsd-ctl": "^2.1.0", "it-all": "^1.0.1", "it-concat": "^1.0.0", "it-pipe": "^1.1.0", diff --git a/src/bitswap/stat.js b/src/bitswap/stat.js index e041f5d9d..36101a1f4 100644 --- a/src/bitswap/stat.js +++ b/src/bitswap/stat.js @@ -23,7 +23,7 @@ function toCoreInterface (res) { return { provideBufLen: res.ProvideBufLen, wantlist: (res.Wantlist || []).map(k => new CID(k['/'])), - peers: (res.Peers || []).map(p => new CID(p)), + peers: (res.Peers || []), blocksReceived: new Big(res.BlocksReceived), dataReceived: new Big(res.DataReceived), blocksSent: new Big(res.BlocksSent), diff --git a/src/dht/find-peer.js b/src/dht/find-peer.js index 9d8f517e5..ef5c6c92a 100644 --- a/src/dht/find-peer.js +++ b/src/dht/find-peer.js @@ -37,7 +37,7 @@ module.exports = configure(({ ky }) => { // https://github.com/ipfs/go-ipfs/blob/eb11f569b064b960d1aba4b5b8ca155a3bd2cb21/core/commands/dht.go#L395-L396 for (const { ID, Addrs } of message.Responses) { return { - id: new CID(ID), + id: ID, addrs: (Addrs || []).map(a => multiaddr(a)) } } diff --git a/src/dht/find-provs.js b/src/dht/find-provs.js index 7adbaf38c..e70935dec 100644 --- a/src/dht/find-provs.js +++ b/src/dht/find-provs.js @@ -35,7 +35,7 @@ module.exports = configure(({ ky }) => { if (message.Type === 4 && message.Responses) { for (const { ID, Addrs } of message.Responses) { yield { - id: new CID(ID), + id: ID, addrs: (Addrs || []).map(a => multiaddr(a)) } } diff --git a/src/dht/provide.js b/src/dht/provide.js index f9013bfed..cdcae2f84 100644 --- a/src/dht/provide.js +++ b/src/dht/provide.js @@ -36,7 +36,7 @@ module.exports = configure(({ ky }) => { message.id = new CID(message.id) if (message.responses) { message.responses = message.responses.map(({ ID, Addrs }) => ({ - id: new CID(ID), + id: ID, addrs: (Addrs || []).map(a => multiaddr(a)) })) } else { diff --git a/src/dht/put.js b/src/dht/put.js index 6d0ecf6fc..8dc924f7a 100644 --- a/src/dht/put.js +++ b/src/dht/put.js @@ -38,7 +38,7 @@ module.exports = configure(({ ky }) => { message.id = new CID(message.id) if (message.responses) { message.responses = message.responses.map(({ ID, Addrs }) => ({ - id: new CID(ID), + id: ID, addrs: (Addrs || []).map(a => multiaddr(a)) })) } diff --git a/src/dht/query.js b/src/dht/query.js index 1628c0cc8..b2b878572 100644 --- a/src/dht/query.js +++ b/src/dht/query.js @@ -26,7 +26,7 @@ module.exports = configure(({ ky }) => { message = toCamel(message) message.id = new CID(message.id) message.responses = (message.responses || []).map(({ ID, Addrs }) => ({ - id: new CID(ID), + id: ID, addrs: (Addrs || []).map(a => multiaddr(a)) })) yield message diff --git a/src/id.js b/src/id.js index d6080ea67..cfec69d3d 100644 --- a/src/id.js +++ b/src/id.js @@ -2,6 +2,7 @@ const configure = require('./lib/configure') const toCamel = require('./lib/object-to-camel') +const multiaddr = require('multiaddr') module.exports = configure(({ ky }) => { return async options => { @@ -14,6 +15,12 @@ module.exports = configure(({ ky }) => { searchParams: options.searchParams }).json() - return toCamel(res) + const output = toCamel(res) + + if (output.addresses) { + output.addresses = output.addresses.map(ma => multiaddr(ma)) + } + + return output } }) diff --git a/src/swarm/addrs.js b/src/swarm/addrs.js index 25bd98d02..c4b6576f6 100644 --- a/src/swarm/addrs.js +++ b/src/swarm/addrs.js @@ -1,6 +1,5 @@ 'use strict' -const CID = require('cids') const multiaddr = require('multiaddr') const configure = require('../lib/configure') @@ -16,7 +15,7 @@ module.exports = configure(({ ky }) => { }).json() return Object.keys(res.Addrs).map(id => ({ - id: new CID(id), + id, addrs: (res.Addrs[id] || []).map(a => multiaddr(a)) })) } diff --git a/src/swarm/peers.js b/src/swarm/peers.js index f10035e06..8388af49f 100644 --- a/src/swarm/peers.js +++ b/src/swarm/peers.js @@ -1,7 +1,6 @@ 'use strict' const multiaddr = require('multiaddr') -const CID = require('cids') const configure = require('../lib/configure') module.exports = configure(({ ky }) => { @@ -25,7 +24,7 @@ module.exports = configure(({ ky }) => { const info = {} try { info.addr = multiaddr(peer.Addr) - info.peer = new CID(peer.Peer) + info.peer = peer.Peer } catch (error) { info.error = error info.rawPeerInfo = peer From 00cdba5922368e518142b450370b537e7689c9d3 Mon Sep 17 00:00:00 2001 From: achingbrain Date: Fri, 31 Jan 2020 12:48:09 +0000 Subject: [PATCH 224/233] chore: update bundle size --- .aegir.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.aegir.js b/.aegir.js index 69e938893..2e5fb64db 100644 --- a/.aegir.js +++ b/.aegir.js @@ -6,7 +6,7 @@ const server = createServer() const echoServer = EchoServer.createServer() module.exports = { - bundlesize: { maxSize: '246kB' }, + bundlesize: { maxSize: '90kB' }, webpack: { resolve: { mainFields: ['browser', 'main'] From ddce43dade36e650f32d5dc1ea96594014814f99 Mon Sep 17 00:00:00 2001 From: achingbrain Date: Fri, 31 Jan 2020 12:48:28 +0000 Subject: [PATCH 225/233] 42.0.0-pre.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 844f26807..fa23fad33 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ipfs-http-client", - "version": "42.0.0-pre.0", + "version": "42.0.0-pre.1", "description": "A client library for the IPFS HTTP API", "keywords": [ "ipfs" From 7d05429859936391a7982a37ea01fbead10a7f58 Mon Sep 17 00:00:00 2001 From: achingbrain Date: Fri, 31 Jan 2020 12:53:56 +0000 Subject: [PATCH 226/233] 42.0.0-pre.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index fa23fad33..0328f7e27 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ipfs-http-client", - "version": "42.0.0-pre.1", + "version": "42.0.0-pre.2", "description": "A client library for the IPFS HTTP API", "keywords": [ "ipfs" From d3eee0dc40f00b7a767ae8efb1057b4ddcdca25a Mon Sep 17 00:00:00 2001 From: Alex Potsides Date: Mon, 3 Feb 2020 13:13:53 +0000 Subject: [PATCH 227/233] fix: interface tests (#1233) * chore: update go-ipfs-dep * chore: build webworkers separately --- .travis.yml | 16 ++++++++++++++-- examples/browser-pubsub/README.md | 2 +- package.json | 4 ++-- 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index 802efe943..0509e5a96 100644 --- a/.travis.yml +++ b/.travis.yml @@ -35,13 +35,25 @@ jobs: name: chrome addons: chrome: stable - script: npx aegir test -t browser -t webworker + script: npx aegir test -t browser + + - stage: test + name: chrome webworker + addons: + chrome: stable + script: npx aegir test -t webworker - stage: test name: firefox addons: firefox: latest - script: npx aegir test -t browser -t webworker -- --browsers FirefoxHeadless + script: npx aegir test -t browser -- --browsers FirefoxHeadless + + - stage: test + name: firefox webworker + addons: + firefox: latest + script: npx aegir test -t webworker -- --browsers FirefoxHeadless - stage: test name: electron-main diff --git a/examples/browser-pubsub/README.md b/examples/browser-pubsub/README.md index abe6a21f9..a74f77604 100644 --- a/examples/browser-pubsub/README.md +++ b/examples/browser-pubsub/README.md @@ -64,7 +64,7 @@ jsipfs init # Configure CORS to allow ipfs-http-client to access this IPFS node jsipfs config --json API.HTTPHeaders.Access-Control-Allow-Origin '["http://127.0.0.1:8888"]' # Start the IPFS node, enabling pubsub -jsipfs daemon --enable-pubsub-experiment +jsipfs daemon ``` ### Install and start the Go IPFS node diff --git a/package.json b/package.json index 0328f7e27..ccc412bcb 100644 --- a/package.json +++ b/package.json @@ -67,8 +67,8 @@ "aegir": "^20.4.1", "async": "^3.1.0", "browser-process-platform": "~0.1.1", - "go-ipfs-dep": "^0.4.22", - "interface-ipfs-core": "^0.131.0", + "go-ipfs-dep": "^0.4.23", + "interface-ipfs-core": "^0.131.7", "ipfsd-ctl": "^2.1.0", "it-all": "^1.0.1", "it-concat": "^1.0.0", From 74a91471ff11201989306953c84b50abc301b548 Mon Sep 17 00:00:00 2001 From: Hugo Dias Date: Tue, 4 Feb 2020 11:28:39 +0000 Subject: [PATCH 228/233] docs: port examples to new api (#1222) * fix: change name-api examples to new api * fix: change files-api example to new api * fix: change upload example to new api * fix: change bundle-webpack to support new api * fix: remove browserify example doesnt support imports * fix: change pubsub example to the new api * Update examples/bundle-webpack/src/App.js Co-Authored-By: Alan Shaw * Update examples/bundle-webpack/src/App.js Co-Authored-By: Alan Shaw * Update examples/files-api/files-api.js Co-Authored-By: Alan Shaw * Update examples/upload-file-via-browser/src/App.js Co-Authored-By: Alan Shaw * Update examples/upload-file-via-browser/src/App.js Co-Authored-By: Alan Shaw Co-authored-by: Alan Shaw --- examples/browser-pubsub/index.html | 2 +- examples/browser-pubsub/package.json | 13 +- examples/bundle-browserify/.gitignore | 1 - examples/bundle-browserify/README.md | 35 - examples/bundle-browserify/img/1.png | Bin 100527 -> 0 bytes examples/bundle-browserify/img/2.png | Bin 146800 -> 0 bytes examples/bundle-browserify/index.html | 26 - examples/bundle-browserify/index.js | 36 - examples/bundle-browserify/package.json | 18 - examples/bundle-webpack/package.json | 5 +- examples/bundle-webpack/src/App.js | 37 +- examples/files-api/files-api.js | 27 +- examples/name-api/index.html | 3 +- examples/name-api/index.js | 57 +- examples/name-api/package-lock.json | 25332 +++++++++++++++- examples/name-api/package.json | 13 +- examples/upload-file-via-browser/README.md | 3 - examples/upload-file-via-browser/index.html | 2 +- examples/upload-file-via-browser/package.json | 27 +- examples/upload-file-via-browser/src/App.js | 54 +- examples/upload-file-via-browser/src/index.js | 1 + .../upload-file-via-browser/webpack.config.js | 37 - 22 files changed, 24529 insertions(+), 1200 deletions(-) delete mode 100644 examples/bundle-browserify/.gitignore delete mode 100644 examples/bundle-browserify/README.md delete mode 100644 examples/bundle-browserify/img/1.png delete mode 100644 examples/bundle-browserify/img/2.png delete mode 100644 examples/bundle-browserify/index.html delete mode 100644 examples/bundle-browserify/index.js delete mode 100644 examples/bundle-browserify/package.json delete mode 100644 examples/upload-file-via-browser/webpack.config.js diff --git a/examples/browser-pubsub/index.html b/examples/browser-pubsub/index.html index d5d84d564..22a0d4765 100644 --- a/examples/browser-pubsub/index.html +++ b/examples/browser-pubsub/index.html @@ -37,6 +37,6 @@

Pubsub

- + diff --git a/examples/browser-pubsub/package.json b/examples/browser-pubsub/package.json index c4c6e2727..6e519bf9e 100644 --- a/examples/browser-pubsub/package.json +++ b/examples/browser-pubsub/package.json @@ -5,16 +5,17 @@ "private": true, "main": "index.js", "scripts": { - "start": "npm run build && npm run serve", - "build": "browserify index.js > bundle.js", - "serve": "http-server -a 127.0.0.1 -p 8888", - "test": "echo \"Error: no test specified\" && exit 1" + "start": "parcel index.html" }, "author": "Alan Shaw", "license": "MIT", "dependencies": { - "browserify": "^16.5.0", - "http-server": "^0.11.1", "ipfs-http-client": "../../" + }, + "browserslist": [ + "last 2 versions and not dead and > 2%" + ], + "devDependencies": { + "parcel-bundler": "^1.12.4" } } diff --git a/examples/bundle-browserify/.gitignore b/examples/bundle-browserify/.gitignore deleted file mode 100644 index 4187d6774..000000000 --- a/examples/bundle-browserify/.gitignore +++ /dev/null @@ -1 +0,0 @@ -bundle.js \ No newline at end of file diff --git a/examples/bundle-browserify/README.md b/examples/bundle-browserify/README.md deleted file mode 100644 index def887200..000000000 --- a/examples/bundle-browserify/README.md +++ /dev/null @@ -1,35 +0,0 @@ -# Bundle js-ipfs-http-client with Browserify! - -> In this example, you will find a boilerplate you can use to guide yourself into bundling js-ipfs-http-client with browserify, so that you can use it in your own web app! - -## Setup - -As for any js-ipfs-http-client example, **you need a running IPFS daemon**, you learn how to do that here: - -- [Spawn a go-ipfs daemon](https://ipfs.io/docs/getting-started/) -- [Spawn a js-ipfs daemon](https://github.com/ipfs/js-ipfs#usage) - -**Note:** If you load your app from a different domain than the one the daemon is running (most probably), you will need to set up CORS, see https://github.com/ipfs/js-ipfs-http-client#cors to learn how to do that. - -A quick (and dirty) way to get it done is: - -```bash -> ipfs config --json API.HTTPHeaders.Access-Control-Allow-Origin "[\"*\"]" -> ipfs config --json API.HTTPHeaders.Access-Control-Allow-Credentials "[\"true\"]" -``` - -## Run this example - -Once the daemon is on, run the following commands within this folder: - -```bash -> npm install -> npm start -``` - -Now open your browser at `http://localhost:8888` - -You should see the following: - -![](https://ipfs.io/ipfs/QmNtpcWCEd6LjdPNfBFDaVZdD4jpgT8ZTAwoFJXKhYMJdo/1.png) -![](https://ipfs.io/ipfs/QmNtpcWCEd6LjdPNfBFDaVZdD4jpgT8ZTAwoFJXKhYMJdo/2.png) diff --git a/examples/bundle-browserify/img/1.png b/examples/bundle-browserify/img/1.png deleted file mode 100644 index 580511dad7510b8791f5c73ac03c37512580d649..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 100527 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 O2s~Z=T-G@yGywofrixJj diff --git a/examples/bundle-browserify/img/2.png b/examples/bundle-browserify/img/2.png deleted file mode 100644 index 5c72fc0a38aa7f6e27b933958355551178cf59b8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 146800 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�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 - - - - JS IPFS API - Example - Browser - Add - - - - -

JS IPFS API - Add data to IPFS from the browser

- - -
-
found in ipfs:
-
[ipfs hash]
-
[ipfs content]
-
- - diff --git a/examples/bundle-browserify/index.js b/examples/bundle-browserify/index.js deleted file mode 100644 index b0bc9f15e..000000000 --- a/examples/bundle-browserify/index.js +++ /dev/null @@ -1,36 +0,0 @@ -'use strict' - -var IPFS = require('ipfs-http-client') - -var ipfs = IPFS() - -function store () { - var toStore = document.getElementById('source').value - ipfs.add(Buffer.from(toStore), function (err, res) { - if (err || !res) { - return console.error('ipfs add error', err, res) - } - - res.forEach(function (file) { - if (file && file.hash) { - console.log('successfully stored', file.hash) - display(file.hash) - } - }) - }) -} - -function display (hash) { - ipfs.cat(hash, function (err, res) { - if (err || !res) { - return console.error('ipfs cat error', err, res) - } - - document.getElementById('hash').innerText = hash - document.getElementById('content').innerText = res.toString() - }) -} - -document.addEventListener('DOMContentLoaded', function () { - document.getElementById('store').onclick = store -}) diff --git a/examples/bundle-browserify/package.json b/examples/bundle-browserify/package.json deleted file mode 100644 index 7245b9c3a..000000000 --- a/examples/bundle-browserify/package.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "name": "bundle-browserify", - "version": "1.0.0", - "description": "Bundle js-ipfs-http-client with Browserify", - "main": "index.js", - "scripts": { - "start": "browserify index.js > bundle.js && http-server -a 127.0.0.1 -p 8888" - }, - "keywords": [], - "author": "Friedel Ziegelmayer", - "license": "MIT", - "devDependencies": { - "browserify": "^16.2.3", - "ipfs-http-client": "../../", - "http-server": "~0.11.1" - }, - "dependencies": {} -} diff --git a/examples/bundle-webpack/package.json b/examples/bundle-webpack/package.json index bfa0b9428..7141efa03 100644 --- a/examples/bundle-webpack/package.json +++ b/examples/bundle-webpack/package.json @@ -21,9 +21,6 @@ "webpack-dev-server": "~3.3.1" }, "browserslist": [ - ">1%", - "not dead", - "not ie <= 11", - "not op_mini all" + "last 2 versions and not dead and > 2%" ] } diff --git a/examples/bundle-webpack/src/App.js b/examples/bundle-webpack/src/App.js index 06bf81991..bc25b5b81 100644 --- a/examples/bundle-webpack/src/App.js +++ b/examples/bundle-webpack/src/App.js @@ -2,7 +2,7 @@ const React = require('react') const ipfsClient = require('ipfs-http-client') -const ipfs = ipfsClient('localhost', '5001') +const ipfs = ipfsClient('/ip4/127.0.0.1/tcp/5001') const stringToUse = 'hello world from webpacked IPFS' class App extends React.Component { @@ -16,24 +16,27 @@ class App extends React.Component { added_file_contents: null } } - componentDidMount () { - ipfs.id((err, res) => { - if (err) throw err - this.setState({ - id: res.id, - version: res.agentVersion, - protocol_version: res.protocolVersion - }) + async componentDidMount () { + const id = await ipfs.id() + this.setState({ + id: id.id, + version: id.agentVersion, + protocol_version: id.protocolVersion }) - ipfs.add([Buffer.from(stringToUse)], (err, res) => { - if (err) throw err - const hash = res[0].hash + + const source = ipfs.add(stringToUse) + for await (const file of source) { + console.log("TCL: App -> forawait -> file", file) + const hash = file.path this.setState({ added_file_hash: hash }) - ipfs.cat(hash, (err, data) => { - if (err) throw err - this.setState({ added_file_contents: data.toString() }) - }) - }) + + const source = ipfs.cat(hash) + const data = [] + for await (const chunk of source) { + data.push(chunk) + } + this.setState({ added_file_contents: Buffer.concat(data).toString() }) + } } render () { return
diff --git a/examples/files-api/files-api.js b/examples/files-api/files-api.js index fefc957d6..308c3fc9e 100644 --- a/examples/files-api/files-api.js +++ b/examples/files-api/files-api.js @@ -1,14 +1,21 @@ +/* eslint-disable no-console */ 'use strict' -const ipfs = require('../../src')('localhost', 5001) +// Run `ipfs daemon` in your terminal to start the IPFS daemon +// Look for `API server listening on /ip4/127.0.0.1/tcp/5001` +const ipfs = require('../../src')('/ip4/127.0.0.1/tcp/5001') -ipfs.files.ls('/folder1', function (err, res) { - if (err) { - return console.log('got an error', err) - } - if (res.readable) { - res.pipe(process.stdout) - } else { - console.log(res) +const run = async () => { + await ipfs.files.write( + '/temp/hello-world', + Buffer.from('Hello, world!'), + { create: true, parents: true } + ) + const source = ipfs.files.ls('/temp') + + for await (const file of source) { + console.log(file) } -}) +} + +run() diff --git a/examples/name-api/index.html b/examples/name-api/index.html index 3e5fba013..54843d332 100644 --- a/examples/name-api/index.html +++ b/examples/name-api/index.html @@ -58,7 +58,6 @@

Resolve an IPNS name

- - + diff --git a/examples/name-api/index.js b/examples/name-api/index.js index 931f5560e..b65c43fd3 100644 --- a/examples/name-api/index.js +++ b/examples/name-api/index.js @@ -1,6 +1,7 @@ +/* eslint-disable no-console */ 'use strict' - -const ipfs = window.IpfsHttpClient('/ip4/127.0.0.1/tcp/5001') +const ipfsHttp = require('ipfs-http-client') +const ipfs = ipfsHttp('/ip4/127.0.0.1/tcp/5001') const DOM = { status: document.getElementById('status'), @@ -30,7 +31,7 @@ const showStatus = (text, bg) => { } const enableForms = () => { - for (let btn of DOM.buttons) { + for (const btn of DOM.buttons) { btn.disabled = false } } @@ -48,31 +49,30 @@ const init = () => { } // Adds a new file to IPFS and publish it -const addAndPublish = (e) => { +const addAndPublish = async (e) => { e.preventDefault() - let input = e.target.elements['text'] - let buffer = Buffer.from(input.value) + const input = e.target.elements.text + const buffer = Buffer.from(input.value) showStatus('adding to IPFS...', COLORS.active) + try { + for await (const file of ipfs.add(buffer)) { + showStatus('success!', COLORS.success) - ipfs.add(buffer) - .then(res => { - showStatus(`success!`, COLORS.success) - - publish(res[0].path) + publish(file.path) input.value = '' - }) - .catch(err => { - showStatus('failed to add the data', COLORS.error) - console.error(err) - }) + } + } catch (err) { + showStatus('failed to add the data', COLORS.error) + console.error(err) + } } // Publishes an IPFS file or directory under your node's identity const publish = (path) => { - showStatus(`publishing...`, COLORS.active) + showStatus('publishing...', COLORS.active) DOM.publishResultsDiv.classList.add('hidden') ipfs.name.publish(path) @@ -90,21 +90,20 @@ const publish = (path) => { } // Resolves an IPNS name -const resolve = (name) => { - showStatus(`resolving...`, COLORS.active) +const resolve = async (name) => { + showStatus('resolving...', COLORS.active) DOM.resolveResultsDiv.classList.add('hidden') - - ipfs.name.resolve(name) - .then(path => { + try { + for await (const path of ipfs.name.resolve(name)) { showStatus('success!', COLORS.success) DOM.resolveResultsDiv.classList.remove('hidden') DOM.resolveResult.innerText = path DOM.resolveGatewayLink.href = `${IPFS_DOMAIN}${path}` - }) - .catch(err => { - showStatus(`error resolving ${name}`, COLORS.error) - console.error(err) - }) + } + } catch (err) { + showStatus(`error resolving ${name}`, COLORS.error) + console.error(err) + } } // Event listeners @@ -112,14 +111,14 @@ DOM.publishNew.onsubmit = addAndPublish DOM.publishPath.onsubmit = (e) => { e.preventDefault() - let input = e.target.elements['path'] + const input = e.target.elements.path publish(input.value) input.value = '' } DOM.resolveName.onsubmit = (e) => { e.preventDefault() - let input = e.target.elements['name'] + const input = e.target.elements.name resolve(input.value) input.value = '' } diff --git a/examples/name-api/package-lock.json b/examples/name-api/package-lock.json index e30d976fb..f0484619d 100644 --- a/examples/name-api/package-lock.json +++ b/examples/name-api/package-lock.json @@ -4,1276 +4,24560 @@ "lockfileVersion": 1, "requires": true, "dependencies": { - "JSONStream": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", - "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", - "dev": true, - "requires": { - "jsonparse": "^1.2.0", - "through": ">=2.2.7 <3" - } - }, - "acorn": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.2.0.tgz", - "integrity": "sha512-8oe72N3WPMjA+2zVG71Ia0nXZ8DpQH+QyyHO+p06jT8eg8FGG3FbcUIi8KziHlAfheJQZeoqbvq1mQSQHXKYLw==", - "dev": true - }, - "acorn-dynamic-import": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/acorn-dynamic-import/-/acorn-dynamic-import-4.0.0.tgz", - "integrity": "sha512-d3OEjQV4ROpoflsnUA8HozoIR504TFxNivYEUi6uwz0IYhBkTDXGuWlNdMtybRt3nqVx/L6XqMt0FxkXuWKZhw==", - "dev": true - }, - "acorn-node": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.7.0.tgz", - "integrity": "sha512-XhahLSsCB6X6CJbe+uNu3Mn9sJBNFxtBN9NLgAOQovfS6Kh0lDUtmlclhjn9CvEK7A7YyRU13PXlNcpSiLI9Yw==", + "@babel/code-frame": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz", + "integrity": "sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==", "dev": true, "requires": { - "acorn": "^6.1.1", - "acorn-dynamic-import": "^4.0.0", - "acorn-walk": "^6.1.1", - "xtend": "^4.0.1" + "@babel/highlight": "^7.8.3" } }, - "acorn-walk": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.2.0.tgz", - "integrity": "sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA==", - "dev": true - }, - "array-filter": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/array-filter/-/array-filter-0.0.1.tgz", - "integrity": "sha1-fajPLiZijtcygDWB/SH2fKzS7uw=", - "dev": true - }, - "array-map": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/array-map/-/array-map-0.0.0.tgz", - "integrity": "sha1-iKK6tz0c97zVwbEYoAP2b2ZfpmI=", - "dev": true - }, - "array-reduce": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/array-reduce/-/array-reduce-0.0.0.tgz", - "integrity": "sha1-FziZ0//Rx9k4PkR5Ul2+J4yrXys=", - "dev": true - }, - "asn1.js": { - "version": "4.10.1", - "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", - "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", + "@babel/compat-data": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.8.1.tgz", + "integrity": "sha512-Z+6ZOXvyOWYxJ50BwxzdhRnRsGST8Y3jaZgxYig575lTjVSs3KtJnmESwZegg6e2Dn0td1eDhoWlp1wI4BTCPw==", "dev": true, "requires": { - "bn.js": "^4.0.0", - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0" + "browserslist": "^4.8.2", + "invariant": "^2.2.4", + "semver": "^5.5.0" } }, - "assert": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/assert/-/assert-1.5.0.tgz", - "integrity": "sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA==", + "@babel/core": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.8.3.tgz", + "integrity": "sha512-4XFkf8AwyrEG7Ziu3L2L0Cv+WyY47Tcsp70JFmpftbAA1K7YL/sgE9jh9HyNj08Y/U50ItUchpN0w6HxAoX1rA==", "dev": true, "requires": { - "object-assign": "^4.1.1", - "util": "0.10.3" + "@babel/code-frame": "^7.8.3", + "@babel/generator": "^7.8.3", + "@babel/helpers": "^7.8.3", + "@babel/parser": "^7.8.3", + "@babel/template": "^7.8.3", + "@babel/traverse": "^7.8.3", + "@babel/types": "^7.8.3", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.1", + "json5": "^2.1.0", + "lodash": "^4.17.13", + "resolve": "^1.3.2", + "semver": "^5.4.1", + "source-map": "^0.5.0" }, "dependencies": { - "inherits": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", - "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", - "dev": true + "convert-source-map": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", + "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.1" + } }, - "util": { - "version": "0.10.3", - "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", - "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", + "json5": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.1.tgz", + "integrity": "sha512-l+3HXD0GEI3huGq1njuqtzYK8OYJyXMkOLtQ53pjWh89tvWS2h6l+1zMkYWqlb57+SiQodKZyvMEFb2X+KrFhQ==", "dev": true, "requires": { - "inherits": "2.0.1" + "minimist": "^1.2.0" } + }, + "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==", + "dev": true } } }, - "balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true - }, - "base64-js": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.0.tgz", - "integrity": "sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw==", - "dev": true - }, - "bn.js": { - "version": "4.11.8", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", - "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", - "dev": true + "@babel/generator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.8.3.tgz", + "integrity": "sha512-WjoPk8hRpDRqqzRpvaR8/gDUPkrnOOeuT2m8cNICJtZH6mwaCo3v0OKMI7Y6SM1pBtyijnLtAL0HDi41pf41ug==", + "dev": true, + "requires": { + "@babel/types": "^7.8.3", + "jsesc": "^2.5.1", + "lodash": "^4.17.13", + "source-map": "^0.5.0" + } }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "@babel/helper-annotate-as-pure": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.8.3.tgz", + "integrity": "sha512-6o+mJrZBxOoEX77Ezv9zwW7WV8DdluouRKNY/IR5u/YTMuKHgugHOzYWlYvYLpLA9nPsQCAAASpCIbjI9Mv+Uw==", "dev": true, "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "@babel/types": "^7.8.3" } }, - "brorand": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", - "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", - "dev": true + "@babel/helper-builder-binary-assignment-operator-visitor": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.8.3.tgz", + "integrity": "sha512-5eFOm2SyFPK4Rh3XMMRDjN7lBH0orh3ss0g3rTYZnBQ+r6YPj7lgDyCvPphynHvUrobJmeMignBr6Acw9mAPlw==", + "dev": true, + "requires": { + "@babel/helper-explode-assignable-expression": "^7.8.3", + "@babel/types": "^7.8.3" + } }, - "browser-pack": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/browser-pack/-/browser-pack-6.1.0.tgz", - "integrity": "sha512-erYug8XoqzU3IfcU8fUgyHqyOXqIE4tUTTQ+7mqUjQlvnXkOO6OlT9c/ZoJVHYoAaqGxr09CN53G7XIsO4KtWA==", + "@babel/helper-builder-react-jsx": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-react-jsx/-/helper-builder-react-jsx-7.8.3.tgz", + "integrity": "sha512-JT8mfnpTkKNCboTqZsQTdGo3l3Ik3l7QIt9hh0O9DYiwVel37VoJpILKM4YFbP2euF32nkQSb+F9cUk9b7DDXQ==", "dev": true, "requires": { - "JSONStream": "^1.0.3", - "combine-source-map": "~0.8.0", - "defined": "^1.0.0", - "safe-buffer": "^5.1.1", - "through2": "^2.0.0", - "umd": "^3.0.0" + "@babel/types": "^7.8.3", + "esutils": "^2.0.0" } }, - "browser-resolve": { - "version": "1.11.3", - "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-1.11.3.tgz", - "integrity": "sha512-exDi1BYWB/6raKHmDTCicQfTkqwN5fioMFV4j8BsfMU4R2DK/QfZfK7kOVkmWCNANf0snkBzqGqAJBao9gZMdQ==", + "@babel/helper-call-delegate": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-call-delegate/-/helper-call-delegate-7.8.3.tgz", + "integrity": "sha512-6Q05px0Eb+N4/GTyKPPvnkig7Lylw+QzihMpws9iiZQv7ZImf84ZsZpQH7QoWN4n4tm81SnSzPgHw2qtO0Zf3A==", "dev": true, "requires": { - "resolve": "1.1.7" - }, - "dependencies": { - "resolve": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", - "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", - "dev": true - } + "@babel/helper-hoist-variables": "^7.8.3", + "@babel/traverse": "^7.8.3", + "@babel/types": "^7.8.3" } }, - "browserify": { - "version": "16.3.0", - "resolved": "https://registry.npmjs.org/browserify/-/browserify-16.3.0.tgz", - "integrity": "sha512-BWaaD7alyGZVEBBwSTYx4iJF5DswIGzK17o8ai9w4iKRbYpk3EOiprRHMRRA8DCZFmFeOdx7A385w2XdFvxWmg==", + "@babel/helper-compilation-targets": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.8.3.tgz", + "integrity": "sha512-JLylPCsFjhLN+6uBSSh3iYdxKdeO9MNmoY96PE/99d8kyBFaXLORtAVhqN6iHa+wtPeqxKLghDOZry0+Aiw9Tw==", "dev": true, "requires": { - "JSONStream": "^1.0.3", - "assert": "^1.4.0", - "browser-pack": "^6.0.1", - "browser-resolve": "^1.11.0", - "browserify-zlib": "~0.2.0", - "buffer": "^5.0.2", - "cached-path-relative": "^1.0.0", - "concat-stream": "^1.6.0", - "console-browserify": "^1.1.0", - "constants-browserify": "~1.0.0", - "crypto-browserify": "^3.0.0", - "defined": "^1.0.0", - "deps-sort": "^2.0.0", - "domain-browser": "^1.2.0", - "duplexer2": "~0.1.2", - "events": "^2.0.0", - "glob": "^7.1.0", - "has": "^1.0.0", - "htmlescape": "^1.1.0", - "https-browserify": "^1.0.0", - "inherits": "~2.0.1", - "insert-module-globals": "^7.0.0", - "labeled-stream-splicer": "^2.0.0", - "mkdirp": "^0.5.0", - "module-deps": "^6.0.0", - "os-browserify": "~0.3.0", - "parents": "^1.0.1", - "path-browserify": "~0.0.0", - "process": "~0.11.0", - "punycode": "^1.3.2", - "querystring-es3": "~0.2.0", - "read-only-stream": "^2.0.0", - "readable-stream": "^2.0.2", - "resolve": "^1.1.4", - "shasum": "^1.0.0", - "shell-quote": "^1.6.1", - "stream-browserify": "^2.0.0", - "stream-http": "^2.0.0", - "string_decoder": "^1.1.1", - "subarg": "^1.0.0", - "syntax-error": "^1.1.1", - "through2": "^2.0.0", - "timers-browserify": "^1.0.1", - "tty-browserify": "0.0.1", - "url": "~0.11.0", - "util": "~0.10.1", - "vm-browserify": "^1.0.0", - "xtend": "^4.0.0" + "@babel/compat-data": "^7.8.1", + "browserslist": "^4.8.2", + "invariant": "^2.2.4", + "levenary": "^1.1.0", + "semver": "^5.5.0" } }, - "browserify-aes": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", - "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", + "@babel/helper-create-regexp-features-plugin": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.8.3.tgz", + "integrity": "sha512-Gcsm1OHCUr9o9TcJln57xhWHtdXbA2pgQ58S0Lxlks0WMGNXuki4+GLfX0p+L2ZkINUGZvfkz8rzoqJQSthI+Q==", "dev": true, "requires": { - "buffer-xor": "^1.0.3", - "cipher-base": "^1.0.0", - "create-hash": "^1.1.0", - "evp_bytestokey": "^1.0.3", - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" + "@babel/helper-regex": "^7.8.3", + "regexpu-core": "^4.6.0" } }, - "browserify-cipher": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", - "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", + "@babel/helper-define-map": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.8.3.tgz", + "integrity": "sha512-PoeBYtxoZGtct3md6xZOCWPcKuMuk3IHhgxsRRNtnNShebf4C8YonTSblsK4tvDbm+eJAw2HAPOfCr+Q/YRG/g==", "dev": true, "requires": { - "browserify-aes": "^1.0.4", - "browserify-des": "^1.0.0", - "evp_bytestokey": "^1.0.0" + "@babel/helper-function-name": "^7.8.3", + "@babel/types": "^7.8.3", + "lodash": "^4.17.13" } }, - "browserify-des": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", - "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", + "@babel/helper-explode-assignable-expression": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.8.3.tgz", + "integrity": "sha512-N+8eW86/Kj147bO9G2uclsg5pwfs/fqqY5rwgIL7eTBklgXjcOJ3btzS5iM6AitJcftnY7pm2lGsrJVYLGjzIw==", "dev": true, "requires": { - "cipher-base": "^1.0.1", - "des.js": "^1.0.0", - "inherits": "^2.0.1", - "safe-buffer": "^5.1.2" + "@babel/traverse": "^7.8.3", + "@babel/types": "^7.8.3" } }, - "browserify-rsa": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", - "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", + "@babel/helper-function-name": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.8.3.tgz", + "integrity": "sha512-BCxgX1BC2hD/oBlIFUgOCQDOPV8nSINxCwM3o93xP4P9Fq6aV5sgv2cOOITDMtCfQ+3PvHp3l689XZvAM9QyOA==", "dev": true, "requires": { - "bn.js": "^4.1.0", - "randombytes": "^2.0.1" + "@babel/helper-get-function-arity": "^7.8.3", + "@babel/template": "^7.8.3", + "@babel/types": "^7.8.3" } }, - "browserify-sign": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz", - "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=", + "@babel/helper-get-function-arity": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.8.3.tgz", + "integrity": "sha512-FVDR+Gd9iLjUMY1fzE2SR0IuaJToR4RkCDARVfsBBPSP53GEqSFjD8gNyxg246VUyc/ALRxFaAK8rVG7UT7xRA==", "dev": true, "requires": { - "bn.js": "^4.1.1", - "browserify-rsa": "^4.0.0", - "create-hash": "^1.1.0", - "create-hmac": "^1.1.2", - "elliptic": "^6.0.0", - "inherits": "^2.0.1", - "parse-asn1": "^5.0.0" + "@babel/types": "^7.8.3" } }, - "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==", + "@babel/helper-hoist-variables": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.8.3.tgz", + "integrity": "sha512-ky1JLOjcDUtSc+xkt0xhYff7Z6ILTAHKmZLHPxAhOP0Nd77O+3nCsd6uSVYur6nJnCI029CrNbYlc0LoPfAPQg==", "dev": true, "requires": { - "pako": "~1.0.5" + "@babel/types": "^7.8.3" } }, - "buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.2.1.tgz", - "integrity": "sha512-c+Ko0loDaFfuPWiL02ls9Xd3GO3cPVmUobQ6t3rXNUk304u6hGq+8N/kFi+QEIKhzK3uwolVhLzszmfLmMLnqg==", + "@babel/helper-member-expression-to-functions": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.8.3.tgz", + "integrity": "sha512-fO4Egq88utkQFjbPrSHGmGLFqmrshs11d46WI+WZDESt7Wu7wN2G2Iu+NMMZJFDOVRHAMIkB5SNh30NtwCA7RA==", "dev": true, "requires": { - "base64-js": "^1.0.2", - "ieee754": "^1.1.4" + "@babel/types": "^7.8.3" } }, - "buffer-from": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", - "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", - "dev": true + "@babel/helper-module-imports": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.8.3.tgz", + "integrity": "sha512-R0Bx3jippsbAEtzkpZ/6FIiuzOURPcMjHp+Z6xPe6DtApDJx+w7UYyOLanZqO8+wKR9G10s/FmHXvxaMd9s6Kg==", + "dev": true, + "requires": { + "@babel/types": "^7.8.3" + } }, - "buffer-xor": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", - "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", - "dev": true + "@babel/helper-module-transforms": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.8.3.tgz", + "integrity": "sha512-C7NG6B7vfBa/pwCOshpMbOYUmrYQDfCpVL/JCRu0ek8B5p8kue1+BCXpg2vOYs7w5ACB9GTOBYQ5U6NwrMg+3Q==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.8.3", + "@babel/helper-simple-access": "^7.8.3", + "@babel/helper-split-export-declaration": "^7.8.3", + "@babel/template": "^7.8.3", + "@babel/types": "^7.8.3", + "lodash": "^4.17.13" + } }, - "builtin-status-codes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", - "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=", - "dev": true + "@babel/helper-optimise-call-expression": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.8.3.tgz", + "integrity": "sha512-Kag20n86cbO2AvHca6EJsvqAd82gc6VMGule4HwebwMlwkpXuVqrNRj6CkCV2sKxgi9MyAUnZVnZ6lJ1/vKhHQ==", + "dev": true, + "requires": { + "@babel/types": "^7.8.3" + } }, - "cached-path-relative": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/cached-path-relative/-/cached-path-relative-1.0.2.tgz", - "integrity": "sha512-5r2GqsoEb4qMTTN9J+WzXfjov+hjxT+j3u5K+kIVNIwAd99DLCJE9pBIMP1qVeybV6JiijL385Oz0DcYxfbOIg==", + "@babel/helper-plugin-utils": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz", + "integrity": "sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ==", "dev": true }, - "charset": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/charset/-/charset-1.0.1.tgz", - "integrity": "sha512-6dVyOOYjpfFcL1Y4qChrAoQLRHvj2ziyhcm0QJlhOcAhykL/k1kTUPbeo+87MNRTRdk2OIIsIXbuF3x2wi5EXg==", - "dev": true + "@babel/helper-regex": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-regex/-/helper-regex-7.8.3.tgz", + "integrity": "sha512-BWt0QtYv/cg/NecOAZMdcn/waj/5P26DR4mVLXfFtDokSR6fyuG0Pj+e2FqtSME+MqED1khnSMulkmGl8qWiUQ==", + "dev": true, + "requires": { + "lodash": "^4.17.13" + } }, - "cipher-base": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", - "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "@babel/helper-remap-async-to-generator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.8.3.tgz", + "integrity": "sha512-kgwDmw4fCg7AVgS4DukQR/roGp+jP+XluJE5hsRZwxCYGg+Rv9wSGErDWhlI90FODdYfd4xG4AQRiMDjjN0GzA==", "dev": true, "requires": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" + "@babel/helper-annotate-as-pure": "^7.8.3", + "@babel/helper-wrap-function": "^7.8.3", + "@babel/template": "^7.8.3", + "@babel/traverse": "^7.8.3", + "@babel/types": "^7.8.3" } }, - "combine-source-map": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/combine-source-map/-/combine-source-map-0.8.0.tgz", - "integrity": "sha1-pY0N8ELBhvz4IqjoAV9UUNLXmos=", + "@babel/helper-replace-supers": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.8.3.tgz", + "integrity": "sha512-xOUssL6ho41U81etpLoT2RTdvdus4VfHamCuAm4AHxGr+0it5fnwoVdwUJ7GFEqCsQYzJUhcbsN9wB9apcYKFA==", "dev": true, "requires": { - "convert-source-map": "~1.1.0", - "inline-source-map": "~0.6.0", - "lodash.memoize": "~3.0.3", - "source-map": "~0.5.3" + "@babel/helper-member-expression-to-functions": "^7.8.3", + "@babel/helper-optimise-call-expression": "^7.8.3", + "@babel/traverse": "^7.8.3", + "@babel/types": "^7.8.3" } }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true + "@babel/helper-simple-access": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.8.3.tgz", + "integrity": "sha512-VNGUDjx5cCWg4vvCTR8qQ7YJYZ+HBjxOgXEl7ounz+4Sn7+LMD3CFrCTEU6/qXKbA2nKg21CwhhBzO0RpRbdCw==", + "dev": true, + "requires": { + "@babel/template": "^7.8.3", + "@babel/types": "^7.8.3" + } }, - "concat-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", - "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "@babel/helper-split-export-declaration": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.8.3.tgz", + "integrity": "sha512-3x3yOeyBhW851hroze7ElzdkeRXQYQbFIb7gLK1WQYsw2GWDay5gAJNw1sWJ0VFP6z5J1whqeXH/WCdCjZv6dA==", "dev": true, "requires": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" + "@babel/types": "^7.8.3" } }, - "console-browserify": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", - "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=", + "@babel/helper-wrap-function": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.8.3.tgz", + "integrity": "sha512-LACJrbUET9cQDzb6kG7EeD7+7doC3JNvUgTEQOx2qaO1fKlzE/Bf05qs9w1oXQMmXlPO65lC3Tq9S6gZpTErEQ==", "dev": true, "requires": { - "date-now": "^0.1.4" + "@babel/helper-function-name": "^7.8.3", + "@babel/template": "^7.8.3", + "@babel/traverse": "^7.8.3", + "@babel/types": "^7.8.3" } }, - "constants-browserify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", - "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=", - "dev": true + "@babel/helpers": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.8.3.tgz", + "integrity": "sha512-LmU3q9Pah/XyZU89QvBgGt+BCsTPoQa+73RxAQh8fb8qkDyIfeQnmgs+hvzhTCKTzqOyk7JTkS3MS1S8Mq5yrQ==", + "dev": true, + "requires": { + "@babel/template": "^7.8.3", + "@babel/traverse": "^7.8.3", + "@babel/types": "^7.8.3" + } }, - "convert-source-map": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.1.3.tgz", - "integrity": "sha1-SCnId+n+SbMWHzvzZziI4gRpmGA=", - "dev": true + "@babel/highlight": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.8.3.tgz", + "integrity": "sha512-PX4y5xQUvy0fnEVHrYOarRPXVWafSjTW9T0Hab8gVIawpl2Sj0ORyrygANq+KjcNlSSTw0YCLSNA8OyZ1I4yEg==", + "dev": true, + "requires": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + } }, - "core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "@babel/parser": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.8.3.tgz", + "integrity": "sha512-/V72F4Yp/qmHaTALizEm9Gf2eQHV3QyTL3K0cNfijwnMnb1L+LDlAubb/ZnSdGAVzVSWakujHYs1I26x66sMeQ==", "dev": true }, - "create-ecdh": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz", - "integrity": "sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw==", + "@babel/plugin-proposal-async-generator-functions": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.8.3.tgz", + "integrity": "sha512-NZ9zLv848JsV3hs8ryEh7Uaz/0KsmPLqv0+PdkDJL1cJy0K4kOCFa8zc1E3mp+RHPQcpdfb/6GovEsW4VDrOMw==", "dev": true, "requires": { - "bn.js": "^4.1.0", - "elliptic": "^6.0.0" + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/helper-remap-async-to-generator": "^7.8.3", + "@babel/plugin-syntax-async-generators": "^7.8.0" } }, - "create-hash": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", - "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "@babel/plugin-proposal-dynamic-import": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.8.3.tgz", + "integrity": "sha512-NyaBbyLFXFLT9FP+zk0kYlUlA8XtCUbehs67F0nnEg7KICgMc2mNkIeu9TYhKzyXMkrapZFwAhXLdnt4IYHy1w==", "dev": true, "requires": { - "cipher-base": "^1.0.1", - "inherits": "^2.0.1", - "md5.js": "^1.3.4", - "ripemd160": "^2.0.1", - "sha.js": "^2.4.0" + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/plugin-syntax-dynamic-import": "^7.8.0" } }, - "create-hmac": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", - "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "@babel/plugin-proposal-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.8.3.tgz", + "integrity": "sha512-KGhQNZ3TVCQG/MjRbAUwuH+14y9q0tpxs1nWWs3pbSleRdDro9SAMMDyye8HhY1gqZ7/NqIc8SKhya0wRDgP1Q==", "dev": true, "requires": { - "cipher-base": "^1.0.3", - "create-hash": "^1.1.0", - "inherits": "^2.0.1", - "ripemd160": "^2.0.0", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/plugin-syntax-json-strings": "^7.8.0" } }, - "crypto-browserify": { - "version": "3.12.0", - "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", - "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", + "@babel/plugin-proposal-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-TS9MlfzXpXKt6YYomudb/KU7nQI6/xnapG6in1uZxoxDghuSMZsPb6D2fyUwNYSAp4l1iR7QtFOjkqcRYcUsfw==", "dev": true, "requires": { - "browserify-cipher": "^1.0.0", - "browserify-sign": "^4.0.0", - "create-ecdh": "^4.0.0", - "create-hash": "^1.1.0", - "create-hmac": "^1.1.0", - "diffie-hellman": "^5.0.0", - "inherits": "^2.0.1", - "pbkdf2": "^3.0.3", - "public-encrypt": "^4.0.0", - "randombytes": "^2.0.0", - "randomfill": "^1.0.3" + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.0" } }, - "dash-ast": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/dash-ast/-/dash-ast-1.0.0.tgz", - "integrity": "sha512-Vy4dx7gquTeMcQR/hDkYLGUnwVil6vk4FOOct+djUnHOUWt+zJPJAaRIXaAFkPXtJjvlY7o3rfRu0/3hpnwoUA==", - "dev": true + "@babel/plugin-proposal-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-8qvuPwU/xxUCt78HocNlv0mXXo0wdh9VT1R04WU8HGOfaOob26pF+9P5/lYjN/q7DHOX1bvX60hnhOvuQUJdbA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/plugin-syntax-object-rest-spread": "^7.8.0" + } }, - "date-now": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", - "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=", - "dev": true + "@babel/plugin-proposal-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-0gkX7J7E+AtAw9fcwlVQj8peP61qhdg/89D5swOkjYbkboA2CVckn3kiyum1DE0wskGb7KJJxBdyEBApDLLVdw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.0" + } }, - "defined": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", - "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=", - "dev": true + "@babel/plugin-proposal-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.8.3.tgz", + "integrity": "sha512-QIoIR9abkVn+seDE3OjA08jWcs3eZ9+wJCKSRgo3WdEU2csFYgdScb+8qHB3+WXsGJD55u+5hWCISI7ejXS+kg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.0" + } }, - "deps-sort": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/deps-sort/-/deps-sort-2.0.0.tgz", - "integrity": "sha1-CRckkC6EZYJg65EHSMzNGvbiH7U=", + "@babel/plugin-proposal-unicode-property-regex": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.8.3.tgz", + "integrity": "sha512-1/1/rEZv2XGweRwwSkLpY+s60za9OZ1hJs4YDqFHCw0kYWYwL5IFljVY1MYBL+weT1l9pokDO2uhSTLVxzoHkQ==", "dev": true, "requires": { - "JSONStream": "^1.0.3", - "shasum": "^1.0.0", - "subarg": "^1.0.0", - "through2": "^2.0.0" + "@babel/helper-create-regexp-features-plugin": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3" } }, - "des.js": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz", - "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=", + "@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", "dev": true, "requires": { - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0" + "@babel/helper-plugin-utils": "^7.8.0" } }, - "detective": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/detective/-/detective-5.2.0.tgz", - "integrity": "sha512-6SsIx+nUUbuK0EthKjv0zrdnajCCXVYGmbYYiYjFVpzcjwEs/JMDZ8tPRG29J/HhN56t3GJp2cGSWDRjjot8Pg==", + "@babel/plugin-syntax-dynamic-import": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", + "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", "dev": true, "requires": { - "acorn-node": "^1.6.1", - "defined": "^1.0.0", - "minimist": "^1.1.1" + "@babel/helper-plugin-utils": "^7.8.0" } }, - "diffie-hellman": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", - "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", + "@babel/plugin-syntax-flow": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.8.3.tgz", + "integrity": "sha512-innAx3bUbA0KSYj2E2MNFSn9hiCeowOFLxlsuhXzw8hMQnzkDomUr9QCD7E9VF60NmnG1sNTuuv6Qf4f8INYsg==", "dev": true, "requires": { - "bn.js": "^4.1.0", - "miller-rabin": "^4.0.0", - "randombytes": "^2.0.0" + "@babel/helper-plugin-utils": "^7.8.3" } }, - "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==", - "dev": true + "@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } }, - "duplexer2": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", - "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", + "@babel/plugin-syntax-jsx": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.8.3.tgz", + "integrity": "sha512-WxdW9xyLgBdefoo0Ynn3MRSkhe5tFVxxKNVdnZSh318WrG2e2jH+E9wd/++JsqcLJZPfz87njQJ8j2Upjm0M0A==", "dev": true, "requires": { - "readable-stream": "^2.0.2" + "@babel/helper-plugin-utils": "^7.8.3" } }, - "ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", - "dev": true + "@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } }, - "elliptic": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.0.tgz", - "integrity": "sha512-eFOJTMyCYb7xtE/caJ6JJu+bhi67WCYNbkGSknu20pmM8Ke/bqOfdnZWxyoGN26JgfxTbXrsCkEw4KheCT/KGg==", + "@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", "dev": true, "requires": { - "bn.js": "^4.4.0", - "brorand": "^1.0.1", - "hash.js": "^1.0.0", - "hmac-drbg": "^1.0.0", - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0", - "minimalistic-crypto-utils": "^1.0.0" + "@babel/helper-plugin-utils": "^7.8.0" } }, - "events": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/events/-/events-2.1.0.tgz", - "integrity": "sha512-3Zmiobend8P9DjmKAty0Era4jV8oJ0yGYe2nJJAxgymF9+N8F2m0hhZiMoWtcfepExzNKZumFU3ksdQbInGWCg==", - "dev": true + "@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } }, - "evp_bytestokey": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", - "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", "dev": true, "requires": { - "md5.js": "^1.3.4", - "safe-buffer": "^5.1.1" + "@babel/helper-plugin-utils": "^7.8.0" } }, - "extatic": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/extatic/-/extatic-4.1.3.tgz", - "integrity": "sha512-ZOzJowsUKufkUKDoRe8WTltm+/mUJRLQzWEgr0FgC0+lMv9yrtXU4OnYQSN++AEKK5LXPe2oyird+xrkDvoogA==", + "@babel/plugin-syntax-top-level-await": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.8.3.tgz", + "integrity": "sha512-kwj1j9lL/6Wd0hROD3b/OZZ7MSrZLqqn9RAZ5+cYYsflQ9HZBIKCUkr3+uL1MEJ1NePiUbf98jjiMQSv0NMR9g==", "dev": true, "requires": { - "charset": "^1.0.1", - "he": "^1.1.1", - "mime": "^2.4.1", - "minimist": "^1.1.0", - "on-finished": "^2.3.0", - "url-join": "^4.0.0" + "@babel/helper-plugin-utils": "^7.8.3" } }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true + "@babel/plugin-transform-arrow-functions": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.8.3.tgz", + "integrity": "sha512-0MRF+KC8EqH4dbuITCWwPSzsyO3HIWWlm30v8BbbpOrS1B++isGxPnnuq/IZvOX5J2D/p7DQalQm+/2PnlKGxg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true + "@babel/plugin-transform-async-to-generator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.8.3.tgz", + "integrity": "sha512-imt9tFLD9ogt56Dd5CI/6XgpukMwd/fLGSrix2httihVe7LOGVPhyhMh1BU5kDM7iHD08i8uUtmV2sWaBFlHVQ==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/helper-remap-async-to-generator": "^7.8.3" + } }, - "get-assigned-identifiers": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/get-assigned-identifiers/-/get-assigned-identifiers-1.2.0.tgz", - "integrity": "sha512-mBBwmeGTrxEMO4pMaaf/uUEFHnYtwr8FTe8Y/mer4rcV/bye0qGm6pw1bGZFGStxC5O76c5ZAVBGnqHmOaJpdQ==", - "dev": true + "@babel/plugin-transform-block-scoped-functions": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.8.3.tgz", + "integrity": "sha512-vo4F2OewqjbB1+yaJ7k2EJFHlTP3jR634Z9Cj9itpqNjuLXvhlVxgnjsHsdRgASR8xYDrx6onw4vW5H6We0Jmg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } }, - "glob": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", - "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", + "@babel/plugin-transform-block-scoping": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.8.3.tgz", + "integrity": "sha512-pGnYfm7RNRgYRi7bids5bHluENHqJhrV4bCZRwc5GamaWIIs07N4rZECcmJL6ZClwjDz1GbdMZFtPs27hTB06w==", "dev": true, "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "@babel/helper-plugin-utils": "^7.8.3", + "lodash": "^4.17.13" } }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "@babel/plugin-transform-classes": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.8.3.tgz", + "integrity": "sha512-SjT0cwFJ+7Rbr1vQsvphAHwUHvSUPmMjMU/0P59G8U2HLFqSa082JO7zkbDNWs9kH/IUqpHI6xWNesGf8haF1w==", "dev": true, "requires": { - "function-bind": "^1.1.1" + "@babel/helper-annotate-as-pure": "^7.8.3", + "@babel/helper-define-map": "^7.8.3", + "@babel/helper-function-name": "^7.8.3", + "@babel/helper-optimise-call-expression": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/helper-replace-supers": "^7.8.3", + "@babel/helper-split-export-declaration": "^7.8.3", + "globals": "^11.1.0" } }, - "hash-base": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", - "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", + "@babel/plugin-transform-computed-properties": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.8.3.tgz", + "integrity": "sha512-O5hiIpSyOGdrQZRQ2ccwtTVkgUDBBiCuK//4RJ6UfePllUTCENOzKxfh6ulckXKc0DixTFLCfb2HVkNA7aDpzA==", "dev": true, "requires": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" + "@babel/helper-plugin-utils": "^7.8.3" } }, - "hash.js": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", - "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "@babel/plugin-transform-destructuring": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.8.3.tgz", + "integrity": "sha512-H4X646nCkiEcHZUZaRkhE2XVsoz0J/1x3VVujnn96pSoGCtKPA99ZZA+va+gK+92Zycd6OBKCD8tDb/731bhgQ==", "dev": true, "requires": { - "inherits": "^2.0.3", - "minimalistic-assert": "^1.0.1" + "@babel/helper-plugin-utils": "^7.8.3" } }, - "he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "dev": true + "@babel/plugin-transform-dotall-regex": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.8.3.tgz", + "integrity": "sha512-kLs1j9Nn4MQoBYdRXH6AeaXMbEJFaFu/v1nQkvib6QzTj8MZI5OQzqmD83/2jEM1z0DLilra5aWO5YpyC0ALIw==", + "dev": true, + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3" + } }, - "hmac-drbg": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", - "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", + "@babel/plugin-transform-duplicate-keys": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.8.3.tgz", + "integrity": "sha512-s8dHiBUbcbSgipS4SMFuWGqCvyge5V2ZeAWzR6INTVC3Ltjig/Vw1G2Gztv0vU/hRG9X8IvKvYdoksnUfgXOEQ==", "dev": true, "requires": { - "hash.js": "^1.0.3", - "minimalistic-assert": "^1.0.0", - "minimalistic-crypto-utils": "^1.0.1" + "@babel/helper-plugin-utils": "^7.8.3" } }, - "htmlescape": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/htmlescape/-/htmlescape-1.1.1.tgz", - "integrity": "sha1-OgPtwiFLyjtmQko+eVk0lQnLA1E=", - "dev": true + "@babel/plugin-transform-exponentiation-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.8.3.tgz", + "integrity": "sha512-zwIpuIymb3ACcInbksHaNcR12S++0MDLKkiqXHl3AzpgdKlFNhog+z/K0+TGW+b0w5pgTq4H6IwV/WhxbGYSjQ==", + "dev": true, + "requires": { + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3" + } }, - "https-browserify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", - "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=", - "dev": true + "@babel/plugin-transform-flow-strip-types": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.8.3.tgz", + "integrity": "sha512-g/6WTWG/xbdd2exBBzMfygjX/zw4eyNC4X8pRaq7aRHRoDUCzAIu3kGYIXviOv8BjCuWm8vDBwjHcjiRNgXrPA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/plugin-syntax-flow": "^7.8.3" + } }, - "ieee754": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", - "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==", - "dev": true + "@babel/plugin-transform-for-of": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.8.3.tgz", + "integrity": "sha512-ZjXznLNTxhpf4Q5q3x1NsngzGA38t9naWH8Gt+0qYZEJAcvPI9waSStSh56u19Ofjr7QmD0wUsQ8hw8s/p1VnA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "@babel/plugin-transform-function-name": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.8.3.tgz", + "integrity": "sha512-rO/OnDS78Eifbjn5Py9v8y0aR+aSYhDhqAwVfsTl0ERuMZyr05L1aFSCJnbv2mmsLkit/4ReeQ9N2BgLnOcPCQ==", "dev": true, "requires": { - "once": "^1.3.0", - "wrappy": "1" + "@babel/helper-function-name": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3" } }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true + "@babel/plugin-transform-literals": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.8.3.tgz", + "integrity": "sha512-3Tqf8JJ/qB7TeldGl+TT55+uQei9JfYaregDcEAyBZ7akutriFrt6C/wLYIer6OYhleVQvH/ntEhjE/xMmy10A==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } }, - "inline-source-map": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/inline-source-map/-/inline-source-map-0.6.2.tgz", - "integrity": "sha1-+Tk0ccGKedFyT4Y/o4tYY3Ct4qU=", + "@babel/plugin-transform-member-expression-literals": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.8.3.tgz", + "integrity": "sha512-3Wk2EXhnw+rP+IDkK6BdtPKsUE5IeZ6QOGrPYvw52NwBStw9V1ZVzxgK6fSKSxqUvH9eQPR3tm3cOq79HlsKYA==", "dev": true, "requires": { - "source-map": "~0.5.3" + "@babel/helper-plugin-utils": "^7.8.3" } }, - "insert-module-globals": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/insert-module-globals/-/insert-module-globals-7.2.0.tgz", - "integrity": "sha512-VE6NlW+WGn2/AeOMd496AHFYmE7eLKkUY6Ty31k4og5vmA3Fjuwe9v6ifH6Xx/Hz27QvdoMoviw1/pqWRB09Sw==", + "@babel/plugin-transform-modules-amd": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.8.3.tgz", + "integrity": "sha512-MadJiU3rLKclzT5kBH4yxdry96odTUwuqrZM+GllFI/VhxfPz+k9MshJM+MwhfkCdxxclSbSBbUGciBngR+kEQ==", "dev": true, "requires": { - "JSONStream": "^1.0.3", - "acorn-node": "^1.5.2", - "combine-source-map": "^0.8.0", - "concat-stream": "^1.6.1", - "is-buffer": "^1.1.0", - "path-is-absolute": "^1.0.1", - "process": "~0.11.0", - "through2": "^2.0.0", - "undeclared-identifiers": "^1.1.2", - "xtend": "^4.0.0" + "@babel/helper-module-transforms": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3", + "babel-plugin-dynamic-import-node": "^2.3.0" } }, - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true + "@babel/plugin-transform-modules-commonjs": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.8.3.tgz", + "integrity": "sha512-JpdMEfA15HZ/1gNuB9XEDlZM1h/gF/YOH7zaZzQu2xCFRfwc01NXBMHHSTT6hRjlXJJs5x/bfODM3LiCk94Sxg==", + "dev": true, + "requires": { + "@babel/helper-module-transforms": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/helper-simple-access": "^7.8.3", + "babel-plugin-dynamic-import-node": "^2.3.0" + } }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true + "@babel/plugin-transform-modules-systemjs": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.8.3.tgz", + "integrity": "sha512-8cESMCJjmArMYqa9AO5YuMEkE4ds28tMpZcGZB/jl3n0ZzlsxOAi3mC+SKypTfT8gjMupCnd3YiXCkMjj2jfOg==", + "dev": true, + "requires": { + "@babel/helper-hoist-variables": "^7.8.3", + "@babel/helper-module-transforms": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3", + "babel-plugin-dynamic-import-node": "^2.3.0" + } }, - "json-stable-stringify": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-0.0.1.tgz", - "integrity": "sha1-YRwj6BTbN1Un34URk9tZ3Sryf0U=", + "@babel/plugin-transform-modules-umd": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.8.3.tgz", + "integrity": "sha512-evhTyWhbwbI3/U6dZAnx/ePoV7H6OUG+OjiJFHmhr9FPn0VShjwC2kdxqIuQ/+1P50TMrneGzMeyMTFOjKSnAw==", "dev": true, "requires": { - "jsonify": "~0.0.0" + "@babel/helper-module-transforms": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3" } }, - "jsonify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", - "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", - "dev": true + "@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.8.3.tgz", + "integrity": "sha512-f+tF/8UVPU86TrCb06JoPWIdDpTNSGGcAtaD9mLP0aYGA0OS0j7j7DHJR0GTFrUZPUU6loZhbsVZgTh0N+Qdnw==", + "dev": true, + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.8.3" + } }, - "jsonparse": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", - "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", - "dev": true + "@babel/plugin-transform-new-target": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.8.3.tgz", + "integrity": "sha512-QuSGysibQpyxexRyui2vca+Cmbljo8bcRckgzYV4kRIsHpVeyeC3JDO63pY+xFZ6bWOBn7pfKZTqV4o/ix9sFw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } }, - "labeled-stream-splicer": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/labeled-stream-splicer/-/labeled-stream-splicer-2.0.2.tgz", - "integrity": "sha512-Ca4LSXFFZUjPScRaqOcFxneA0VpKZr4MMYCljyQr4LIewTLb3Y0IUTIsnBBsVubIeEfxeSZpSjSsRM8APEQaAw==", + "@babel/plugin-transform-object-super": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.8.3.tgz", + "integrity": "sha512-57FXk+gItG/GejofIyLIgBKTas4+pEU47IXKDBWFTxdPd7F80H8zybyAY7UoblVfBhBGs2EKM+bJUu2+iUYPDQ==", "dev": true, "requires": { - "inherits": "^2.0.1", - "stream-splicer": "^2.0.0" + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/helper-replace-supers": "^7.8.3" } }, - "lodash.memoize": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-3.0.4.tgz", - "integrity": "sha1-LcvSwofLwKVcxCMovQxzYVDVPj8=", - "dev": true + "@babel/plugin-transform-parameters": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.8.3.tgz", + "integrity": "sha512-/pqngtGb54JwMBZ6S/D3XYylQDFtGjWrnoCF4gXZOUpFV/ujbxnoNGNvDGu6doFWRPBveE72qTx/RRU44j5I/Q==", + "dev": true, + "requires": { + "@babel/helper-call-delegate": "^7.8.3", + "@babel/helper-get-function-arity": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3" + } }, - "md5.js": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", - "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "@babel/plugin-transform-property-literals": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.8.3.tgz", + "integrity": "sha512-uGiiXAZMqEoQhRWMK17VospMZh5sXWg+dlh2soffpkAl96KAm+WZuJfa6lcELotSRmooLqg0MWdH6UUq85nmmg==", "dev": true, "requires": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1", - "safe-buffer": "^5.1.2" + "@babel/helper-plugin-utils": "^7.8.3" } }, - "miller-rabin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", - "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "@babel/plugin-transform-react-jsx": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.8.3.tgz", + "integrity": "sha512-r0h+mUiyL595ikykci+fbwm9YzmuOrUBi0b+FDIKmi3fPQyFokWVEMJnRWHJPPQEjyFJyna9WZC6Viv6UHSv1g==", "dev": true, "requires": { - "bn.js": "^4.0.0", - "brorand": "^1.0.1" + "@babel/helper-builder-react-jsx": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/plugin-syntax-jsx": "^7.8.3" } }, - "mime": { - "version": "2.4.4", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.4.tgz", - "integrity": "sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA==", - "dev": true + "@babel/plugin-transform-regenerator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.8.3.tgz", + "integrity": "sha512-qt/kcur/FxrQrzFR432FGZznkVAjiyFtCOANjkAKwCbt465L6ZCiUQh2oMYGU3Wo8LRFJxNDFwWn106S5wVUNA==", + "dev": true, + "requires": { + "regenerator-transform": "^0.14.0" + } }, - "minimalistic-assert": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", - "dev": true + "@babel/plugin-transform-reserved-words": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.8.3.tgz", + "integrity": "sha512-mwMxcycN3omKFDjDQUl+8zyMsBfjRFr0Zn/64I41pmjv4NJuqcYlEtezwYtw9TFd9WR1vN5kiM+O0gMZzO6L0A==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } }, - "minimalistic-crypto-utils": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", - "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=", - "dev": true + "@babel/plugin-transform-shorthand-properties": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.8.3.tgz", + "integrity": "sha512-I9DI6Odg0JJwxCHzbzW08ggMdCezoWcuQRz3ptdudgwaHxTjxw5HgdFJmZIkIMlRymL6YiZcped4TTCB0JcC8w==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "@babel/plugin-transform-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.8.3.tgz", + "integrity": "sha512-CkuTU9mbmAoFOI1tklFWYYbzX5qCIZVXPVy0jpXgGwkplCndQAa58s2jr66fTeQnA64bDox0HL4U56CFYoyC7g==", "dev": true, "requires": { - "brace-expansion": "^1.1.7" + "@babel/helper-plugin-utils": "^7.8.3" } }, - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - }, - "mkdirp": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "@babel/plugin-transform-sticky-regex": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.8.3.tgz", + "integrity": "sha512-9Spq0vGCD5Bb4Z/ZXXSK5wbbLFMG085qd2vhL1JYu1WcQ5bXqZBAYRzU1d+p79GcHs2szYv5pVQCX13QgldaWw==", "dev": true, "requires": { - "minimist": "0.0.8" - }, - "dependencies": { - "minimist": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", - "dev": true - } + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/helper-regex": "^7.8.3" } }, - "module-deps": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/module-deps/-/module-deps-6.2.1.tgz", - "integrity": "sha512-UnEn6Ah36Tu4jFiBbJVUtt0h+iXqxpLqDvPS8nllbw5RZFmNJ1+Mz5BjYnM9ieH80zyxHkARGLnMIHlPK5bu6A==", + "@babel/plugin-transform-template-literals": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.8.3.tgz", + "integrity": "sha512-820QBtykIQOLFT8NZOcTRJ1UNuztIELe4p9DCgvj4NK+PwluSJ49we7s9FB1HIGNIYT7wFUJ0ar2QpCDj0escQ==", "dev": true, "requires": { - "JSONStream": "^1.0.3", - "browser-resolve": "^1.7.0", - "cached-path-relative": "^1.0.2", - "concat-stream": "~1.6.0", - "defined": "^1.0.0", - "detective": "^5.0.2", - "duplexer2": "^0.1.2", - "inherits": "^2.0.1", - "parents": "^1.0.0", - "readable-stream": "^2.0.2", - "resolve": "^1.4.0", - "stream-combiner2": "^1.1.1", - "subarg": "^1.0.0", - "through2": "^2.0.0", - "xtend": "^4.0.0" + "@babel/helper-annotate-as-pure": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3" } }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true + "@babel/plugin-transform-typeof-symbol": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.8.3.tgz", + "integrity": "sha512-3TrkKd4LPqm4jHs6nPtSDI/SV9Cm5PRJkHLUgTcqRQQTMAZ44ZaAdDZJtvWFSaRcvT0a1rTmJ5ZA5tDKjleF3g==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } }, - "on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "@babel/plugin-transform-unicode-regex": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.8.3.tgz", + "integrity": "sha512-+ufgJjYdmWfSQ+6NS9VGUR2ns8cjJjYbrbi11mZBTaWm+Fui/ncTLFF28Ei1okavY+xkojGr1eJxNsWYeA5aZw==", "dev": true, "requires": { - "ee-first": "1.1.1" + "@babel/helper-create-regexp-features-plugin": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3" } }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "@babel/preset-env": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.8.3.tgz", + "integrity": "sha512-Rs4RPL2KjSLSE2mWAx5/iCH+GC1ikKdxPrhnRS6PfFVaiZeom22VFKN4X8ZthyN61kAaR05tfXTbCvatl9WIQg==", "dev": true, "requires": { - "wrappy": "1" + "@babel/compat-data": "^7.8.0", + "@babel/helper-compilation-targets": "^7.8.3", + "@babel/helper-module-imports": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/plugin-proposal-async-generator-functions": "^7.8.3", + "@babel/plugin-proposal-dynamic-import": "^7.8.3", + "@babel/plugin-proposal-json-strings": "^7.8.3", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-proposal-object-rest-spread": "^7.8.3", + "@babel/plugin-proposal-optional-catch-binding": "^7.8.3", + "@babel/plugin-proposal-optional-chaining": "^7.8.3", + "@babel/plugin-proposal-unicode-property-regex": "^7.8.3", + "@babel/plugin-syntax-async-generators": "^7.8.0", + "@babel/plugin-syntax-dynamic-import": "^7.8.0", + "@babel/plugin-syntax-json-strings": "^7.8.0", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.0", + "@babel/plugin-syntax-object-rest-spread": "^7.8.0", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.0", + "@babel/plugin-syntax-optional-chaining": "^7.8.0", + "@babel/plugin-syntax-top-level-await": "^7.8.3", + "@babel/plugin-transform-arrow-functions": "^7.8.3", + "@babel/plugin-transform-async-to-generator": "^7.8.3", + "@babel/plugin-transform-block-scoped-functions": "^7.8.3", + "@babel/plugin-transform-block-scoping": "^7.8.3", + "@babel/plugin-transform-classes": "^7.8.3", + "@babel/plugin-transform-computed-properties": "^7.8.3", + "@babel/plugin-transform-destructuring": "^7.8.3", + "@babel/plugin-transform-dotall-regex": "^7.8.3", + "@babel/plugin-transform-duplicate-keys": "^7.8.3", + "@babel/plugin-transform-exponentiation-operator": "^7.8.3", + "@babel/plugin-transform-for-of": "^7.8.3", + "@babel/plugin-transform-function-name": "^7.8.3", + "@babel/plugin-transform-literals": "^7.8.3", + "@babel/plugin-transform-member-expression-literals": "^7.8.3", + "@babel/plugin-transform-modules-amd": "^7.8.3", + "@babel/plugin-transform-modules-commonjs": "^7.8.3", + "@babel/plugin-transform-modules-systemjs": "^7.8.3", + "@babel/plugin-transform-modules-umd": "^7.8.3", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.8.3", + "@babel/plugin-transform-new-target": "^7.8.3", + "@babel/plugin-transform-object-super": "^7.8.3", + "@babel/plugin-transform-parameters": "^7.8.3", + "@babel/plugin-transform-property-literals": "^7.8.3", + "@babel/plugin-transform-regenerator": "^7.8.3", + "@babel/plugin-transform-reserved-words": "^7.8.3", + "@babel/plugin-transform-shorthand-properties": "^7.8.3", + "@babel/plugin-transform-spread": "^7.8.3", + "@babel/plugin-transform-sticky-regex": "^7.8.3", + "@babel/plugin-transform-template-literals": "^7.8.3", + "@babel/plugin-transform-typeof-symbol": "^7.8.3", + "@babel/plugin-transform-unicode-regex": "^7.8.3", + "@babel/types": "^7.8.3", + "browserslist": "^4.8.2", + "core-js-compat": "^3.6.2", + "invariant": "^2.2.2", + "levenary": "^1.1.0", + "semver": "^5.5.0" } }, - "os-browserify": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", - "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=", - "dev": true + "@babel/runtime": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.8.3.tgz", + "integrity": "sha512-fVHx1rzEmwB130VTkLnxR+HmxcTjGzH12LYQcFFoBwakMd3aOMD4OsRN7tGG/UOYE2ektgFrS8uACAoRk1CY0w==", + "dev": true, + "requires": { + "regenerator-runtime": "^0.13.2" + } }, - "pako": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.10.tgz", - "integrity": "sha512-0DTvPVU3ed8+HNXOu5Bs+o//Mbdj9VNQMUOe9oKCwh8l0GNwpTDMKCWbRjgtD291AWnkAgkqA/LOnQS8AmS1tw==", - "dev": true + "@babel/template": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.8.3.tgz", + "integrity": "sha512-04m87AcQgAFdvuoyiQ2kgELr2tV8B4fP/xJAVUL3Yb3bkNdMedD3d0rlSQr3PegP0cms3eHjl1F7PWlvWbU8FQ==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.8.3", + "@babel/parser": "^7.8.3", + "@babel/types": "^7.8.3" + } }, - "parents": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parents/-/parents-1.0.1.tgz", - "integrity": "sha1-/t1NK/GTp3dF/nHjcdc8MwfZx1E=", + "@babel/traverse": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.8.3.tgz", + "integrity": "sha512-we+a2lti+eEImHmEXp7bM9cTxGzxPmBiVJlLVD+FuuQMeeO7RaDbutbgeheDkw+Xe3mCfJHnGOWLswT74m2IPg==", "dev": true, "requires": { - "path-platform": "~0.11.15" + "@babel/code-frame": "^7.8.3", + "@babel/generator": "^7.8.3", + "@babel/helper-function-name": "^7.8.3", + "@babel/helper-split-export-declaration": "^7.8.3", + "@babel/parser": "^7.8.3", + "@babel/types": "^7.8.3", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.13" } }, - "parse-asn1": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.4.tgz", - "integrity": "sha512-Qs5duJcuvNExRfFZ99HDD3z4mAi3r9Wl/FOjEOijlxwCZs7E7mW2vjTpgQ4J8LpTF8x5v+1Vn5UQFejmWT11aw==", + "@babel/types": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.8.3.tgz", + "integrity": "sha512-jBD+G8+LWpMBBWvVcdr4QysjUE4mU/syrhN17o1u3gx0/WzJB1kwiVZAXRtWbsIPOwW8pF/YJV5+nmetPzepXg==", "dev": true, "requires": { - "asn1.js": "^4.0.0", - "browserify-aes": "^1.0.0", - "create-hash": "^1.1.0", - "evp_bytestokey": "^1.0.0", - "pbkdf2": "^3.0.3", - "safe-buffer": "^5.1.1" + "esutils": "^2.0.2", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" } }, - "path-browserify": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.1.tgz", - "integrity": "sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ==", + "@iarna/toml": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/@iarna/toml/-/toml-2.2.3.tgz", + "integrity": "sha512-FmuxfCuolpLl0AnQ2NHSzoUKWEJDFl63qXjzdoWBVyFCXzMGm1spBzk7LeHNoVCiWCF7mRVms9e6jEV9+MoPbg==", "dev": true }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true + "@mrmlnc/readdir-enhanced": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz", + "integrity": "sha512-bPHp6Ji8b41szTOcaP63VlnbbO5Ny6dwAATtY6JTjh5N2OLrb5Qk/Th5cRkRQhkWCt+EJsYrNB0MiL+Gpn6e3g==", + "dev": true, + "requires": { + "call-me-maybe": "^1.0.1", + "glob-to-regexp": "^0.3.0" + } }, - "path-parse": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", - "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "@nodelib/fs.stat": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz", + "integrity": "sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==", "dev": true }, - "path-platform": { - "version": "0.11.15", - "resolved": "https://registry.npmjs.org/path-platform/-/path-platform-0.11.15.tgz", - "integrity": "sha1-6GQhf3TDaFDwhSt43Hv31KVyG/I=", + "@parcel/fs": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@parcel/fs/-/fs-1.11.0.tgz", + "integrity": "sha512-86RyEqULbbVoeo8OLcv+LQ1Vq2PKBAvWTU9fCgALxuCTbbs5Ppcvll4Vr+Ko1AnmMzja/k++SzNAwJfeQXVlpA==", + "dev": true, + "requires": { + "@parcel/utils": "^1.11.0", + "mkdirp": "^0.5.1", + "rimraf": "^2.6.2" + } + }, + "@parcel/logger": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@parcel/logger/-/logger-1.11.1.tgz", + "integrity": "sha512-9NF3M6UVeP2udOBDILuoEHd8VrF4vQqoWHEafymO1pfSoOMfxrSJZw1MfyAAIUN/IFp9qjcpDCUbDZB+ioVevA==", + "dev": true, + "requires": { + "@parcel/workers": "^1.11.0", + "chalk": "^2.1.0", + "grapheme-breaker": "^0.3.2", + "ora": "^2.1.0", + "strip-ansi": "^4.0.0" + } + }, + "@parcel/utils": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@parcel/utils/-/utils-1.11.0.tgz", + "integrity": "sha512-cA3p4jTlaMeOtAKR/6AadanOPvKeg8VwgnHhOyfi0yClD0TZS/hi9xu12w4EzA/8NtHu0g6o4RDfcNjqN8l1AQ==", "dev": true }, - "pbkdf2": { - "version": "3.0.17", - "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.17.tgz", - "integrity": "sha512-U/il5MsrZp7mGg3mSQfn742na2T+1/vHDCG5/iTI3X9MKUuYUZVLQhyRsg06mCgDBTd57TxzgZt7P+fYfjRLtA==", + "@parcel/watcher": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-1.12.1.tgz", + "integrity": "sha512-od+uCtCxC/KoNQAIE1vWx1YTyKYY+7CTrxBJPRh3cDWw/C0tCtlBMVlrbplscGoEpt6B27KhJDCv82PBxOERNA==", "dev": true, "requires": { - "create-hash": "^1.1.2", - "create-hmac": "^1.1.4", - "ripemd160": "^2.0.1", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" + "@parcel/utils": "^1.11.0", + "chokidar": "^2.1.5" } }, - "process": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", - "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", + "@parcel/workers": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@parcel/workers/-/workers-1.11.0.tgz", + "integrity": "sha512-USSjRAAQYsZFlv43FUPdD+jEGML5/8oLF0rUzPQTtK4q9kvaXr49F5ZplyLz5lox78cLZ0TxN2bIDQ1xhOkulQ==", + "dev": true, + "requires": { + "@parcel/utils": "^1.11.0", + "physical-cpu-count": "^2.0.0" + } + }, + "@types/q": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.2.tgz", + "integrity": "sha512-ce5d3q03Ex0sy4R14722Rmt6MT07Ua+k4FwDfdcToYJcMKNtRVQvJ6JCAPdAmAnbRb6CsX6aYb9m96NGod9uTw==", "dev": true }, - "process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "abab": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.3.tgz", + "integrity": "sha512-tsFzPpcttalNjFBCFMqsKYQcWxxen1pgJR56by//QwvJc4/OUS3kPOOttx2tSIfjsylB0pYu7f5D3K1RCxUnUg==", "dev": true }, - "public-encrypt": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", - "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", + "acorn": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.2.0.tgz", + "integrity": "sha512-8oe72N3WPMjA+2zVG71Ia0nXZ8DpQH+QyyHO+p06jT8eg8FGG3FbcUIi8KziHlAfheJQZeoqbvq1mQSQHXKYLw==", + "dev": true + }, + "acorn-globals": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-4.3.4.tgz", + "integrity": "sha512-clfQEh21R+D0leSbUdWf3OcfqyaCSAQ8Ryq00bofSekfr9W8u1jyYZo6ir0xu9Gtcf7BjcHJpnbZH7JOCpP60A==", "dev": true, "requires": { - "bn.js": "^4.1.0", - "browserify-rsa": "^4.0.0", - "create-hash": "^1.1.0", - "parse-asn1": "^5.0.0", - "randombytes": "^2.0.1", - "safe-buffer": "^5.1.2" + "acorn": "^6.0.1", + "acorn-walk": "^6.0.1" } }, - "punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "acorn-walk": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.2.0.tgz", + "integrity": "sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA==", "dev": true }, - "querystring": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", - "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", + "ajv": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.11.0.tgz", + "integrity": "sha512-nCprB/0syFYy9fVYU1ox1l2KN8S9I+tziH8D4zdZuLT3N6RMlGSGt5FSTpAiHB/Whv8Qs1cWHma1aMKZyaHRKA==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "alphanum-sort": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/alphanum-sort/-/alphanum-sort-1.0.2.tgz", + "integrity": "sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM=", "dev": true }, - "querystring-es3": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", - "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=", + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", "dev": true }, - "randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, "requires": { - "safe-buffer": "^5.1.0" + "color-convert": "^1.9.0" } }, - "randomfill": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", - "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", + "ansi-to-html": { + "version": "0.6.13", + "resolved": "https://registry.npmjs.org/ansi-to-html/-/ansi-to-html-0.6.13.tgz", + "integrity": "sha512-Ys2/umuaTlQvP9DLkaa7UzRKF2FLrfod/hNHXS9QhXCrw7seObG6ksOGmNz3UoK+adwM8L9vQfG7mvaxfJ3Jvw==", "dev": true, "requires": { - "randombytes": "^2.0.5", - "safe-buffer": "^5.1.0" + "entities": "^1.1.2" } }, - "read-only-stream": { + "anymatch": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/read-only-stream/-/read-only-stream-2.0.0.tgz", - "integrity": "sha1-JyT9aoET1zdkrCiNQ4YnDB2/F/A=", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", "dev": true, "requires": { - "readable-stream": "^2.0.2" + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + }, + "dependencies": { + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "requires": { + "remove-trailing-separator": "^1.0.1" + } + } } }, - "readable-stream": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", "dev": true, "requires": { - "core-util-is": "~1.0.0", - "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.1" + "sprintf-js": "~1.0.2" + } + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "dev": true + }, + "arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", + "dev": true + }, + "array-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-equal/-/array-equal-1.0.0.tgz", + "integrity": "sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "asn1": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", + "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "dev": true, + "requires": { + "safer-buffer": "~2.1.0" + } + }, + "asn1.js": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", + "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", + "dev": true, + "requires": { + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, + "assert": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/assert/-/assert-1.5.0.tgz", + "integrity": "sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA==", + "dev": true, + "requires": { + "object-assign": "^4.1.1", + "util": "0.10.3" }, "dependencies": { - "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==", + "inherits": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", "dev": true }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "util": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", + "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", "dev": true, "requires": { - "safe-buffer": "~5.1.0" + "inherits": "2.0.1" } } } }, - "resolve": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.11.1.tgz", - "integrity": "sha512-vIpgF6wfuJOZI7KKKSP+HmiKggadPQAdsp5HiC1mvqnfp0gF1vdwgBWZIdrVft9pgqoMFQN+R7BSWZiBxx+BBw==", - "dev": true, - "requires": { - "path-parse": "^1.0.6" - } + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true }, - "ripemd160": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", - "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", + "dev": true + }, + "async-each": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", + "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==", + "dev": true + }, + "async-limiter": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", + "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==", + "dev": true + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "dev": true + }, + "atob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", + "dev": true + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", + "dev": true + }, + "aws4": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.9.1.tgz", + "integrity": "sha512-wMHVg2EOHaMRxbzgFJ9gtjOOCrI80OHLG14rxi28XwOW8ux6IiEbRCGGGqCtdAIg4FQCbW20k9RsT4y3gJlFug==", + "dev": true + }, + "babel-plugin-dynamic-import-node": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.0.tgz", + "integrity": "sha512-o6qFkpeQEBxcqt0XYlWzAVxNCSCZdUgcR8IRlhD/8DylxjjO4foPcvTW0GGKa/cVt3rvxZ7o5ippJ+/0nvLhlQ==", + "dev": true, + "requires": { + "object.assign": "^4.1.0" + } + }, + "babel-runtime": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", + "dev": true, + "requires": { + "core-js": "^2.4.0", + "regenerator-runtime": "^0.11.0" + }, + "dependencies": { + "regenerator-runtime": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", + "dev": true + } + } + }, + "babel-types": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", + "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", + "dev": true, + "requires": { + "babel-runtime": "^6.26.0", + "esutils": "^2.0.2", + "lodash": "^4.17.4", + "to-fast-properties": "^1.0.3" + }, + "dependencies": { + "to-fast-properties": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", + "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=", + "dev": true + } + } + }, + "babylon-walk": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/babylon-walk/-/babylon-walk-1.0.2.tgz", + "integrity": "sha1-OxWl3btIKni0zpwByLoYFwLZ1s4=", + "dev": true, + "requires": { + "babel-runtime": "^6.11.6", + "babel-types": "^6.15.0", + "lodash.clone": "^4.5.0" + } + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "base": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "dev": true, + "requires": { + "cache-base": "^1.0.1", + "class-utils": "^0.3.5", + "component-emitter": "^1.2.1", + "define-property": "^1.0.0", + "isobject": "^3.0.1", + "mixin-deep": "^1.2.0", + "pascalcase": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "base64-js": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.0.tgz", + "integrity": "sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw==", + "dev": true + }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "dev": true, + "requires": { + "tweetnacl": "^0.14.3" + } + }, + "binary-extensions": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", + "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", + "dev": true + }, + "bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "dev": true, + "requires": { + "file-uri-to-path": "1.0.0" + } + }, + "bn.js": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", + "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", + "dev": true + }, + "boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "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.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "brfs": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/brfs/-/brfs-1.6.1.tgz", + "integrity": "sha512-OfZpABRQQf+Xsmju8XE9bDjs+uU4vLREGolP7bDgcpsI17QREyZ4Bl+2KLxxx1kCgA0fAIhKQBaBYh+PEcCqYQ==", + "dev": true, + "requires": { + "quote-stream": "^1.0.1", + "resolve": "^1.1.5", + "static-module": "^2.2.0", + "through2": "^2.0.0" + } + }, + "brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", + "dev": true + }, + "browser-process-hrtime": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-0.1.3.tgz", + "integrity": "sha512-bRFnI4NnjO6cnyLmOV/7PVoDEMJChlcfN0z4s1YMBY989/SvlfMI1lgCnkFUs53e9gQF+w7qu7XdllSTiSl8Aw==", + "dev": true + }, + "browserify-aes": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", + "dev": true, + "requires": { + "buffer-xor": "^1.0.3", + "cipher-base": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.3", + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "browserify-cipher": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", + "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", + "dev": true, + "requires": { + "browserify-aes": "^1.0.4", + "browserify-des": "^1.0.0", + "evp_bytestokey": "^1.0.0" + } + }, + "browserify-des": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", + "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", + "dev": true, + "requires": { + "cipher-base": "^1.0.1", + "des.js": "^1.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "browserify-rsa": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", + "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "randombytes": "^2.0.1" + } + }, + "browserify-sign": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz", + "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=", + "dev": true, + "requires": { + "bn.js": "^4.1.1", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.2", + "elliptic": "^6.0.0", + "inherits": "^2.0.1", + "parse-asn1": "^5.0.0" + } + }, + "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==", + "dev": true, + "requires": { + "pako": "~1.0.5" + } + }, + "browserslist": { + "version": "4.8.4", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.8.4.tgz", + "integrity": "sha512-3qv/Ar3nRnRTpwGD+LZc7F4YHDBb3NAEIn+DesNa8TcBhyxf8eDqYwTOa70kiWXwvFjQQz+abbykJcyOlfBfNg==", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30001021", + "electron-to-chromium": "^1.3.338", + "node-releases": "^1.1.46" + } + }, + "buffer-equal": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-0.0.1.tgz", + "integrity": "sha1-kbx0sR6kBbyRa8aqkI+q+ltKrEs=", + "dev": true + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", + "dev": true + }, + "buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", + "dev": true + }, + "builtin-status-codes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", + "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=", + "dev": true + }, + "cache-base": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "dev": true, + "requires": { + "collection-visit": "^1.0.0", + "component-emitter": "^1.2.1", + "get-value": "^2.0.6", + "has-value": "^1.0.0", + "isobject": "^3.0.1", + "set-value": "^2.0.0", + "to-object-path": "^0.3.0", + "union-value": "^1.0.0", + "unset-value": "^1.0.0" + } + }, + "call-me-maybe": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.1.tgz", + "integrity": "sha1-JtII6onje1y95gJQoV8DHBak1ms=", + "dev": true + }, + "caller-callsite": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz", + "integrity": "sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ=", + "dev": true, + "requires": { + "callsites": "^2.0.0" + } + }, + "caller-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-2.0.0.tgz", + "integrity": "sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ=", + "dev": true, + "requires": { + "caller-callsite": "^2.0.0" + } + }, + "callsites": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz", + "integrity": "sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA=", + "dev": true + }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + }, + "caniuse-api": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz", + "integrity": "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==", + "dev": true, + "requires": { + "browserslist": "^4.0.0", + "caniuse-lite": "^1.0.0", + "lodash.memoize": "^4.1.2", + "lodash.uniq": "^4.5.0" + }, + "dependencies": { + "lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=", + "dev": true + } + } + }, + "caniuse-lite": { + "version": "1.0.30001022", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001022.tgz", + "integrity": "sha512-FjwPPtt/I07KyLPkBQ0g7/XuZg6oUkYBVnPHNj3VHJbOjmmJ/GdSo/GUY6MwINEQvjhP6WZVbX8Tvms8xh0D5A==", + "dev": true + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", + "dev": true + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "chokidar": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", + "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", + "dev": true, + "requires": { + "anymatch": "^2.0.0", + "async-each": "^1.0.1", + "braces": "^2.3.2", + "fsevents": "^1.2.7", + "glob-parent": "^3.1.0", + "inherits": "^2.0.3", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "normalize-path": "^3.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.2.1", + "upath": "^1.1.1" + } + }, + "cipher-base": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "class-utils": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "dev": true, + "requires": { + "arr-union": "^3.1.0", + "define-property": "^0.2.5", + "isobject": "^3.0.0", + "static-extend": "^0.1.1" + }, + "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=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, + "cli-cursor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", + "dev": true, + "requires": { + "restore-cursor": "^2.0.0" + } + }, + "cli-spinners": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-1.3.1.tgz", + "integrity": "sha512-1QL4544moEsDVH9T/l6Cemov/37iv1RtoKf7NJ04A60+4MREXNfx/QvavbH6QoGdsD4N4Mwy49cmaINR/o2mdg==", + "dev": true + }, + "cliui": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "dev": true, + "requires": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=", + "dev": true + }, + "coa": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/coa/-/coa-2.0.2.tgz", + "integrity": "sha512-q5/jG+YQnSy4nRTV4F7lPepBJZ8qBNJJDBuJdoejDyLXgmL7IEo+Le2JDZudFTFt7mrCqIRaSjws4ygRCTCAXA==", + "dev": true, + "requires": { + "@types/q": "^1.5.1", + "chalk": "^2.4.1", + "q": "^1.1.2" + } + }, + "collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", + "dev": true, + "requires": { + "map-visit": "^1.0.0", + "object-visit": "^1.0.0" + } + }, + "color": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/color/-/color-3.1.2.tgz", + "integrity": "sha512-vXTJhHebByxZn3lDvDJYw4lR5+uB3vuoHsuYA5AKuxRVn5wzzIfQKGLBmgdVRHKTJYeK5rvJcHnrd0Li49CFpg==", + "dev": true, + "requires": { + "color-convert": "^1.9.1", + "color-string": "^1.5.2" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "color-string": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.3.tgz", + "integrity": "sha512-dC2C5qeWoYkxki5UAXapdjqO672AM4vZuPGRQfO8b5HKuKGBbKWpITyDYN7TOFKvRW7kOgAn3746clDBMDJyQw==", + "dev": true, + "requires": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } + }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "command-exists": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/command-exists/-/command-exists-1.2.8.tgz", + "integrity": "sha512-PM54PkseWbiiD/mMsbvW351/u+dafwTJ0ye2qB60G1aGQP9j3xK2gmMDc+R34L3nDtx4qMCitXT75mkbkGJDLw==", + "dev": true + }, + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "component-emitter": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "console-browserify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", + "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=", + "dev": true, + "requires": { + "date-now": "^0.1.4" + } + }, + "constants-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", + "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=", + "dev": true + }, + "copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", + "dev": true + }, + "core-js": { + "version": "2.6.11", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.11.tgz", + "integrity": "sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg==", + "dev": true + }, + "core-js-compat": { + "version": "3.6.4", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.6.4.tgz", + "integrity": "sha512-zAa3IZPvsJ0slViBQ2z+vgyyTuhd3MFn1rBQjZSKVEgB0UMYhUkCj9jJUVPgGTGqWvsBVmfnruXgTcNyTlEiSA==", + "dev": true, + "requires": { + "browserslist": "^4.8.3", + "semver": "7.0.0" + }, + "dependencies": { + "semver": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", + "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==", + "dev": true + } + } + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "cosmiconfig": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz", + "integrity": "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==", + "dev": true, + "requires": { + "import-fresh": "^2.0.0", + "is-directory": "^0.3.1", + "js-yaml": "^3.13.1", + "parse-json": "^4.0.0" + } + }, + "create-ecdh": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz", + "integrity": "sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw==", + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "elliptic": "^6.0.0" + } + }, + "create-hash": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "dev": true, + "requires": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" + } + }, + "create-hmac": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "dev": true, + "requires": { + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "crypto-browserify": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", + "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", + "dev": true, + "requires": { + "browserify-cipher": "^1.0.0", + "browserify-sign": "^4.0.0", + "create-ecdh": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.0", + "diffie-hellman": "^5.0.0", + "inherits": "^2.0.1", + "pbkdf2": "^3.0.3", + "public-encrypt": "^4.0.0", + "randombytes": "^2.0.0", + "randomfill": "^1.0.3" + } + }, + "css-color-names": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/css-color-names/-/css-color-names-0.0.4.tgz", + "integrity": "sha1-gIrcLnnPhHOAabZGyyDsJ762KeA=", + "dev": true + }, + "css-declaration-sorter": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-4.0.1.tgz", + "integrity": "sha512-BcxQSKTSEEQUftYpBVnsH4SF05NTuBokb19/sBt6asXGKZ/6VP7PLG1CBCkFDYOnhXhPh0jMhO6xZ71oYHXHBA==", + "dev": true, + "requires": { + "postcss": "^7.0.1", + "timsort": "^0.3.0" + } + }, + "css-modules-loader-core": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/css-modules-loader-core/-/css-modules-loader-core-1.1.0.tgz", + "integrity": "sha1-WQhmgpShvs0mGuCkziGwtVHyHRY=", + "dev": true, + "requires": { + "icss-replace-symbols": "1.1.0", + "postcss": "6.0.1", + "postcss-modules-extract-imports": "1.1.0", + "postcss-modules-local-by-default": "1.2.0", + "postcss-modules-scope": "1.1.0", + "postcss-modules-values": "1.3.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + }, + "dependencies": { + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, + "postcss": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.1.tgz", + "integrity": "sha1-AA29H47vIXqjaLmiEsX8QLKo8/I=", + "dev": true, + "requires": { + "chalk": "^1.1.3", + "source-map": "^0.5.6", + "supports-color": "^3.2.3" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true, + "requires": { + "has-flag": "^1.0.0" + } + } + } + }, + "css-select": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-2.1.0.tgz", + "integrity": "sha512-Dqk7LQKpwLoH3VovzZnkzegqNSuAziQyNZUcrdDM401iY+R5NkGBXGmtO05/yaXQziALuPogeG0b7UAgjnTJTQ==", + "dev": true, + "requires": { + "boolbase": "^1.0.0", + "css-what": "^3.2.1", + "domutils": "^1.7.0", + "nth-check": "^1.0.2" + } + }, + "css-select-base-adapter": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz", + "integrity": "sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w==", + "dev": true + }, + "css-selector-tokenizer": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/css-selector-tokenizer/-/css-selector-tokenizer-0.7.1.tgz", + "integrity": "sha512-xYL0AMZJ4gFzJQsHUKa5jiWWi2vH77WVNg7JYRyewwj6oPh4yb/y6Y9ZCw9dsj/9UauMhtuxR+ogQd//EdEVNA==", + "dev": true, + "requires": { + "cssesc": "^0.1.0", + "fastparse": "^1.1.1", + "regexpu-core": "^1.0.0" + }, + "dependencies": { + "jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", + "dev": true + }, + "regexpu-core": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-1.0.0.tgz", + "integrity": "sha1-hqdj9Y7k18L2sQLkdkBQ3n7ZDGs=", + "dev": true, + "requires": { + "regenerate": "^1.2.1", + "regjsgen": "^0.2.0", + "regjsparser": "^0.1.4" + } + }, + "regjsgen": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz", + "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=", + "dev": true + }, + "regjsparser": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz", + "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=", + "dev": true, + "requires": { + "jsesc": "~0.5.0" + } + } + } + }, + "css-tree": { + "version": "1.0.0-alpha.37", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.37.tgz", + "integrity": "sha512-DMxWJg0rnz7UgxKT0Q1HU/L9BeJI0M6ksor0OgqOnF+aRCDWg/N2641HmVyU9KVIu0OVVWOb2IpC9A+BJRnejg==", + "dev": true, + "requires": { + "mdn-data": "2.0.4", + "source-map": "^0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "css-unit-converter": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/css-unit-converter/-/css-unit-converter-1.1.1.tgz", + "integrity": "sha1-2bkoGtz9jO2TW9urqDeGiX9k6ZY=", + "dev": true + }, + "css-what": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-3.2.1.tgz", + "integrity": "sha512-WwOrosiQTvyms+Ti5ZC5vGEK0Vod3FTt1ca+payZqvKuGJF+dq7bG63DstxtN0dpm6FxY27a/zS3Wten+gEtGw==", + "dev": true + }, + "cssesc": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-0.1.0.tgz", + "integrity": "sha1-yBSQPkViM3GgR3tAEJqq++6t27Q=", + "dev": true + }, + "cssnano": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-4.1.10.tgz", + "integrity": "sha512-5wny+F6H4/8RgNlaqab4ktc3e0/blKutmq8yNlBFXA//nSFFAqAngjNVRzUvCgYROULmZZUoosL/KSoZo5aUaQ==", + "dev": true, + "requires": { + "cosmiconfig": "^5.0.0", + "cssnano-preset-default": "^4.0.7", + "is-resolvable": "^1.0.0", + "postcss": "^7.0.0" + } + }, + "cssnano-preset-default": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-4.0.7.tgz", + "integrity": "sha512-x0YHHx2h6p0fCl1zY9L9roD7rnlltugGu7zXSKQx6k2rYw0Hi3IqxcoAGF7u9Q5w1nt7vK0ulxV8Lo+EvllGsA==", + "dev": true, + "requires": { + "css-declaration-sorter": "^4.0.1", + "cssnano-util-raw-cache": "^4.0.1", + "postcss": "^7.0.0", + "postcss-calc": "^7.0.1", + "postcss-colormin": "^4.0.3", + "postcss-convert-values": "^4.0.1", + "postcss-discard-comments": "^4.0.2", + "postcss-discard-duplicates": "^4.0.2", + "postcss-discard-empty": "^4.0.1", + "postcss-discard-overridden": "^4.0.1", + "postcss-merge-longhand": "^4.0.11", + "postcss-merge-rules": "^4.0.3", + "postcss-minify-font-values": "^4.0.2", + "postcss-minify-gradients": "^4.0.2", + "postcss-minify-params": "^4.0.2", + "postcss-minify-selectors": "^4.0.2", + "postcss-normalize-charset": "^4.0.1", + "postcss-normalize-display-values": "^4.0.2", + "postcss-normalize-positions": "^4.0.2", + "postcss-normalize-repeat-style": "^4.0.2", + "postcss-normalize-string": "^4.0.2", + "postcss-normalize-timing-functions": "^4.0.2", + "postcss-normalize-unicode": "^4.0.1", + "postcss-normalize-url": "^4.0.1", + "postcss-normalize-whitespace": "^4.0.2", + "postcss-ordered-values": "^4.1.2", + "postcss-reduce-initial": "^4.0.3", + "postcss-reduce-transforms": "^4.0.2", + "postcss-svgo": "^4.0.2", + "postcss-unique-selectors": "^4.0.1" + } + }, + "cssnano-util-get-arguments": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cssnano-util-get-arguments/-/cssnano-util-get-arguments-4.0.0.tgz", + "integrity": "sha1-7ToIKZ8h11dBsg87gfGU7UnMFQ8=", + "dev": true + }, + "cssnano-util-get-match": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cssnano-util-get-match/-/cssnano-util-get-match-4.0.0.tgz", + "integrity": "sha1-wOTKB/U4a7F+xeUiULT1lhNlFW0=", + "dev": true + }, + "cssnano-util-raw-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/cssnano-util-raw-cache/-/cssnano-util-raw-cache-4.0.1.tgz", + "integrity": "sha512-qLuYtWK2b2Dy55I8ZX3ky1Z16WYsx544Q0UWViebptpwn/xDBmog2TLg4f+DBMg1rJ6JDWtn96WHbOKDWt1WQA==", + "dev": true, + "requires": { + "postcss": "^7.0.0" + } + }, + "cssnano-util-same-parent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/cssnano-util-same-parent/-/cssnano-util-same-parent-4.0.1.tgz", + "integrity": "sha512-WcKx5OY+KoSIAxBW6UBBRay1U6vkYheCdjyVNDm85zt5K9mHoGOfsOsqIszfAqrQQFIIKgjh2+FDgIj/zsl21Q==", + "dev": true + }, + "csso": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/csso/-/csso-4.0.2.tgz", + "integrity": "sha512-kS7/oeNVXkHWxby5tHVxlhjizRCSv8QdU7hB2FpdAibDU8FjTAolhNjKNTiLzXtUrKT6HwClE81yXwEk1309wg==", + "dev": true, + "requires": { + "css-tree": "1.0.0-alpha.37" + } + }, + "cssom": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", + "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", + "dev": true + }, + "cssstyle": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-1.4.0.tgz", + "integrity": "sha512-GBrLZYZ4X4x6/QEoBnIrqb8B/f5l4+8me2dkom/j1Gtbxy0kBv6OGzKuAsGM75bkGwGAFkt56Iwg28S3XTZgSA==", + "dev": true, + "requires": { + "cssom": "0.3.x" + } + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0" + } + }, + "data-urls": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-1.1.0.tgz", + "integrity": "sha512-YTWYI9se1P55u58gL5GkQHW4P6VJBJ5iBT+B5a7i2Tjadhv52paJG0qHX4A0OR6/t52odI64KP2YvFpkDOi3eQ==", + "dev": true, + "requires": { + "abab": "^2.0.0", + "whatwg-mimetype": "^2.2.0", + "whatwg-url": "^7.0.0" + } + }, + "date-now": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", + "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=", + "dev": true + }, + "deasync": { + "version": "0.1.19", + "resolved": "https://registry.npmjs.org/deasync/-/deasync-0.1.19.tgz", + "integrity": "sha512-oh3MRktfnPlLysCPpBpKZZzb4cUC/p0aA3SyRGp15lN30juJBTo/CiD0d4fR+f1kBtUQoJj1NE9RPNWQ7BQ9Mg==", + "dev": true, + "requires": { + "bindings": "^1.5.0", + "node-addon-api": "^1.7.1" + } + }, + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true + }, + "decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", + "dev": true + }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "dev": true + }, + "defaults": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", + "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", + "dev": true, + "requires": { + "clone": "^1.0.2" + }, + "dependencies": { + "clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", + "dev": true + } + } + }, + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, + "requires": { + "object-keys": "^1.0.12" + } + }, + "define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "dev": true, + "requires": { + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" + }, + "dependencies": { + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "dev": true + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "dev": true + }, + "des.js": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz", + "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, + "destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=", + "dev": true + }, + "diffie-hellman": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", + "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "miller-rabin": "^4.0.0", + "randombytes": "^2.0.0" + } + }, + "dom-serializer": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz", + "integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==", + "dev": true, + "requires": { + "domelementtype": "^2.0.1", + "entities": "^2.0.0" + }, + "dependencies": { + "domelementtype": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.0.1.tgz", + "integrity": "sha512-5HOHUDsYZWV8FGWN0Njbr/Rn7f/eWSQi1v7+HsUVwXgn8nWWlL64zKDkS0n8ZmQ3mlWOMuXOnR+7Nx/5tMO5AQ==", + "dev": true + }, + "entities": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.0.0.tgz", + "integrity": "sha512-D9f7V0JSRwIxlRI2mjMqufDrRDnx8p+eEOz7aUM9SuvF8gsBzra0/6tbjl1m8eQHrZlYj6PxqE00hZ1SAIKPLw==", + "dev": true + } + } + }, + "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==", + "dev": true + }, + "domelementtype": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", + "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==", + "dev": true + }, + "domexception": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/domexception/-/domexception-1.0.1.tgz", + "integrity": "sha512-raigMkn7CJNNo6Ihro1fzG7wr3fHuYVytzquZKX5n0yizGsTcYgzdIUwj1X9pK0VvjeihV+XiclP+DjwbsSKug==", + "dev": true, + "requires": { + "webidl-conversions": "^4.0.2" + } + }, + "domhandler": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz", + "integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==", + "dev": true, + "requires": { + "domelementtype": "1" + } + }, + "domutils": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz", + "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==", + "dev": true, + "requires": { + "dom-serializer": "0", + "domelementtype": "1" + } + }, + "dot-prop": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.0.tgz", + "integrity": "sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ==", + "dev": true, + "requires": { + "is-obj": "^1.0.0" + } + }, + "dotenv": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-5.0.1.tgz", + "integrity": "sha512-4As8uPrjfwb7VXC+WnLCbXK7y+Ueb2B3zgNCePYfhxS1PYeaO1YTeplffTEcbfLhvFNGLAz90VvJs9yomG7bow==", + "dev": true + }, + "dotenv-expand": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-5.1.0.tgz", + "integrity": "sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA==", + "dev": true + }, + "duplexer2": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", + "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", + "dev": true, + "requires": { + "readable-stream": "^2.0.2" + } + }, + "ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "dev": true, + "requires": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", + "dev": true + }, + "electron-to-chromium": { + "version": "1.3.338", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.338.tgz", + "integrity": "sha512-wlmfixuHEc9CkfOKgcqdtzBmRW4NStM9ptl5oPILY2UDyHuSXb3Yit+yLVyLObTgGuMMU36hhnfs2GDJId7ctA==", + "dev": true + }, + "elliptic": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.0.tgz", + "integrity": "sha512-eFOJTMyCYb7xtE/caJ6JJu+bhi67WCYNbkGSknu20pmM8Ke/bqOfdnZWxyoGN26JgfxTbXrsCkEw4KheCT/KGg==", + "dev": true, + "requires": { + "bn.js": "^4.4.0", + "brorand": "^1.0.1", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.0" + } + }, + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", + "dev": true + }, + "entities": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", + "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==", + "dev": true + }, + "envinfo": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.5.0.tgz", + "integrity": "sha512-jDgnJaF/Btomk+m3PZDTTCb5XIIIX3zYItnCRfF73zVgvinLoRomuhi75Y4su0PtQxWz4v66XnLLckyvyJTOIQ==", + "dev": true + }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "es-abstract": { + "version": "1.17.3", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.3.tgz", + "integrity": "sha512-AwiVPKf3sKGMoWtFw0J7Y4MTZ4Iek67k4COWOwHqS8B9TOZ71DCfcoBmdamy8Y6mj4MDz0+VNUpC2HKHFHA3pg==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.1.5", + "is-regex": "^1.0.5", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimleft": "^2.1.1", + "string.prototype.trimright": "^2.1.1" + }, + "dependencies": { + "object-inspect": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.7.0.tgz", + "integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw==", + "dev": true + } + } + }, + "es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "escodegen": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.9.1.tgz", + "integrity": "sha512-6hTjO1NAWkHnDk3OqQ4YrCuwwmGHL9S3nPlzBOUG/R44rda3wLNrfvQ5fkSGjyhHFKM7ALPKcKGrwvCLe0lC7Q==", + "dev": true, + "requires": { + "esprima": "^3.1.3", + "estraverse": "^4.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1", + "source-map": "~0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "optional": true + } + } + }, + "esprima": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", + "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=", + "dev": true + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true + }, + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", + "dev": true + }, + "evp_bytestokey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "dev": true, + "requires": { + "md5.js": "^1.3.4", + "safe-buffer": "^5.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=", + "dev": true, + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true + }, + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "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.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", + "dev": true + }, + "falafel": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/falafel/-/falafel-2.1.0.tgz", + "integrity": "sha1-lrsXdh2rqU9G0AFzizzt86Z/4Gw=", + "dev": true, + "requires": { + "acorn": "^5.0.0", + "foreach": "^2.0.5", + "isarray": "0.0.1", + "object-keys": "^1.0.6" + }, + "dependencies": { + "acorn": { + "version": "5.7.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz", + "integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==", + "dev": true + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + } + } + }, + "fast-deep-equal": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz", + "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==", + "dev": true + }, + "fast-glob": { + "version": "2.2.7", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-2.2.7.tgz", + "integrity": "sha512-g1KuQwHOZAmOZMuBtHdxDtju+T2RT8jgCC9aANsbpdiDDTSnjgfuVsIBNKbUeJI3oKMRExcfNDtJl4OhbffMsw==", + "dev": true, + "requires": { + "@mrmlnc/readdir-enhanced": "^2.2.1", + "@nodelib/fs.stat": "^1.1.2", + "glob-parent": "^3.1.0", + "is-glob": "^4.0.0", + "merge2": "^1.2.3", + "micromatch": "^3.1.10" + } + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, + "fastparse": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/fastparse/-/fastparse-1.1.2.tgz", + "integrity": "sha512-483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ==", + "dev": true + }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "dev": true + }, + "filesize": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/filesize/-/filesize-3.6.1.tgz", + "integrity": "sha512-7KjR1vv6qnicaPMi1iiTcI85CyYwRO/PSFCu6SvqL8jN2Wjt/NIYQTFtFs7fSDCYOstUkEWIQGFUg5YZQfjlcg==", + "dev": true + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "dev": true + }, + "foreach": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", + "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=", + "dev": true + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "dev": true + }, + "form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "dev": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + } + }, + "fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "dev": true, + "requires": { + "map-cache": "^0.2.2" + } + }, + "fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", + "dev": true + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "fsevents": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.11.tgz", + "integrity": "sha512-+ux3lx6peh0BpvY0JebGyZoiR4D+oYzdPZMKJwkZ+sFkNJzpL7tXc/wehS49gUAxg3tmMHPHZkA8JU2rhhgDHw==", + "dev": true, + "optional": true, + "requires": { + "bindings": "^1.5.0", + "nan": "^2.12.1", + "node-pre-gyp": "*" + }, + "dependencies": { + "abbrev": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "aproba": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true + }, + "are-we-there-yet": { + "version": "1.1.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "balanced-match": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "brace-expansion": { + "version": "1.1.11", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "chownr": { + "version": "1.1.3", + "bundled": true, + "dev": true, + "optional": true + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "optional": true + }, + "concat-map": { + "version": "0.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "optional": true + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "debug": { + "version": "3.2.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ms": "^2.1.1" + } + }, + "deep-extend": { + "version": "0.6.0", + "bundled": true, + "dev": true, + "optional": true + }, + "delegates": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "detect-libc": { + "version": "1.0.3", + "bundled": true, + "dev": true, + "optional": true + }, + "fs-minipass": { + "version": "1.2.7", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minipass": "^2.6.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "gauge": { + "version": "2.7.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "glob": { + "version": "7.1.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "has-unicode": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "iconv-lite": { + "version": "0.4.24", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ignore-walk": { + "version": "3.0.3", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minimatch": "^3.0.4" + } + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "bundled": true, + "dev": true, + "optional": true + }, + "ini": { + "version": "1.3.5", + "bundled": true, + "dev": true, + "optional": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "bundled": true, + "dev": true, + "optional": true + }, + "minipass": { + "version": "2.9.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + } + }, + "minizlib": { + "version": "1.3.3", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minipass": "^2.9.0" + } + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.1.2", + "bundled": true, + "dev": true, + "optional": true + }, + "needle": { + "version": "2.4.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "debug": "^3.2.6", + "iconv-lite": "^0.4.4", + "sax": "^1.2.4" + } + }, + "node-pre-gyp": { + "version": "0.14.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "detect-libc": "^1.0.2", + "mkdirp": "^0.5.1", + "needle": "^2.2.1", + "nopt": "^4.0.1", + "npm-packlist": "^1.1.6", + "npmlog": "^4.0.2", + "rc": "^1.2.7", + "rimraf": "^2.6.1", + "semver": "^5.3.0", + "tar": "^4.4.2" + } + }, + "nopt": { + "version": "4.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "abbrev": "1", + "osenv": "^0.1.4" + } + }, + "npm-bundled": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "npm-normalize-package-bin": "^1.0.1" + } + }, + "npm-normalize-package-bin": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "npm-packlist": { + "version": "1.4.7", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ignore-walk": "^3.0.1", + "npm-bundled": "^1.0.1" + } + }, + "npmlog": { + "version": "4.1.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "once": { + "version": "1.4.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "wrappy": "1" + } + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "os-tmpdir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "osenv": { + "version": "0.1.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "process-nextick-args": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "rc": { + "version": "1.2.8", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "readable-stream": { + "version": "2.3.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "core-util-is": "~1.0.0", + "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.1" + } + }, + "rimraf": { + "version": "2.7.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "glob": "^7.1.3" + } + }, + "safe-buffer": { + "version": "5.1.2", + "bundled": true, + "dev": true, + "optional": true + }, + "safer-buffer": { + "version": "2.1.2", + "bundled": true, + "dev": true, + "optional": true + }, + "sax": { + "version": "1.2.4", + "bundled": true, + "dev": true, + "optional": true + }, + "semver": { + "version": "5.7.1", + "bundled": true, + "dev": true, + "optional": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "string-width": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "tar": { + "version": "4.4.13", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "chownr": "^1.1.1", + "fs-minipass": "^1.2.5", + "minipass": "^2.8.6", + "minizlib": "^1.2.1", + "mkdirp": "^0.5.0", + "safe-buffer": "^5.1.2", + "yallist": "^3.0.3" + } + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "wide-align": { + "version": "1.1.3", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "string-width": "^1.0.2 || 2" + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "yallist": { + "version": "3.1.1", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "gensync": { + "version": "1.0.0-beta.1", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.1.tgz", + "integrity": "sha512-r8EC6NO1sngH/zdD9fiRDLdcgnbayXah+mLgManTaIZJqEC1MZstmnox8KpnI2/fxQwrp5OpCOYWLp4rBl4Jcg==", + "dev": true + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true + }, + "get-port": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/get-port/-/get-port-3.2.0.tgz", + "integrity": "sha1-3Xzn3hh8Bsi/NTeWrHHgmfCYDrw=", + "dev": true + }, + "get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", + "dev": true + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0" + } + }, + "glob": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", + "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dev": true, + "requires": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "^2.1.0" + } + } + } + }, + "glob-to-regexp": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz", + "integrity": "sha1-jFoUlNIGbFcMw7/kSWF1rMTVAqs=", + "dev": true + }, + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true + }, + "graceful-fs": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", + "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==", + "dev": true + }, + "grapheme-breaker": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/grapheme-breaker/-/grapheme-breaker-0.3.2.tgz", + "integrity": "sha1-W55reMODJFLSuiuxy4MPlidkEKw=", + "dev": true, + "requires": { + "brfs": "^1.2.0", + "unicode-trie": "^0.3.1" + } + }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", + "dev": true + }, + "har-validator": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", + "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", + "dev": true, + "requires": { + "ajv": "^6.5.5", + "har-schema": "^2.0.0" + } + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + } + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "has-symbols": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", + "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", + "dev": true + }, + "has-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", + "dev": true, + "requires": { + "get-value": "^2.0.6", + "has-values": "^1.0.0", + "isobject": "^3.0.0" + } + }, + "has-values": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", + "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "kind-of": "^4.0.0" + }, + "dependencies": { + "kind-of": { + "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.5" + } + } + } + }, + "hash-base": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", + "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "hash.js": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, + "hex-color-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/hex-color-regex/-/hex-color-regex-1.1.0.tgz", + "integrity": "sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ==", + "dev": true + }, + "hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", + "dev": true, + "requires": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "hsl-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/hsl-regex/-/hsl-regex-1.0.0.tgz", + "integrity": "sha1-1JMwx4ntgZ4nakwNJy3/owsY/m4=", + "dev": true + }, + "hsla-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/hsla-regex/-/hsla-regex-1.0.0.tgz", + "integrity": "sha1-wc56MWjIxmFAM6S194d/OyJfnDg=", + "dev": true + }, + "html-comment-regex": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/html-comment-regex/-/html-comment-regex-1.1.2.tgz", + "integrity": "sha512-P+M65QY2JQ5Y0G9KKdlDpo0zK+/OHptU5AaBwUfAIDJZk1MYf32Frm84EcOytfJE0t5JvkAnKlmjsXDnWzCJmQ==", + "dev": true + }, + "html-encoding-sniffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-1.0.2.tgz", + "integrity": "sha512-71lZziiDnsuabfdYiUeWdCVyKuqwWi23L8YeIgV9jSSZHCtb6wB1BKWooH7L3tn4/FuZJMVWyNaIDr4RGmaSYw==", + "dev": true, + "requires": { + "whatwg-encoding": "^1.0.1" + } + }, + "html-tags": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-1.2.0.tgz", + "integrity": "sha1-x43mW1Zjqll5id0rerSSANfk25g=", + "dev": true + }, + "htmlnano": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/htmlnano/-/htmlnano-0.2.5.tgz", + "integrity": "sha512-X1iPSwXG/iF9bVs+/obt2n6F64uH0ETkA8zp7qFDmLW9/+A6ueHGeb/+qD67T21qUY22owZPMdawljN50ajkqA==", + "dev": true, + "requires": { + "cssnano": "^4.1.10", + "normalize-html-whitespace": "^1.0.0", + "posthtml": "^0.12.0", + "posthtml-render": "^1.1.5", + "purgecss": "^1.4.0", + "svgo": "^1.3.2", + "terser": "^4.3.9", + "uncss": "^0.17.2" + }, + "dependencies": { + "posthtml": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/posthtml/-/posthtml-0.12.0.tgz", + "integrity": "sha512-aNUEP/SfKUXAt+ghG51LC5MmafChBZeslVe/SSdfKIgLGUVRE68mrMF4V8XbH07ZifM91tCSuxY3eHIFLlecQw==", + "dev": true, + "requires": { + "posthtml-parser": "^0.4.1", + "posthtml-render": "^1.1.5" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "terser": { + "version": "4.6.3", + "resolved": "https://registry.npmjs.org/terser/-/terser-4.6.3.tgz", + "integrity": "sha512-Lw+ieAXmY69d09IIc/yqeBqXpEQIpDGZqT34ui1QWXIUpR2RjbqEkT8X7Lgex19hslSqcWM5iMN2kM11eMsESQ==", + "dev": true, + "requires": { + "commander": "^2.20.0", + "source-map": "~0.6.1", + "source-map-support": "~0.5.12" + } + } + } + }, + "htmlparser2": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz", + "integrity": "sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==", + "dev": true, + "requires": { + "domelementtype": "^1.3.1", + "domhandler": "^2.3.0", + "domutils": "^1.5.1", + "entities": "^1.1.1", + "inherits": "^2.0.1", + "readable-stream": "^3.1.1" + }, + "dependencies": { + "readable-stream": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.5.0.tgz", + "integrity": "sha512-gSz026xs2LfxBPudDuI41V1lka8cxg64E66SGe78zJlsUofOg/yqwezdIcdfwik6B4h8LFmWPA9ef9X3FiNFLA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "http-errors": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz", + "integrity": "sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==", + "dev": true, + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.4", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + } + }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } + }, + "https-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", + "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=", + "dev": true + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "icss-replace-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz", + "integrity": "sha1-Bupvg2ead0njhs/h/oEq5dsiPe0=", + "dev": true + }, + "ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==", + "dev": true + }, + "import-fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz", + "integrity": "sha1-2BNVwVYS04bGH53dOSLUMEgipUY=", + "dev": true, + "requires": { + "caller-path": "^2.0.0", + "resolve-from": "^3.0.0" + } + }, + "indexes-of": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/indexes-of/-/indexes-of-1.0.1.tgz", + "integrity": "sha1-8w9xbI4r00bHtn0985FVZqfAVgc=", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "dev": true, + "requires": { + "loose-envify": "^1.0.0" + } + }, + "ipfs-http-client": { + "version": "file:../..", + "requires": { + "abort-controller": "^3.0.0", + "bignumber.js": "^9.0.0", + "bs58": "^4.0.1", + "buffer": "^5.4.2", + "cids": "~0.7.1", + "debug": "^4.1.0", + "form-data": "^3.0.0", + "ipfs-block": "~0.8.1", + "ipfs-utils": "^0.6.0", + "ipld-dag-cbor": "^0.15.1", + "ipld-dag-pb": "^0.18.2", + "ipld-raw": "^4.0.1", + "it-tar": "^1.1.1", + "it-to-stream": "^0.1.1", + "iterable-ndjson": "^1.1.0", + "ky": "^0.15.0", + "ky-universal": "^0.3.0", + "merge-options": "^2.0.0", + "multiaddr": "^7.2.1", + "multiaddr-to-uri": "^5.1.0", + "multibase": "~0.6.0", + "multicodec": "^1.0.0", + "multihashes": "~0.4.14", + "parse-duration": "^0.1.1", + "stream-to-it": "^0.2.0" + }, + "dependencies": { + "@babel/cli": { + "version": "7.8.3", + "requires": { + "chokidar": "^2.1.8", + "commander": "^4.0.1", + "convert-source-map": "^1.1.0", + "fs-readdir-recursive": "^1.1.0", + "glob": "^7.0.0", + "lodash": "^4.17.13", + "make-dir": "^2.1.0", + "slash": "^2.0.0", + "source-map": "^0.5.0" + }, + "dependencies": { + "commander": { + "version": "4.1.0" + }, + "slash": { + "version": "2.0.0" + }, + "source-map": { + "version": "0.5.7" + } + } + }, + "@babel/code-frame": { + "version": "7.8.3", + "requires": { + "@babel/highlight": "^7.8.3" + } + }, + "@babel/compat-data": { + "version": "7.8.1", + "requires": { + "browserslist": "^4.8.2", + "invariant": "^2.2.4", + "semver": "^5.5.0" + } + }, + "@babel/core": { + "version": "7.8.3", + "requires": { + "@babel/code-frame": "^7.8.3", + "@babel/generator": "^7.8.3", + "@babel/helpers": "^7.8.3", + "@babel/parser": "^7.8.3", + "@babel/template": "^7.8.3", + "@babel/traverse": "^7.8.3", + "@babel/types": "^7.8.3", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.1", + "json5": "^2.1.0", + "lodash": "^4.17.13", + "resolve": "^1.3.2", + "semver": "^5.4.1", + "source-map": "^0.5.0" + }, + "dependencies": { + "source-map": { + "version": "0.5.7" + } + } + }, + "@babel/generator": { + "version": "7.8.3", + "requires": { + "@babel/types": "^7.8.3", + "jsesc": "^2.5.1", + "lodash": "^4.17.13", + "source-map": "^0.5.0" + }, + "dependencies": { + "source-map": { + "version": "0.5.7" + } + } + }, + "@babel/helper-annotate-as-pure": { + "version": "7.8.3", + "requires": { + "@babel/types": "^7.8.3" + } + }, + "@babel/helper-builder-binary-assignment-operator-visitor": { + "version": "7.8.3", + "requires": { + "@babel/helper-explode-assignable-expression": "^7.8.3", + "@babel/types": "^7.8.3" + } + }, + "@babel/helper-builder-react-jsx": { + "version": "7.8.3", + "requires": { + "@babel/types": "^7.8.3", + "esutils": "^2.0.0" + } + }, + "@babel/helper-call-delegate": { + "version": "7.8.3", + "requires": { + "@babel/helper-hoist-variables": "^7.8.3", + "@babel/traverse": "^7.8.3", + "@babel/types": "^7.8.3" + } + }, + "@babel/helper-compilation-targets": { + "version": "7.8.3", + "requires": { + "@babel/compat-data": "^7.8.1", + "browserslist": "^4.8.2", + "invariant": "^2.2.4", + "levenary": "^1.1.0", + "semver": "^5.5.0" + } + }, + "@babel/helper-create-class-features-plugin": { + "version": "7.8.3", + "requires": { + "@babel/helper-function-name": "^7.8.3", + "@babel/helper-member-expression-to-functions": "^7.8.3", + "@babel/helper-optimise-call-expression": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/helper-replace-supers": "^7.8.3", + "@babel/helper-split-export-declaration": "^7.8.3" + } + }, + "@babel/helper-create-regexp-features-plugin": { + "version": "7.8.3", + "requires": { + "@babel/helper-regex": "^7.8.3", + "regexpu-core": "^4.6.0" + } + }, + "@babel/helper-define-map": { + "version": "7.8.3", + "requires": { + "@babel/helper-function-name": "^7.8.3", + "@babel/types": "^7.8.3", + "lodash": "^4.17.13" + } + }, + "@babel/helper-explode-assignable-expression": { + "version": "7.8.3", + "requires": { + "@babel/traverse": "^7.8.3", + "@babel/types": "^7.8.3" + } + }, + "@babel/helper-function-name": { + "version": "7.8.3", + "requires": { + "@babel/helper-get-function-arity": "^7.8.3", + "@babel/template": "^7.8.3", + "@babel/types": "^7.8.3" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.8.3", + "requires": { + "@babel/types": "^7.8.3" + } + }, + "@babel/helper-hoist-variables": { + "version": "7.8.3", + "requires": { + "@babel/types": "^7.8.3" + } + }, + "@babel/helper-member-expression-to-functions": { + "version": "7.8.3", + "requires": { + "@babel/types": "^7.8.3" + } + }, + "@babel/helper-module-imports": { + "version": "7.8.3", + "requires": { + "@babel/types": "^7.8.3" + } + }, + "@babel/helper-module-transforms": { + "version": "7.8.3", + "requires": { + "@babel/helper-module-imports": "^7.8.3", + "@babel/helper-simple-access": "^7.8.3", + "@babel/helper-split-export-declaration": "^7.8.3", + "@babel/template": "^7.8.3", + "@babel/types": "^7.8.3", + "lodash": "^4.17.13" + } + }, + "@babel/helper-optimise-call-expression": { + "version": "7.8.3", + "requires": { + "@babel/types": "^7.8.3" + } + }, + "@babel/helper-plugin-utils": { + "version": "7.8.3" + }, + "@babel/helper-regex": { + "version": "7.8.3", + "requires": { + "lodash": "^4.17.13" + } + }, + "@babel/helper-remap-async-to-generator": { + "version": "7.8.3", + "requires": { + "@babel/helper-annotate-as-pure": "^7.8.3", + "@babel/helper-wrap-function": "^7.8.3", + "@babel/template": "^7.8.3", + "@babel/traverse": "^7.8.3", + "@babel/types": "^7.8.3" + } + }, + "@babel/helper-replace-supers": { + "version": "7.8.3", + "requires": { + "@babel/helper-member-expression-to-functions": "^7.8.3", + "@babel/helper-optimise-call-expression": "^7.8.3", + "@babel/traverse": "^7.8.3", + "@babel/types": "^7.8.3" + } + }, + "@babel/helper-simple-access": { + "version": "7.8.3", + "requires": { + "@babel/template": "^7.8.3", + "@babel/types": "^7.8.3" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.8.3", + "requires": { + "@babel/types": "^7.8.3" + } + }, + "@babel/helper-wrap-function": { + "version": "7.8.3", + "requires": { + "@babel/helper-function-name": "^7.8.3", + "@babel/template": "^7.8.3", + "@babel/traverse": "^7.8.3", + "@babel/types": "^7.8.3" + } + }, + "@babel/helpers": { + "version": "7.8.3", + "requires": { + "@babel/template": "^7.8.3", + "@babel/traverse": "^7.8.3", + "@babel/types": "^7.8.3" + } + }, + "@babel/highlight": { + "version": "7.8.3", + "requires": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.8.3" + }, + "@babel/plugin-proposal-async-generator-functions": { + "version": "7.8.3", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/helper-remap-async-to-generator": "^7.8.3", + "@babel/plugin-syntax-async-generators": "^7.8.0" + } + }, + "@babel/plugin-proposal-class-properties": { + "version": "7.8.3", + "requires": { + "@babel/helper-create-class-features-plugin": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-proposal-decorators": { + "version": "7.8.3", + "requires": { + "@babel/helper-create-class-features-plugin": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/plugin-syntax-decorators": "^7.8.3" + } + }, + "@babel/plugin-proposal-do-expressions": { + "version": "7.8.3", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/plugin-syntax-do-expressions": "^7.8.3" + } + }, + "@babel/plugin-proposal-dynamic-import": { + "version": "7.8.3", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/plugin-syntax-dynamic-import": "^7.8.0" + } + }, + "@babel/plugin-proposal-export-default-from": { + "version": "7.8.3", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/plugin-syntax-export-default-from": "^7.8.3" + } + }, + "@babel/plugin-proposal-export-namespace-from": { + "version": "7.8.3", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3" + } + }, + "@babel/plugin-proposal-function-bind": { + "version": "7.8.3", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/plugin-syntax-function-bind": "^7.8.3" + } + }, + "@babel/plugin-proposal-function-sent": { + "version": "7.8.3", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/helper-wrap-function": "^7.8.3", + "@babel/plugin-syntax-function-sent": "^7.8.3" + } + }, + "@babel/plugin-proposal-json-strings": { + "version": "7.8.3", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/plugin-syntax-json-strings": "^7.8.0" + } + }, + "@babel/plugin-proposal-logical-assignment-operators": { + "version": "7.8.3", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3" + } + }, + "@babel/plugin-proposal-nullish-coalescing-operator": { + "version": "7.8.3", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.0" + } + }, + "@babel/plugin-proposal-numeric-separator": { + "version": "7.8.3", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.8.3" + } + }, + "@babel/plugin-proposal-object-rest-spread": { + "version": "7.8.3", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/plugin-syntax-object-rest-spread": "^7.8.0" + } + }, + "@babel/plugin-proposal-optional-catch-binding": { + "version": "7.8.3", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.0" + } + }, + "@babel/plugin-proposal-optional-chaining": { + "version": "7.8.3", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.0" + } + }, + "@babel/plugin-proposal-pipeline-operator": { + "version": "7.8.3", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/plugin-syntax-pipeline-operator": "^7.8.3" + } + }, + "@babel/plugin-proposal-throw-expressions": { + "version": "7.8.3", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/plugin-syntax-throw-expressions": "^7.8.3" + } + }, + "@babel/plugin-proposal-unicode-property-regex": { + "version": "7.8.3", + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-decorators": { + "version": "7.8.3", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-syntax-do-expressions": { + "version": "7.8.3", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-syntax-dynamic-import": { + "version": "7.8.3", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-export-default-from": { + "version": "7.8.3", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-syntax-export-namespace-from": { + "version": "7.8.3", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-syntax-flow": { + "version": "7.8.3", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-syntax-function-bind": { + "version": "7.8.3", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-syntax-function-sent": { + "version": "7.8.3", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-syntax-import-meta": { + "version": "7.8.3", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-jsx": { + "version": "7.8.3", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.8.3", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-numeric-separator": { + "version": "7.8.3", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-pipeline-operator": { + "version": "7.8.3", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-syntax-throw-expressions": { + "version": "7.8.3", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-syntax-top-level-await": { + "version": "7.8.3", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-transform-arrow-functions": { + "version": "7.8.3", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-transform-async-to-generator": { + "version": "7.8.3", + "requires": { + "@babel/helper-module-imports": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/helper-remap-async-to-generator": "^7.8.3" + } + }, + "@babel/plugin-transform-block-scoped-functions": { + "version": "7.8.3", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-transform-block-scoping": { + "version": "7.8.3", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3", + "lodash": "^4.17.13" + } + }, + "@babel/plugin-transform-classes": { + "version": "7.8.3", + "requires": { + "@babel/helper-annotate-as-pure": "^7.8.3", + "@babel/helper-define-map": "^7.8.3", + "@babel/helper-function-name": "^7.8.3", + "@babel/helper-optimise-call-expression": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/helper-replace-supers": "^7.8.3", + "@babel/helper-split-export-declaration": "^7.8.3", + "globals": "^11.1.0" + } + }, + "@babel/plugin-transform-computed-properties": { + "version": "7.8.3", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-transform-destructuring": { + "version": "7.8.3", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-transform-dotall-regex": { + "version": "7.8.3", + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-transform-duplicate-keys": { + "version": "7.8.3", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-transform-exponentiation-operator": { + "version": "7.8.3", + "requires": { + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-transform-flow-strip-types": { + "version": "7.8.3", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/plugin-syntax-flow": "^7.8.3" + } + }, + "@babel/plugin-transform-for-of": { + "version": "7.8.3", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-transform-function-name": { + "version": "7.8.3", + "requires": { + "@babel/helper-function-name": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-transform-literals": { + "version": "7.8.3", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-transform-member-expression-literals": { + "version": "7.8.3", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-transform-modules-amd": { + "version": "7.8.3", + "requires": { + "@babel/helper-module-transforms": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3", + "babel-plugin-dynamic-import-node": "^2.3.0" + } + }, + "@babel/plugin-transform-modules-commonjs": { + "version": "7.8.3", + "requires": { + "@babel/helper-module-transforms": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/helper-simple-access": "^7.8.3", + "babel-plugin-dynamic-import-node": "^2.3.0" + } + }, + "@babel/plugin-transform-modules-systemjs": { + "version": "7.8.3", + "requires": { + "@babel/helper-hoist-variables": "^7.8.3", + "@babel/helper-module-transforms": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3", + "babel-plugin-dynamic-import-node": "^2.3.0" + } + }, + "@babel/plugin-transform-modules-umd": { + "version": "7.8.3", + "requires": { + "@babel/helper-module-transforms": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.8.3", + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.8.3" + } + }, + "@babel/plugin-transform-new-target": { + "version": "7.8.3", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-transform-object-super": { + "version": "7.8.3", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/helper-replace-supers": "^7.8.3" + } + }, + "@babel/plugin-transform-parameters": { + "version": "7.8.3", + "requires": { + "@babel/helper-call-delegate": "^7.8.3", + "@babel/helper-get-function-arity": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-transform-property-literals": { + "version": "7.8.3", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-transform-react-display-name": { + "version": "7.8.3", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-transform-react-jsx": { + "version": "7.8.3", + "requires": { + "@babel/helper-builder-react-jsx": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/plugin-syntax-jsx": "^7.8.3" + } + }, + "@babel/plugin-transform-react-jsx-self": { + "version": "7.8.3", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/plugin-syntax-jsx": "^7.8.3" + } + }, + "@babel/plugin-transform-react-jsx-source": { + "version": "7.8.3", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/plugin-syntax-jsx": "^7.8.3" + } + }, + "@babel/plugin-transform-regenerator": { + "version": "7.8.3", + "requires": { + "regenerator-transform": "^0.14.0" + } + }, + "@babel/plugin-transform-reserved-words": { + "version": "7.8.3", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-transform-runtime": { + "version": "7.8.3", + "requires": { + "@babel/helper-module-imports": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3", + "resolve": "^1.8.1", + "semver": "^5.5.1" + } + }, + "@babel/plugin-transform-shorthand-properties": { + "version": "7.8.3", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-transform-spread": { + "version": "7.8.3", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-transform-sticky-regex": { + "version": "7.8.3", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/helper-regex": "^7.8.3" + } + }, + "@babel/plugin-transform-template-literals": { + "version": "7.8.3", + "requires": { + "@babel/helper-annotate-as-pure": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-transform-typeof-symbol": { + "version": "7.8.3", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-transform-unicode-regex": { + "version": "7.8.3", + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/preset-env": { + "version": "7.8.3", + "requires": { + "@babel/compat-data": "^7.8.0", + "@babel/helper-compilation-targets": "^7.8.3", + "@babel/helper-module-imports": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/plugin-proposal-async-generator-functions": "^7.8.3", + "@babel/plugin-proposal-dynamic-import": "^7.8.3", + "@babel/plugin-proposal-json-strings": "^7.8.3", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-proposal-object-rest-spread": "^7.8.3", + "@babel/plugin-proposal-optional-catch-binding": "^7.8.3", + "@babel/plugin-proposal-optional-chaining": "^7.8.3", + "@babel/plugin-proposal-unicode-property-regex": "^7.8.3", + "@babel/plugin-syntax-async-generators": "^7.8.0", + "@babel/plugin-syntax-dynamic-import": "^7.8.0", + "@babel/plugin-syntax-json-strings": "^7.8.0", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.0", + "@babel/plugin-syntax-object-rest-spread": "^7.8.0", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.0", + "@babel/plugin-syntax-optional-chaining": "^7.8.0", + "@babel/plugin-syntax-top-level-await": "^7.8.3", + "@babel/plugin-transform-arrow-functions": "^7.8.3", + "@babel/plugin-transform-async-to-generator": "^7.8.3", + "@babel/plugin-transform-block-scoped-functions": "^7.8.3", + "@babel/plugin-transform-block-scoping": "^7.8.3", + "@babel/plugin-transform-classes": "^7.8.3", + "@babel/plugin-transform-computed-properties": "^7.8.3", + "@babel/plugin-transform-destructuring": "^7.8.3", + "@babel/plugin-transform-dotall-regex": "^7.8.3", + "@babel/plugin-transform-duplicate-keys": "^7.8.3", + "@babel/plugin-transform-exponentiation-operator": "^7.8.3", + "@babel/plugin-transform-for-of": "^7.8.3", + "@babel/plugin-transform-function-name": "^7.8.3", + "@babel/plugin-transform-literals": "^7.8.3", + "@babel/plugin-transform-member-expression-literals": "^7.8.3", + "@babel/plugin-transform-modules-amd": "^7.8.3", + "@babel/plugin-transform-modules-commonjs": "^7.8.3", + "@babel/plugin-transform-modules-systemjs": "^7.8.3", + "@babel/plugin-transform-modules-umd": "^7.8.3", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.8.3", + "@babel/plugin-transform-new-target": "^7.8.3", + "@babel/plugin-transform-object-super": "^7.8.3", + "@babel/plugin-transform-parameters": "^7.8.3", + "@babel/plugin-transform-property-literals": "^7.8.3", + "@babel/plugin-transform-regenerator": "^7.8.3", + "@babel/plugin-transform-reserved-words": "^7.8.3", + "@babel/plugin-transform-shorthand-properties": "^7.8.3", + "@babel/plugin-transform-spread": "^7.8.3", + "@babel/plugin-transform-sticky-regex": "^7.8.3", + "@babel/plugin-transform-template-literals": "^7.8.3", + "@babel/plugin-transform-typeof-symbol": "^7.8.3", + "@babel/plugin-transform-unicode-regex": "^7.8.3", + "@babel/types": "^7.8.3", + "browserslist": "^4.8.2", + "core-js-compat": "^3.6.2", + "invariant": "^2.2.2", + "levenary": "^1.1.0", + "semver": "^5.5.0" + } + }, + "@babel/preset-flow": { + "version": "7.8.3", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/plugin-transform-flow-strip-types": "^7.8.3" + } + }, + "@babel/preset-react": { + "version": "7.8.3", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/plugin-transform-react-display-name": "^7.8.3", + "@babel/plugin-transform-react-jsx": "^7.8.3", + "@babel/plugin-transform-react-jsx-self": "^7.8.3", + "@babel/plugin-transform-react-jsx-source": "^7.8.3" + } + }, + "@babel/preset-stage-0": { + "version": "7.8.3" + }, + "@babel/register": { + "version": "7.8.3", + "requires": { + "find-cache-dir": "^2.0.0", + "lodash": "^4.17.13", + "make-dir": "^2.1.0", + "pirates": "^4.0.0", + "source-map-support": "^0.5.16" + } + }, + "@babel/runtime": { + "version": "7.8.3", + "requires": { + "regenerator-runtime": "^0.13.2" + } + }, + "@babel/template": { + "version": "7.8.3", + "requires": { + "@babel/code-frame": "^7.8.3", + "@babel/parser": "^7.8.3", + "@babel/types": "^7.8.3" + } + }, + "@babel/traverse": { + "version": "7.8.3", + "requires": { + "@babel/code-frame": "^7.8.3", + "@babel/generator": "^7.8.3", + "@babel/helper-function-name": "^7.8.3", + "@babel/helper-split-export-declaration": "^7.8.3", + "@babel/parser": "^7.8.3", + "@babel/types": "^7.8.3", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.13" + } + }, + "@babel/types": { + "version": "7.8.3", + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" + } + }, + "@commitlint/cli": { + "version": "8.3.5", + "requires": { + "@commitlint/format": "^8.3.4", + "@commitlint/lint": "^8.3.5", + "@commitlint/load": "^8.3.5", + "@commitlint/read": "^8.3.4", + "babel-polyfill": "6.26.0", + "chalk": "2.4.2", + "get-stdin": "7.0.0", + "lodash": "4.17.15", + "meow": "5.0.0", + "resolve-from": "5.0.0", + "resolve-global": "1.0.0" + }, + "dependencies": { + "get-stdin": { + "version": "7.0.0" + } + } + }, + "@commitlint/config-conventional": { + "version": "8.3.4", + "requires": { + "conventional-changelog-conventionalcommits": "4.2.1" + } + }, + "@commitlint/ensure": { + "version": "8.3.4", + "requires": { + "lodash": "4.17.15" + } + }, + "@commitlint/execute-rule": { + "version": "8.3.4" + }, + "@commitlint/format": { + "version": "8.3.4", + "requires": { + "chalk": "^2.0.1" + } + }, + "@commitlint/is-ignored": { + "version": "8.3.5", + "requires": { + "semver": "6.3.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0" + } + } + }, + "@commitlint/lint": { + "version": "8.3.5", + "requires": { + "@commitlint/is-ignored": "^8.3.5", + "@commitlint/parse": "^8.3.4", + "@commitlint/rules": "^8.3.4", + "babel-runtime": "^6.23.0", + "lodash": "4.17.15" + } + }, + "@commitlint/load": { + "version": "8.3.5", + "requires": { + "@commitlint/execute-rule": "^8.3.4", + "@commitlint/resolve-extends": "^8.3.5", + "babel-runtime": "^6.23.0", + "chalk": "2.4.2", + "cosmiconfig": "^5.2.0", + "lodash": "4.17.15", + "resolve-from": "^5.0.0" + } + }, + "@commitlint/message": { + "version": "8.3.4" + }, + "@commitlint/parse": { + "version": "8.3.4", + "requires": { + "conventional-changelog-angular": "^1.3.3", + "conventional-commits-parser": "^3.0.0", + "lodash": "^4.17.11" + } + }, + "@commitlint/read": { + "version": "8.3.4", + "requires": { + "@commitlint/top-level": "^8.3.4", + "@marionebl/sander": "^0.6.0", + "babel-runtime": "^6.23.0", + "git-raw-commits": "^2.0.0" + }, + "dependencies": { + "git-raw-commits": { + "version": "2.0.3", + "requires": { + "dargs": "^4.0.1", + "lodash.template": "^4.0.2", + "meow": "^5.0.0", + "split2": "^2.0.0", + "through2": "^3.0.0" + } + }, + "readable-stream": { + "version": "3.5.0", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "string_decoder": { + "version": "1.3.0", + "requires": { + "safe-buffer": "~5.2.0" + } + }, + "through2": { + "version": "3.0.1", + "requires": { + "readable-stream": "2 || 3" + } + } + } + }, + "@commitlint/resolve-extends": { + "version": "8.3.5", + "requires": { + "import-fresh": "^3.0.0", + "lodash": "4.17.15", + "resolve-from": "^5.0.0", + "resolve-global": "^1.0.0" + } + }, + "@commitlint/rules": { + "version": "8.3.4", + "requires": { + "@commitlint/ensure": "^8.3.4", + "@commitlint/message": "^8.3.4", + "@commitlint/to-lines": "^8.3.4", + "babel-runtime": "^6.23.0" + } + }, + "@commitlint/to-lines": { + "version": "8.3.4" + }, + "@commitlint/top-level": { + "version": "8.3.4", + "requires": { + "find-up": "^4.0.0" + }, + "dependencies": { + "find-up": { + "version": "4.1.0", + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "locate-path": { + "version": "5.0.0", + "requires": { + "p-locate": "^4.1.0" + } + }, + "p-locate": { + "version": "4.1.0", + "requires": { + "p-limit": "^2.2.0" + } + }, + "path-exists": { + "version": "4.0.0" + } + } + }, + "@commitlint/travis-cli": { + "version": "8.3.5", + "requires": { + "@commitlint/cli": "^8.3.5", + "babel-runtime": "6.26.0", + "execa": "0.11.0" + }, + "dependencies": { + "execa": { + "version": "0.11.0", + "requires": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "get-stream": { + "version": "4.1.0", + "requires": { + "pump": "^3.0.0" + } + }, + "is-stream": { + "version": "1.1.0" + } + } + }, + "@hapi/accept": { + "version": "3.2.3", + "requires": { + "@hapi/boom": "7.x.x", + "@hapi/hoek": "8.x.x" + } + }, + "@hapi/address": { + "version": "2.1.4" + }, + "@hapi/ammo": { + "version": "3.1.1", + "requires": { + "@hapi/hoek": "8.x.x" + } + }, + "@hapi/b64": { + "version": "4.2.1", + "requires": { + "@hapi/hoek": "8.x.x" + } + }, + "@hapi/boom": { + "version": "7.4.11", + "requires": { + "@hapi/hoek": "8.x.x" + } + }, + "@hapi/bounce": { + "version": "1.3.2", + "requires": { + "@hapi/boom": "7.x.x", + "@hapi/hoek": "^8.3.1" + } + }, + "@hapi/bourne": { + "version": "1.3.2" + }, + "@hapi/call": { + "version": "5.1.2", + "requires": { + "@hapi/boom": "7.x.x", + "@hapi/hoek": "8.x.x" + } + }, + "@hapi/catbox": { + "version": "10.2.3", + "requires": { + "@hapi/boom": "7.x.x", + "@hapi/hoek": "8.x.x", + "@hapi/joi": "16.x.x", + "@hapi/podium": "3.x.x" + } + }, + "@hapi/catbox-memory": { + "version": "4.1.1", + "requires": { + "@hapi/boom": "7.x.x", + "@hapi/hoek": "8.x.x" + } + }, + "@hapi/content": { + "version": "4.1.0", + "requires": { + "@hapi/boom": "7.x.x" + } + }, + "@hapi/cryptiles": { + "version": "4.2.1", + "requires": { + "@hapi/boom": "7.x.x" + } + }, + "@hapi/file": { + "version": "1.0.0" + }, + "@hapi/formula": { + "version": "1.2.0" + }, + "@hapi/hapi": { + "version": "18.4.0", + "requires": { + "@hapi/accept": "3.x.x", + "@hapi/ammo": "3.x.x", + "@hapi/boom": "7.x.x", + "@hapi/bounce": "1.x.x", + "@hapi/call": "5.x.x", + "@hapi/catbox": "10.x.x", + "@hapi/catbox-memory": "4.x.x", + "@hapi/heavy": "6.x.x", + "@hapi/hoek": "8.x.x", + "@hapi/joi": "15.x.x", + "@hapi/mimos": "4.x.x", + "@hapi/podium": "3.x.x", + "@hapi/shot": "4.x.x", + "@hapi/somever": "2.x.x", + "@hapi/statehood": "6.x.x", + "@hapi/subtext": "6.x.x", + "@hapi/teamwork": "3.x.x", + "@hapi/topo": "3.x.x" + }, + "dependencies": { + "@hapi/joi": { + "version": "15.1.1", + "requires": { + "@hapi/address": "2.x.x", + "@hapi/bourne": "1.x.x", + "@hapi/hoek": "8.x.x", + "@hapi/topo": "3.x.x" + } + } + } + }, + "@hapi/heavy": { + "version": "6.2.2", + "requires": { + "@hapi/boom": "7.x.x", + "@hapi/hoek": "8.x.x", + "@hapi/joi": "16.x.x" + } + }, + "@hapi/hoek": { + "version": "8.5.0" + }, + "@hapi/inert": { + "version": "5.2.2", + "requires": { + "@hapi/ammo": "3.x.x", + "@hapi/boom": "7.x.x", + "@hapi/bounce": "1.x.x", + "@hapi/hoek": "8.x.x", + "@hapi/joi": "16.x.x", + "lru-cache": "4.1.x" + } + }, + "@hapi/iron": { + "version": "5.1.4", + "requires": { + "@hapi/b64": "4.x.x", + "@hapi/boom": "7.x.x", + "@hapi/bourne": "1.x.x", + "@hapi/cryptiles": "4.x.x", + "@hapi/hoek": "8.x.x" + } + }, + "@hapi/joi": { + "version": "16.1.8", + "requires": { + "@hapi/address": "^2.1.2", + "@hapi/formula": "^1.2.0", + "@hapi/hoek": "^8.2.4", + "@hapi/pinpoint": "^1.0.2", + "@hapi/topo": "^3.1.3" + } + }, + "@hapi/mimos": { + "version": "4.1.1", + "requires": { + "@hapi/hoek": "8.x.x", + "mime-db": "1.x.x" + } + }, + "@hapi/nigel": { + "version": "3.1.1", + "requires": { + "@hapi/hoek": "8.x.x", + "@hapi/vise": "3.x.x" + } + }, + "@hapi/pez": { + "version": "4.1.1", + "requires": { + "@hapi/b64": "4.x.x", + "@hapi/boom": "7.x.x", + "@hapi/content": "4.x.x", + "@hapi/hoek": "8.x.x", + "@hapi/nigel": "3.x.x" + } + }, + "@hapi/pinpoint": { + "version": "1.0.2" + }, + "@hapi/podium": { + "version": "3.4.3", + "requires": { + "@hapi/hoek": "8.x.x", + "@hapi/joi": "16.x.x" + } + }, + "@hapi/shot": { + "version": "4.1.2", + "requires": { + "@hapi/hoek": "8.x.x", + "@hapi/joi": "16.x.x" + } + }, + "@hapi/somever": { + "version": "2.1.1", + "requires": { + "@hapi/bounce": "1.x.x", + "@hapi/hoek": "8.x.x" + } + }, + "@hapi/statehood": { + "version": "6.1.2", + "requires": { + "@hapi/boom": "7.x.x", + "@hapi/bounce": "1.x.x", + "@hapi/bourne": "1.x.x", + "@hapi/cryptiles": "4.x.x", + "@hapi/hoek": "8.x.x", + "@hapi/iron": "5.x.x", + "@hapi/joi": "16.x.x" + } + }, + "@hapi/subtext": { + "version": "6.1.2", + "requires": { + "@hapi/boom": "7.x.x", + "@hapi/bourne": "1.x.x", + "@hapi/content": "4.x.x", + "@hapi/file": "1.x.x", + "@hapi/hoek": "8.x.x", + "@hapi/pez": "4.x.x", + "@hapi/wreck": "15.x.x" + } + }, + "@hapi/teamwork": { + "version": "3.3.1" + }, + "@hapi/topo": { + "version": "3.1.6", + "requires": { + "@hapi/hoek": "^8.3.0" + } + }, + "@hapi/vise": { + "version": "3.1.1", + "requires": { + "@hapi/hoek": "8.x.x" + } + }, + "@hapi/wreck": { + "version": "15.1.0", + "requires": { + "@hapi/boom": "7.x.x", + "@hapi/bourne": "1.x.x", + "@hapi/hoek": "8.x.x" + } + }, + "@marionebl/sander": { + "version": "0.6.1", + "requires": { + "graceful-fs": "^4.1.3", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.2" + } + }, + "@nodelib/fs.scandir": { + "version": "2.1.3", + "requires": { + "@nodelib/fs.stat": "2.0.3", + "run-parallel": "^1.1.9" + } + }, + "@nodelib/fs.stat": { + "version": "2.0.3" + }, + "@nodelib/fs.walk": { + "version": "1.2.4", + "requires": { + "@nodelib/fs.scandir": "2.1.3", + "fastq": "^1.6.0" + } + }, + "@protobufjs/utf8": { + "version": "1.1.0" + }, + "@samverschueren/stream-to-observable": { + "version": "0.3.0", + "requires": { + "any-observable": "^0.3.0" + } + }, + "@sindresorhus/is": { + "version": "0.7.0" + }, + "@sinonjs/commons": { + "version": "1.7.0", + "requires": { + "type-detect": "4.0.8" + } + }, + "@sinonjs/formatio": { + "version": "3.2.2", + "requires": { + "@sinonjs/commons": "^1", + "@sinonjs/samsam": "^3.1.0" + } + }, + "@sinonjs/samsam": { + "version": "3.3.3", + "requires": { + "@sinonjs/commons": "^1.3.0", + "array-from": "^2.1.1", + "lodash": "^4.17.15" + } + }, + "@sinonjs/text-encoding": { + "version": "0.7.1" + }, + "@szmarczak/http-timer": { + "version": "1.1.2", + "requires": { + "defer-to-connect": "^1.0.1" + } + }, + "@types/bn.js": { + "version": "4.11.6", + "requires": { + "@types/node": "*" + } + }, + "@types/color-name": { + "version": "1.1.1" + }, + "@types/events": { + "version": "3.0.0" + }, + "@types/glob": { + "version": "7.1.1", + "requires": { + "@types/events": "*", + "@types/minimatch": "*", + "@types/node": "*" + } + }, + "@types/minimatch": { + "version": "3.0.3" + }, + "@types/minimist": { + "version": "1.2.0" + }, + "@types/node": { + "version": "13.1.8" + }, + "@types/normalize-package-data": { + "version": "2.4.0" + }, + "@types/unist": { + "version": "2.0.3" + }, + "@webassemblyjs/ast": { + "version": "1.8.5", + "requires": { + "@webassemblyjs/helper-module-context": "1.8.5", + "@webassemblyjs/helper-wasm-bytecode": "1.8.5", + "@webassemblyjs/wast-parser": "1.8.5" + } + }, + "@webassemblyjs/floating-point-hex-parser": { + "version": "1.8.5" + }, + "@webassemblyjs/helper-api-error": { + "version": "1.8.5" + }, + "@webassemblyjs/helper-buffer": { + "version": "1.8.5" + }, + "@webassemblyjs/helper-code-frame": { + "version": "1.8.5", + "requires": { + "@webassemblyjs/wast-printer": "1.8.5" + } + }, + "@webassemblyjs/helper-fsm": { + "version": "1.8.5" + }, + "@webassemblyjs/helper-module-context": { + "version": "1.8.5", + "requires": { + "@webassemblyjs/ast": "1.8.5", + "mamacro": "^0.0.3" + } + }, + "@webassemblyjs/helper-wasm-bytecode": { + "version": "1.8.5" + }, + "@webassemblyjs/helper-wasm-section": { + "version": "1.8.5", + "requires": { + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/helper-buffer": "1.8.5", + "@webassemblyjs/helper-wasm-bytecode": "1.8.5", + "@webassemblyjs/wasm-gen": "1.8.5" + } + }, + "@webassemblyjs/ieee754": { + "version": "1.8.5", + "requires": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "@webassemblyjs/leb128": { + "version": "1.8.5", + "requires": { + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/utf8": { + "version": "1.8.5" + }, + "@webassemblyjs/wasm-edit": { + "version": "1.8.5", + "requires": { + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/helper-buffer": "1.8.5", + "@webassemblyjs/helper-wasm-bytecode": "1.8.5", + "@webassemblyjs/helper-wasm-section": "1.8.5", + "@webassemblyjs/wasm-gen": "1.8.5", + "@webassemblyjs/wasm-opt": "1.8.5", + "@webassemblyjs/wasm-parser": "1.8.5", + "@webassemblyjs/wast-printer": "1.8.5" + } + }, + "@webassemblyjs/wasm-gen": { + "version": "1.8.5", + "requires": { + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/helper-wasm-bytecode": "1.8.5", + "@webassemblyjs/ieee754": "1.8.5", + "@webassemblyjs/leb128": "1.8.5", + "@webassemblyjs/utf8": "1.8.5" + } + }, + "@webassemblyjs/wasm-opt": { + "version": "1.8.5", + "requires": { + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/helper-buffer": "1.8.5", + "@webassemblyjs/wasm-gen": "1.8.5", + "@webassemblyjs/wasm-parser": "1.8.5" + } + }, + "@webassemblyjs/wasm-parser": { + "version": "1.8.5", + "requires": { + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/helper-api-error": "1.8.5", + "@webassemblyjs/helper-wasm-bytecode": "1.8.5", + "@webassemblyjs/ieee754": "1.8.5", + "@webassemblyjs/leb128": "1.8.5", + "@webassemblyjs/utf8": "1.8.5" + } + }, + "@webassemblyjs/wast-parser": { + "version": "1.8.5", + "requires": { + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/floating-point-hex-parser": "1.8.5", + "@webassemblyjs/helper-api-error": "1.8.5", + "@webassemblyjs/helper-code-frame": "1.8.5", + "@webassemblyjs/helper-fsm": "1.8.5", + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/wast-printer": { + "version": "1.8.5", + "requires": { + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/wast-parser": "1.8.5", + "@xtuc/long": "4.2.2" + } + }, + "@xtuc/ieee754": { + "version": "1.2.0" + }, + "@xtuc/long": { + "version": "4.2.2" + }, + "JSONStream": { + "version": "1.3.5", + "requires": { + "jsonparse": "^1.2.0", + "through": ">=2.2.7 <3" + } + }, + "abbrev": { + "version": "1.1.1" + }, + "abort-controller": { + "version": "3.0.0", + "requires": { + "event-target-shim": "^5.0.0" + } + }, + "abstract-leveldown": { + "version": "5.0.0", + "requires": { + "xtend": "~4.0.0" + } + }, + "abstract-logging": { + "version": "1.0.0" + }, + "accepts": { + "version": "1.3.7", + "requires": { + "mime-types": "~2.1.24", + "negotiator": "0.6.2" + } + }, + "acorn": { + "version": "7.1.0" + }, + "acorn-jsx": { + "version": "5.1.0" + }, + "acorn-node": { + "version": "1.8.2", + "requires": { + "acorn": "^7.0.0", + "acorn-walk": "^7.0.0", + "xtend": "^4.0.2" + }, + "dependencies": { + "acorn-walk": { + "version": "7.0.0" + } + } + }, + "acorn-walk": { + "version": "6.2.0" + }, + "add-stream": { + "version": "1.0.0" + }, + "aegir": { + "version": "20.5.1", + "requires": { + "@babel/cli": "^7.7.5", + "@babel/core": "^7.7.5", + "@babel/plugin-transform-regenerator": "^7.7.5", + "@babel/plugin-transform-runtime": "^7.7.6", + "@babel/preset-env": "^7.7.6", + "@babel/register": "^7.7.4", + "@babel/runtime": "^7.7.6", + "@commitlint/cli": "^8.0.0", + "@commitlint/config-conventional": "^8.0.0", + "@commitlint/lint": "^8.0.0", + "@commitlint/load": "^8.0.0", + "@commitlint/read": "^8.0.0", + "@commitlint/travis-cli": "^8.0.0", + "@hapi/joi": "^15.1.0", + "arrify": "^2.0.1", + "async": "^2.6.1", + "babel-loader": "^8.0.5", + "babel-plugin-transform-flow-comments": "^6.22.0", + "browserify-zlib": "~0.2.0", + "bundlesize": "~0.18.0", + "chalk": "^3.0.0", + "codecov": "^3.3.0", + "conventional-changelog": "^3.1.15", + "conventional-github-releaser": "^3.1.3", + "del": "^5.1.0", + "dependency-check": "^4.1.0", + "detect-node": "^2.0.4", + "documentation": "^12.1.4", + "electron": "^6.0.9", + "electron-mocha": "^8.1.2", + "es6-promisify": "^6.0.2", + "eslint": "^6.3.0", + "eslint-config-standard": "^14.1.0", + "eslint-plugin-import": "^2.19.1", + "eslint-plugin-no-only-tests": "^2.4.0", + "eslint-plugin-node": "^10.0.0", + "eslint-plugin-promise": "^4.2.1", + "eslint-plugin-standard": "^4.0.1", + "execa": "^1.0.0", + "filesize": "^6.0.1", + "findup-sync": "^4.0.0", + "fs-extra": "^8.1.0", + "gh-pages": "^2.1.1", + "git-validate": "^2.2.4", + "globby": "^10.0.1", + "it-glob": "~0.0.5", + "json-loader": "~0.5.7", + "karma": "^4.4.1", + "karma-chrome-launcher": "^3.1.0", + "karma-cli": "^2.0.0", + "karma-edge-launcher": "~0.4.2", + "karma-firefox-launcher": "^1.2.0", + "karma-junit-reporter": "^2.0.1", + "karma-mocha": "^1.3.0", + "karma-mocha-reporter": "^2.2.5", + "karma-mocha-webworker": "^1.3.0", + "karma-sourcemap-loader": "~0.3.7", + "karma-webpack": "4.0.2", + "listr": "~0.14.2", + "listr-verbose-renderer": "~0.6.0", + "lodash": "^4.17.14", + "mocha": "^6.2.2", + "npm-package-json-lint": "^4.4.0", + "npm-which": "^3.0.1", + "nyc": "^14.1.0", + "p-map": "^3.0.0", + "pify": "^4.0.1", + "pretty-hrtime": "^1.0.3", + "prompt-promise": "^1.0.3", + "read-pkg-up": "^7.0.1", + "resolve-bin": "~0.4.0", + "rimraf": "^3.0.0", + "semver": "^6.3.0", + "simple-git": "^1.128.0", + "stats-webpack-plugin": "~0.7.0", + "stream-array": "^1.1.2", + "stream-http": "^3.1.0", + "terser-webpack-plugin": "^2.2.3", + "through": "^2.3.8", + "transform-loader": "~0.2.4", + "update-notifier": "^3.0.1", + "vinyl-fs": "^3.0.3", + "webpack": "^4.41.2", + "webpack-bundle-analyzer": "^3.6.0", + "webpack-cli": "^3.3.10", + "webpack-merge": "^4.2.2", + "yargs": "^15.0.2", + "yargs-parser": "^16.1.0" + }, + "dependencies": { + "@hapi/joi": { + "version": "15.1.1", + "requires": { + "@hapi/address": "2.x.x", + "@hapi/bourne": "1.x.x", + "@hapi/hoek": "8.x.x", + "@hapi/topo": "3.x.x" + } + }, + "ansi-regex": { + "version": "5.0.0" + }, + "ansi-styles": { + "version": "4.2.1", + "requires": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + } + }, + "arrify": { + "version": "2.0.1" + }, + "async": { + "version": "2.6.3", + "requires": { + "lodash": "^4.17.14" + } + }, + "chalk": { + "version": "3.0.0", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "cliui": { + "version": "6.0.0", + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + } + }, + "color-convert": { + "version": "2.0.1", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4" + }, + "emoji-regex": { + "version": "8.0.0" + }, + "filesize": { + "version": "6.0.1" + }, + "find-up": { + "version": "4.1.0", + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "has-flag": { + "version": "4.0.0" + }, + "is-fullwidth-code-point": { + "version": "3.0.0" + }, + "locate-path": { + "version": "5.0.0", + "requires": { + "p-locate": "^4.1.0" + } + }, + "p-locate": { + "version": "4.1.0", + "requires": { + "p-limit": "^2.2.0" + } + }, + "parse-json": { + "version": "5.0.0", + "requires": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1", + "lines-and-columns": "^1.1.6" + } + }, + "path-exists": { + "version": "4.0.0" + }, + "read-pkg": { + "version": "5.2.0", + "requires": { + "@types/normalize-package-data": "^2.4.0", + "normalize-package-data": "^2.5.0", + "parse-json": "^5.0.0", + "type-fest": "^0.6.0" + }, + "dependencies": { + "type-fest": { + "version": "0.6.0" + } + } + }, + "read-pkg-up": { + "version": "7.0.1", + "requires": { + "find-up": "^4.1.0", + "read-pkg": "^5.2.0", + "type-fest": "^0.8.1" + } + }, + "rimraf": { + "version": "3.0.0", + "requires": { + "glob": "^7.1.3" + } + }, + "semver": { + "version": "6.3.0" + }, + "string-width": { + "version": "4.2.0", + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + } + }, + "strip-ansi": { + "version": "6.0.0", + "requires": { + "ansi-regex": "^5.0.0" + } + }, + "supports-color": { + "version": "7.1.0", + "requires": { + "has-flag": "^4.0.0" + } + }, + "wrap-ansi": { + "version": "6.2.0", + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, + "yargs": { + "version": "15.1.0", + "requires": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^16.1.0" + } + }, + "yargs-parser": { + "version": "16.1.0", + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } + } + }, + "after": { + "version": "0.8.2" + }, + "agent-base": { + "version": "4.3.0", + "requires": { + "es6-promisify": "^5.0.0" + }, + "dependencies": { + "es6-promisify": { + "version": "5.0.0", + "requires": { + "es6-promise": "^4.0.3" + } + } + } + }, + "aggregate-error": { + "version": "3.0.1", + "requires": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "dependencies": { + "indent-string": { + "version": "4.0.0" + } + } + }, + "ajv": { + "version": "6.11.0", + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ajv-errors": { + "version": "1.0.1" + }, + "ajv-keywords": { + "version": "3.4.1" + }, + "ansi-align": { + "version": "3.0.0", + "requires": { + "string-width": "^3.0.0" + } + }, + "ansi-colors": { + "version": "3.2.3" + }, + "ansi-escapes": { + "version": "4.3.0", + "requires": { + "type-fest": "^0.8.1" + } + }, + "ansi-html": { + "version": "0.0.7" + }, + "ansi-regex": { + "version": "2.1.1" + }, + "ansi-styles": { + "version": "3.2.1", + "requires": { + "color-convert": "^1.9.0" + } + }, + "any-observable": { + "version": "0.3.0" + }, + "anymatch": { + "version": "3.1.1", + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "append-buffer": { + "version": "1.0.2", + "requires": { + "buffer-equal": "^1.0.0" + } + }, + "append-transform": { + "version": "1.0.0", + "requires": { + "default-require-extensions": "^2.0.0" + } + }, + "aproba": { + "version": "1.2.0" + }, + "archy": { + "version": "1.0.0" + }, + "are-we-there-yet": { + "version": "1.1.5", + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "argparse": { + "version": "1.0.10", + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "args": { + "version": "5.0.1", + "requires": { + "camelcase": "5.0.0", + "chalk": "2.4.2", + "leven": "2.1.0", + "mri": "1.1.4" + }, + "dependencies": { + "camelcase": { + "version": "5.0.0" + }, + "leven": { + "version": "2.1.0" + } + } + }, + "argv": { + "version": "0.0.2" + }, + "arr-diff": { + "version": "4.0.0" + }, + "arr-flatten": { + "version": "1.1.0" + }, + "arr-union": { + "version": "3.1.0" + }, + "array-find-index": { + "version": "1.0.2" + }, + "array-flatten": { + "version": "1.1.1" + }, + "array-from": { + "version": "2.1.1" + }, + "array-ify": { + "version": "1.0.0" + }, + "array-includes": { + "version": "3.1.1", + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0", + "is-string": "^1.0.5" + } + }, + "array-shuffle": { + "version": "1.0.1" + }, + "array-union": { + "version": "2.1.0" + }, + "array-uniq": { + "version": "1.0.3" + }, + "array-unique": { + "version": "0.3.2" + }, + "array.prototype.flat": { + "version": "1.2.3", + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1" + } + }, + "arraybuffer.slice": { + "version": "0.0.7" + }, + "arrify": { + "version": "1.0.1" + }, + "asmcrypto.js": { + "version": "2.3.2" + }, + "asn1": { + "version": "0.2.4", + "requires": { + "safer-buffer": "~2.1.0" + } + }, + "asn1.js": { + "version": "5.3.0", + "requires": { + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "safer-buffer": "^2.1.0" + } + }, + "assemblyscript": { + "version": "0.6.0", + "requires": { + "@protobufjs/utf8": "^1.1.0", + "binaryen": "77.0.0-nightly.20190407", + "glob": "^7.1.3", + "long": "^4.0.0", + "opencollective-postinstall": "^2.0.0", + "source-map-support": "^0.5.11" + } + }, + "assert": { + "version": "1.5.0", + "requires": { + "object-assign": "^4.1.1", + "util": "0.10.3" + }, + "dependencies": { + "inherits": { + "version": "2.0.1" + }, + "util": { + "version": "0.10.3", + "requires": { + "inherits": "2.0.1" + } + } + } + }, + "assert-plus": { + "version": "1.0.0" + }, + "assertion-error": { + "version": "1.1.0" + }, + "assign-symbols": { + "version": "1.0.0" + }, + "astral-regex": { + "version": "1.0.0" + }, + "async": { + "version": "3.1.0" + }, + "async-each": { + "version": "1.0.3" + }, + "async-iterator-all": { + "version": "1.0.0" + }, + "async-iterator-batch": { + "version": "0.0.1" + }, + "async-iterator-first": { + "version": "1.0.0" + }, + "async-iterator-last": { + "version": "1.0.0" + }, + "async-iterator-to-pull-stream": { + "version": "1.3.0", + "requires": { + "get-iterator": "^1.0.2", + "pull-stream-to-async-iterator": "^1.0.1" + } + }, + "async-iterator-to-stream": { + "version": "1.1.0", + "requires": { + "readable-stream": "^3.0.5" + }, + "dependencies": { + "readable-stream": { + "version": "3.5.0", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "string_decoder": { + "version": "1.3.0", + "requires": { + "safe-buffer": "~5.2.0" + } + } + } + }, + "async-limiter": { + "version": "1.0.1" + }, + "asynckit": { + "version": "0.4.0" + }, + "atob": { + "version": "2.1.2" + }, + "aws-sign2": { + "version": "0.7.0" + }, + "aws4": { + "version": "1.9.1" + }, + "axios": { + "version": "0.19.1", + "requires": { + "follow-redirects": "1.5.10" + } + }, + "babel-loader": { + "version": "8.0.6", + "requires": { + "find-cache-dir": "^2.0.0", + "loader-utils": "^1.0.2", + "mkdirp": "^0.5.1", + "pify": "^4.0.1" + } + }, + "babel-plugin-dynamic-import-node": { + "version": "2.3.0", + "requires": { + "object.assign": "^4.1.0" + } + }, + "babel-plugin-syntax-flow": { + "version": "6.18.0" + }, + "babel-plugin-transform-flow-comments": { + "version": "6.22.0", + "requires": { + "babel-plugin-syntax-flow": "^6.8.0", + "babel-runtime": "^6.22.0" + } + }, + "babel-polyfill": { + "version": "6.26.0", + "requires": { + "babel-runtime": "^6.26.0", + "core-js": "^2.5.0", + "regenerator-runtime": "^0.10.5" + }, + "dependencies": { + "regenerator-runtime": { + "version": "0.10.5" + } + } + }, + "babel-runtime": { + "version": "6.26.0", + "requires": { + "core-js": "^2.4.0", + "regenerator-runtime": "^0.11.0" + }, + "dependencies": { + "regenerator-runtime": { + "version": "0.11.1" + } + } + }, + "babelify": { + "version": "10.0.0" + }, + "backo2": { + "version": "1.0.2" + }, + "bail": { + "version": "1.0.4" + }, + "balanced-match": { + "version": "1.0.0" + }, + "base": { + "version": "0.11.2", + "requires": { + "cache-base": "^1.0.1", + "class-utils": "^0.3.5", + "component-emitter": "^1.2.1", + "define-property": "^1.0.0", + "isobject": "^3.0.1", + "mixin-deep": "^1.2.0", + "pascalcase": "^0.1.1" + }, + "dependencies": { + "component-emitter": { + "version": "1.3.0" + }, + "define-property": { + "version": "1.0.0", + "requires": { + "is-descriptor": "^1.0.0" + } + } + } + }, + "base-x": { + "version": "3.0.4", + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "base32-encode": { + "version": "1.1.1" + }, + "base32.js": { + "version": "0.1.0" + }, + "base64-arraybuffer": { + "version": "0.1.5" + }, + "base64-js": { + "version": "1.3.1" + }, + "base64id": { + "version": "1.0.0" + }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "requires": { + "tweetnacl": "^0.14.3" + } + }, + "bech32": { + "version": "1.1.3" + }, + "better-assert": { + "version": "1.0.2", + "requires": { + "callsite": "1.0.0" + } + }, + "bfj": { + "version": "6.1.2", + "requires": { + "bluebird": "^3.5.5", + "check-types": "^8.0.3", + "hoopy": "^0.1.4", + "tryer": "^1.0.1" + } + }, + "big.js": { + "version": "5.2.2" + }, + "bignumber.js": { + "version": "9.0.0" + }, + "binary": { + "version": "0.3.0", + "requires": { + "buffers": "~0.1.1", + "chainsaw": "~0.1.0" + } + }, + "binary-extensions": { + "version": "2.0.0" + }, + "binary-querystring": { + "version": "0.1.2" + }, + "binaryen": { + "version": "77.0.0-nightly.20190407" + }, + "bindings": { + "version": "1.5.0", + "requires": { + "file-uri-to-path": "1.0.0" + } + }, + "bintrees": { + "version": "1.0.1" + }, + "bip174": { + "version": "1.0.1" + }, + "bip32": { + "version": "2.0.5", + "requires": { + "@types/node": "10.12.18", + "bs58check": "^2.1.1", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "tiny-secp256k1": "^1.1.3", + "typeforce": "^1.11.5", + "wif": "^2.0.6" + }, + "dependencies": { + "@types/node": { + "version": "10.12.18" + } + } + }, + "bip66": { + "version": "1.1.5", + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "bitcoin-ops": { + "version": "1.4.1" + }, + "bitcoinjs-lib": { + "version": "5.1.7", + "requires": { + "bech32": "^1.1.2", + "bip174": "^1.0.1", + "bip32": "^2.0.4", + "bip66": "^1.1.0", + "bitcoin-ops": "^1.4.0", + "bs58check": "^2.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.3", + "merkle-lib": "^2.0.10", + "pushdata-bitcoin": "^1.0.1", + "randombytes": "^2.0.1", + "tiny-secp256k1": "^1.1.1", + "typeforce": "^1.11.3", + "varuint-bitcoin": "^1.0.4", + "wif": "^2.0.1" + } + }, + "bl": { + "version": "4.0.0", + "requires": { + "readable-stream": "^3.4.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.5.0", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "string_decoder": { + "version": "1.3.0", + "requires": { + "safe-buffer": "~5.2.0" + } + } + } + }, + "blakejs": { + "version": "1.1.0" + }, + "blob": { + "version": "0.0.5" + }, + "bluebird": { + "version": "3.7.2" + }, + "bn.js": { + "version": "4.11.8" + }, + "body": { + "version": "5.1.0", + "requires": { + "continuable-cache": "^0.3.1", + "error": "^7.0.0", + "raw-body": "~1.1.0", + "safe-json-parse": "~1.0.1" + }, + "dependencies": { + "bytes": { + "version": "1.0.0" + }, + "raw-body": { + "version": "1.1.7", + "requires": { + "bytes": "1", + "string_decoder": "0.10" + } + } + } + }, + "body-parser": { + "version": "1.19.0", + "requires": { + "bytes": "3.1.0", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "on-finished": "~2.3.0", + "qs": "6.7.0", + "raw-body": "2.4.0", + "type-is": "~1.6.17" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0" + }, + "qs": { + "version": "6.7.0" + } + } + }, + "borc": { + "version": "2.1.1", + "requires": { + "bignumber.js": "^9.0.0", + "commander": "^2.15.0", + "ieee754": "^1.1.8", + "iso-url": "~0.4.4", + "json-text-sequence": "~0.1.0" + } + }, + "boxen": { + "version": "3.2.0", + "requires": { + "ansi-align": "^3.0.0", + "camelcase": "^5.3.1", + "chalk": "^2.4.2", + "cli-boxes": "^2.2.0", + "string-width": "^3.0.0", + "term-size": "^1.2.0", + "type-fest": "^0.3.0", + "widest-line": "^2.0.0" + }, + "dependencies": { + "type-fest": { + "version": "0.3.1" + } + } + }, + "brace-expansion": { + "version": "1.1.11", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "3.0.2", + "requires": { + "fill-range": "^7.0.1" + } + }, + "brorand": { + "version": "1.1.0" + }, + "brotli-size": { + "version": "0.1.0", + "requires": { + "duplexer": "^0.1.1", + "iltorb": "^2.4.3" + } + }, + "browser-process-platform": { + "version": "0.1.1" + }, + "browser-resolve": { + "version": "1.11.3", + "requires": { + "resolve": "1.1.7" + }, + "dependencies": { + "resolve": { + "version": "1.1.7" + } + } + }, + "browser-stdout": { + "version": "1.3.1" + }, + "browserify-aes": { + "version": "1.2.0", + "requires": { + "buffer-xor": "^1.0.3", + "cipher-base": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.3", + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "browserify-cipher": { + "version": "1.0.1", + "requires": { + "browserify-aes": "^1.0.4", + "browserify-des": "^1.0.0", + "evp_bytestokey": "^1.0.0" + } + }, + "browserify-des": { + "version": "1.0.2", + "requires": { + "cipher-base": "^1.0.1", + "des.js": "^1.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "browserify-rsa": { + "version": "4.0.1", + "requires": { + "bn.js": "^4.1.0", + "randombytes": "^2.0.1" + } + }, + "browserify-sign": { + "version": "4.0.4", + "requires": { + "bn.js": "^4.1.1", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.2", + "elliptic": "^6.0.0", + "inherits": "^2.0.1", + "parse-asn1": "^5.0.0" + } + }, + "browserify-zlib": { + "version": "0.2.0", + "requires": { + "pako": "~1.0.5" + } + }, + "browserslist": { + "version": "4.8.4", + "requires": { + "caniuse-lite": "^1.0.30001021", + "electron-to-chromium": "^1.3.338", + "node-releases": "^1.1.46" + } + }, + "bs58": { + "version": "4.0.1", + "requires": { + "base-x": "^3.0.2" + }, + "dependencies": { + "base-x": { + "version": "3.0.7", + "requires": { + "safe-buffer": "^5.0.1" + } + } + } + }, + "bs58check": { + "version": "2.1.2", + "requires": { + "bs58": "^4.0.0", + "create-hash": "^1.1.0", + "safe-buffer": "^5.1.2" + } + }, + "buffer": { + "version": "5.4.3", + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "buffer-alloc": { + "version": "1.2.0", + "requires": { + "buffer-alloc-unsafe": "^1.1.0", + "buffer-fill": "^1.0.0" + } + }, + "buffer-alloc-unsafe": { + "version": "1.1.0" + }, + "buffer-equal": { + "version": "1.0.0" + }, + "buffer-fill": { + "version": "1.0.0" + }, + "buffer-from": { + "version": "1.1.1" + }, + "buffer-indexof": { + "version": "1.1.1" + }, + "buffer-peek-stream": { + "version": "1.0.1" + }, + "buffer-reuse-pool": { + "version": "1.0.0" + }, + "buffer-shims": { + "version": "1.0.0" + }, + "buffer-split": { + "version": "1.0.0", + "requires": { + "buffer-indexof": "~0.0.0" + }, + "dependencies": { + "buffer-indexof": { + "version": "0.0.2" + } + } + }, + "buffer-xor": { + "version": "1.0.3" + }, + "buffers": { + "version": "0.1.1" + }, + "builtin-status-codes": { + "version": "3.0.0" + }, + "bundlesize": { + "version": "0.18.0", + "requires": { + "axios": "^0.19.0", + "brotli-size": "0.1.0", + "bytes": "^3.1.0", + "ci-env": "^1.4.0", + "commander": "^2.20.0", + "cosmiconfig": "^5.2.1", + "github-build": "^1.2.0", + "glob": "^7.1.4", + "gzip-size": "^4.0.0", + "prettycli": "^1.4.3" + } + }, + "byteman": { + "version": "1.3.5" + }, + "bytes": { + "version": "3.1.0" + }, + "cacache": { + "version": "13.0.1", + "requires": { + "chownr": "^1.1.2", + "figgy-pudding": "^3.5.1", + "fs-minipass": "^2.0.0", + "glob": "^7.1.4", + "graceful-fs": "^4.2.2", + "infer-owner": "^1.0.4", + "lru-cache": "^5.1.1", + "minipass": "^3.0.0", + "minipass-collect": "^1.0.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.2", + "mkdirp": "^0.5.1", + "move-concurrently": "^1.0.1", + "p-map": "^3.0.0", + "promise-inflight": "^1.0.1", + "rimraf": "^2.7.1", + "ssri": "^7.0.0", + "unique-filename": "^1.1.1" + }, + "dependencies": { + "lru-cache": { + "version": "5.1.1", + "requires": { + "yallist": "^3.0.2" + } + } + } + }, + "cache-base": { + "version": "1.0.1", + "requires": { + "collection-visit": "^1.0.0", + "component-emitter": "^1.2.1", + "get-value": "^2.0.6", + "has-value": "^1.0.0", + "isobject": "^3.0.1", + "set-value": "^2.0.0", + "to-object-path": "^0.3.0", + "union-value": "^1.0.0", + "unset-value": "^1.0.0" + }, + "dependencies": { + "component-emitter": { + "version": "1.3.0" + } + } + }, + "cacheable-request": { + "version": "2.1.4", + "requires": { + "clone-response": "1.0.2", + "get-stream": "3.0.0", + "http-cache-semantics": "3.8.1", + "keyv": "3.0.0", + "lowercase-keys": "1.0.0", + "normalize-url": "2.0.1", + "responselike": "1.0.2" + }, + "dependencies": { + "lowercase-keys": { + "version": "1.0.0" + }, + "normalize-url": { + "version": "2.0.1", + "requires": { + "prepend-http": "^2.0.0", + "query-string": "^5.0.1", + "sort-keys": "^2.0.0" + } + }, + "query-string": { + "version": "5.1.1", + "requires": { + "decode-uri-component": "^0.2.0", + "object-assign": "^4.1.0", + "strict-uri-encode": "^1.0.0" + } + }, + "sort-keys": { + "version": "2.0.0", + "requires": { + "is-plain-obj": "^1.0.0" + } + } + } + }, + "cached-path-relative": { + "version": "1.0.2" + }, + "caching-transform": { + "version": "3.0.2", + "requires": { + "hasha": "^3.0.0", + "make-dir": "^2.0.0", + "package-hash": "^3.0.0", + "write-file-atomic": "^2.4.2" + } + }, + "callbackify": { + "version": "1.1.0" + }, + "caller-callsite": { + "version": "2.0.0", + "requires": { + "callsites": "^2.0.0" + }, + "dependencies": { + "callsites": { + "version": "2.0.0" + } + } + }, + "caller-path": { + "version": "2.0.0", + "requires": { + "caller-callsite": "^2.0.0" + } + }, + "callsite": { + "version": "1.0.0" + }, + "callsites": { + "version": "3.1.0" + }, + "camelcase": { + "version": "5.3.1" + }, + "camelcase-keys": { + "version": "4.2.0", + "requires": { + "camelcase": "^4.1.0", + "map-obj": "^2.0.0", + "quick-lru": "^1.0.0" + }, + "dependencies": { + "camelcase": { + "version": "4.1.0" + }, + "map-obj": { + "version": "2.0.0" + } + } + }, + "caniuse-lite": { + "version": "1.0.30001022" + }, + "caseless": { + "version": "0.12.0" + }, + "ccount": { + "version": "1.0.4" + }, + "chai": { + "version": "4.2.0", + "requires": { + "assertion-error": "^1.1.0", + "check-error": "^1.0.2", + "deep-eql": "^3.0.1", + "get-func-name": "^2.0.0", + "pathval": "^1.1.0", + "type-detect": "^4.0.5" + } + }, + "chai-as-promised": { + "version": "7.1.1", + "requires": { + "check-error": "^1.0.2" + } + }, + "chai-checkmark": { + "version": "1.0.1" + }, + "chainsaw": { + "version": "0.1.0", + "requires": { + "traverse": ">=0.3.0 <0.4" + } + }, + "chalk": { + "version": "2.4.2", + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "dependencies": { + "supports-color": { + "version": "5.5.0", + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "character-entities": { + "version": "1.2.3" + }, + "character-entities-html4": { + "version": "1.1.3" + }, + "character-entities-legacy": { + "version": "1.1.3" + }, + "character-reference-invalid": { + "version": "1.1.3" + }, + "chardet": { + "version": "0.7.0" + }, + "check-error": { + "version": "1.0.2" + }, + "check-types": { + "version": "8.0.3" + }, + "chokidar": { + "version": "2.1.8", + "requires": { + "anymatch": "^2.0.0", + "async-each": "^1.0.1", + "braces": "^2.3.2", + "fsevents": "^1.2.7", + "glob-parent": "^3.1.0", + "inherits": "^2.0.3", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "normalize-path": "^3.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.2.1", + "upath": "^1.1.1" + }, + "dependencies": { + "anymatch": { + "version": "2.0.0", + "requires": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + }, + "dependencies": { + "normalize-path": { + "version": "2.1.1", + "requires": { + "remove-trailing-separator": "^1.0.1" + } + } + } + }, + "binary-extensions": { + "version": "1.13.1" + }, + "braces": { + "version": "2.3.2", + "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.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + } + }, + "fill-range": { + "version": "4.0.0", + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + } + }, + "fsevents": { + "version": "1.2.11", + "optional": true, + "requires": { + "bindings": "^1.5.0", + "nan": "^2.12.1", + "node-pre-gyp": "*" + }, + "dependencies": { + "abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "optional": true + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "optional": true + }, + "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.5", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", + "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", + "optional": true, + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "optional": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "optional": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "chownr": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.3.tgz", + "integrity": "sha512-i70fVHhmV3DtTl6nqvZOnIjbY0Pe4kAUjwHj8z0zAdgBtYrJyYwLKCCuRBQ5ppkyL0AkN7HKRnETdmdp1zqNXw==", + "optional": true + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "optional": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "optional": true + }, + "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=", + "optional": true + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "optional": true + }, + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "optional": true, + "requires": { + "ms": "^2.1.1" + } + }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "optional": true + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", + "optional": true + }, + "detect-libc": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", + "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=", + "optional": true + }, + "fs-minipass": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz", + "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==", + "optional": true, + "requires": { + "minipass": "^2.6.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "optional": true + }, + "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.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "optional": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "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 + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "optional": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ignore-walk": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.3.tgz", + "integrity": "sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw==", + "optional": true, + "requires": { + "minimatch": "^3.0.4" + } + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "optional": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "optional": true + }, + "ini": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", + "optional": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "optional": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "optional": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "optional": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "optional": true + }, + "minipass": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", + "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", + "optional": true, + "requires": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + } + }, + "minizlib": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz", + "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==", + "optional": true, + "requires": { + "minipass": "^2.9.0" + } + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "optional": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "optional": true + }, + "needle": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/needle/-/needle-2.4.0.tgz", + "integrity": "sha512-4Hnwzr3mi5L97hMYeNl8wRW/Onhy4nUKR/lVemJ8gJedxxUyBLm9kkrDColJvoSfwi0jCNhD+xCdOtiGDQiRZg==", + "optional": true, + "requires": { + "debug": "^3.2.6", + "iconv-lite": "^0.4.4", + "sax": "^1.2.4" + } + }, + "node-pre-gyp": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.14.0.tgz", + "integrity": "sha512-+CvDC7ZttU/sSt9rFjix/P05iS43qHCOOGzcr3Ry99bXG7VX953+vFyEuph/tfqoYu8dttBkE86JSKBO2OzcxA==", + "optional": true, + "requires": { + "detect-libc": "^1.0.2", + "mkdirp": "^0.5.1", + "needle": "^2.2.1", + "nopt": "^4.0.1", + "npm-packlist": "^1.1.6", + "npmlog": "^4.0.2", + "rc": "^1.2.7", + "rimraf": "^2.6.1", + "semver": "^5.3.0", + "tar": "^4.4.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", + "osenv": "^0.1.4" + } + }, + "npm-bundled": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.1.1.tgz", + "integrity": "sha512-gqkfgGePhTpAEgUsGEgcq1rqPXA+tv/aVBlgEzfXwA1yiUJF7xtEt3CtVwOjNYQOVknDk0F20w58Fnm3EtG0fA==", + "optional": true, + "requires": { + "npm-normalize-package-bin": "^1.0.1" + } + }, + "npm-normalize-package-bin": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz", + "integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==", + "optional": true + }, + "npm-packlist": { + "version": "1.4.7", + "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.4.7.tgz", + "integrity": "sha512-vAj7dIkp5NhieaGZxBJB8fF4R0078rqsmhJcAfXZ6O7JJhjhPK96n5Ry1oZcfLXgfun0GWTZPOxaEyqv8GBykQ==", + "optional": true, + "requires": { + "ignore-walk": "^3.0.1", + "npm-bundled": "^1.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.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "optional": true + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "optional": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "optional": true, + "requires": { + "wrappy": "1" + } + }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "optional": true + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "optional": true + }, + "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.0", + "os-tmpdir": "^1.0.0" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "optional": true + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "optional": true + }, + "rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "optional": true, + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "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 + } + } + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "optional": true, + "requires": { + "core-util-is": "~1.0.0", + "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.1" + } + }, + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "optional": true, + "requires": { + "glob": "^7.1.3" + } + }, + "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==", + "optional": true + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "optional": true + }, + "sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", + "optional": true + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "optional": true + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "optional": true + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "optional": true + }, + "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.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "optional": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "optional": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "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=", + "optional": true + }, + "tar": { + "version": "4.4.13", + "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.13.tgz", + "integrity": "sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA==", + "optional": true, + "requires": { + "chownr": "^1.1.1", + "fs-minipass": "^1.2.5", + "minipass": "^2.8.6", + "minizlib": "^1.2.1", + "mkdirp": "^0.5.0", + "safe-buffer": "^5.1.2", + "yallist": "^3.0.3" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "optional": true + }, + "wide-align": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", + "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "optional": true, + "requires": { + "string-width": "^1.0.2 || 2" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "optional": true + }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "optional": true + } + } + }, + "glob-parent": { + "version": "3.1.0", + "requires": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "requires": { + "is-extglob": "^2.1.0" + } + } + } + }, + "is-binary-path": { + "version": "1.0.1", + "requires": { + "binary-extensions": "^1.0.0" + } + }, + "to-regex-range": { + "version": "2.1.1", + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } + } + } + }, + "chownr": { + "version": "1.1.3" + }, + "chrome-trace-event": { + "version": "1.0.2", + "requires": { + "tslib": "^1.9.0" + } + }, + "ci-env": { + "version": "1.12.0" + }, + "ci-info": { + "version": "2.0.0" + }, + "cid-tool": { + "version": "0.4.0", + "requires": { + "cids": "~0.7.0", + "explain-error": "^1.0.4", + "multibase": "~0.6.0", + "multihashes": "~0.4.14", + "split2": "^3.1.1", + "yargs": "^15.0.2" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.0" + }, + "ansi-styles": { + "version": "4.2.1", + "requires": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + } + }, + "cliui": { + "version": "6.0.0", + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + } + }, + "color-convert": { + "version": "2.0.1", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4" + }, + "emoji-regex": { + "version": "8.0.0" + }, + "find-up": { + "version": "4.1.0", + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "is-fullwidth-code-point": { + "version": "3.0.0" + }, + "locate-path": { + "version": "5.0.0", + "requires": { + "p-locate": "^4.1.0" + } + }, + "p-locate": { + "version": "4.1.0", + "requires": { + "p-limit": "^2.2.0" + } + }, + "path-exists": { + "version": "4.0.0" + }, + "readable-stream": { + "version": "3.5.0", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "split2": { + "version": "3.1.1", + "requires": { + "readable-stream": "^3.0.0" + } + }, + "string-width": { + "version": "4.2.0", + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + } + }, + "string_decoder": { + "version": "1.3.0", + "requires": { + "safe-buffer": "~5.2.0" + } + }, + "strip-ansi": { + "version": "6.0.0", + "requires": { + "ansi-regex": "^5.0.0" + } + }, + "wrap-ansi": { + "version": "6.2.0", + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, + "yargs": { + "version": "15.1.0", + "requires": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^16.1.0" + } + }, + "yargs-parser": { + "version": "16.1.0", + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } + } + }, + "cids": { + "version": "0.7.2", + "requires": { + "class-is": "^1.1.0", + "multibase": "~0.6.0", + "multicodec": "^1.0.0", + "multihashes": "~0.4.15" + } + }, + "cipher-base": { + "version": "1.0.4", + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "class-is": { + "version": "1.1.0" + }, + "class-utils": { + "version": "0.3.6", + "requires": { + "arr-union": "^3.1.0", + "define-property": "^0.2.5", + "isobject": "^3.0.0", + "static-extend": "^0.1.1" + } + }, + "clean-stack": { + "version": "2.2.0" + }, + "cli-boxes": { + "version": "2.2.0" + }, + "cli-cursor": { + "version": "2.1.0", + "requires": { + "restore-cursor": "^2.0.0" + } + }, + "cli-truncate": { + "version": "0.2.1", + "requires": { + "slice-ansi": "0.0.4", + "string-width": "^1.0.1" + }, + "dependencies": { + "is-fullwidth-code-point": { + "version": "1.0.0", + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "slice-ansi": { + "version": "0.0.4" + }, + "string-width": { + "version": "1.0.2", + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + } + } + }, + "cli-width": { + "version": "2.2.0" + }, + "cliui": { + "version": "5.0.0", + "requires": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0" + }, + "strip-ansi": { + "version": "5.2.0", + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "clone": { + "version": "2.1.2" + }, + "clone-buffer": { + "version": "1.0.0" + }, + "clone-deep": { + "version": "4.0.1", + "requires": { + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" + } + }, + "clone-response": { + "version": "1.0.2", + "requires": { + "mimic-response": "^1.0.0" + } + }, + "clone-stats": { + "version": "1.0.0" + }, + "cloneable-readable": { + "version": "1.1.3", + "requires": { + "inherits": "^2.0.1", + "process-nextick-args": "^2.0.0", + "readable-stream": "^2.3.5" + }, + "dependencies": { + "process-nextick-args": { + "version": "2.0.1" + } + } + }, + "code-point-at": { + "version": "1.1.0" + }, + "codecov": { + "version": "3.6.1", + "requires": { + "argv": "^0.0.2", + "ignore-walk": "^3.0.1", + "js-yaml": "^3.13.1", + "teeny-request": "^3.11.3", + "urlgrey": "^0.4.4" + } + }, + "collapse-white-space": { + "version": "1.0.5" + }, + "collection-visit": { + "version": "1.0.0", + "requires": { + "map-visit": "^1.0.0", + "object-visit": "^1.0.0" + } + }, + "color-convert": { + "version": "1.9.3", + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3" + }, + "colors": { + "version": "1.4.0" + }, + "combined-stream": { + "version": "1.0.8", + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "comma-separated-tokens": { + "version": "1.0.7" + }, + "commander": { + "version": "2.20.3" + }, + "commondir": { + "version": "1.0.1" + }, + "compare-func": { + "version": "1.3.2", + "requires": { + "array-ify": "^1.0.0", + "dot-prop": "^3.0.0" + } + }, + "component-bind": { + "version": "1.0.0" + }, + "component-emitter": { + "version": "1.2.1" + }, + "component-inherit": { + "version": "0.0.3" + }, + "concat-map": { + "version": "0.0.1" + }, + "concat-stream": { + "version": "1.6.2", + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "configstore": { + "version": "4.0.0", + "requires": { + "dot-prop": "^4.1.0", + "graceful-fs": "^4.1.2", + "make-dir": "^1.0.0", + "unique-string": "^1.0.0", + "write-file-atomic": "^2.0.0", + "xdg-basedir": "^3.0.0" + }, + "dependencies": { + "dot-prop": { + "version": "4.2.0", + "requires": { + "is-obj": "^1.0.0" + } + }, + "make-dir": { + "version": "1.3.0", + "requires": { + "pify": "^3.0.0" + } + }, + "pify": { + "version": "3.0.0" + } + } + }, + "connect": { + "version": "3.7.0", + "requires": { + "debug": "2.6.9", + "finalhandler": "1.1.2", + "parseurl": "~1.3.3", + "utils-merge": "1.0.1" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0" + } + } + }, + "console-browserify": { + "version": "1.2.0" + }, + "console-control-strings": { + "version": "1.1.0" + }, + "constants-browserify": { + "version": "1.0.0" + }, + "contains-path": { + "version": "0.1.0" + }, + "content-disposition": { + "version": "0.5.3", + "requires": { + "safe-buffer": "5.1.2" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2" + } + } + }, + "content-type": { + "version": "1.0.4" + }, + "continuable-cache": { + "version": "0.3.1" + }, + "conventional-changelog": { + "version": "3.1.18", + "requires": { + "conventional-changelog-angular": "^5.0.6", + "conventional-changelog-atom": "^2.0.3", + "conventional-changelog-codemirror": "^2.0.3", + "conventional-changelog-conventionalcommits": "^4.2.3", + "conventional-changelog-core": "^4.1.4", + "conventional-changelog-ember": "^2.0.4", + "conventional-changelog-eslint": "^3.0.4", + "conventional-changelog-express": "^2.0.1", + "conventional-changelog-jquery": "^3.0.6", + "conventional-changelog-jshint": "^2.0.3", + "conventional-changelog-preset-loader": "^2.3.0" + }, + "dependencies": { + "conventional-changelog-angular": { + "version": "5.0.6", + "requires": { + "compare-func": "^1.3.1", + "q": "^1.5.1" + } + }, + "conventional-changelog-conventionalcommits": { + "version": "4.2.3", + "requires": { + "compare-func": "^1.3.1", + "lodash": "^4.17.15", + "q": "^1.5.1" + } + } + } + }, + "conventional-changelog-angular": { + "version": "1.6.6", + "requires": { + "compare-func": "^1.3.1", + "q": "^1.5.1" + } + }, + "conventional-changelog-atom": { + "version": "2.0.3", + "requires": { + "q": "^1.5.1" + } + }, + "conventional-changelog-codemirror": { + "version": "2.0.3", + "requires": { + "q": "^1.5.1" + } + }, + "conventional-changelog-conventionalcommits": { + "version": "4.2.1", + "requires": { + "compare-func": "^1.3.1", + "lodash": "^4.2.1", + "q": "^1.5.1" + } + }, + "conventional-changelog-core": { + "version": "4.1.4", + "requires": { + "add-stream": "^1.0.0", + "conventional-changelog-writer": "^4.0.11", + "conventional-commits-parser": "^3.0.8", + "dateformat": "^3.0.0", + "get-pkg-repo": "^1.0.0", + "git-raw-commits": "2.0.0", + "git-remote-origin-url": "^2.0.0", + "git-semver-tags": "^3.0.1", + "lodash": "^4.17.15", + "normalize-package-data": "^2.3.5", + "q": "^1.5.1", + "read-pkg": "^3.0.0", + "read-pkg-up": "^3.0.0", + "through2": "^3.0.0" + }, + "dependencies": { + "git-semver-tags": { + "version": "3.0.1", + "requires": { + "meow": "^5.0.0", + "semver": "^6.0.0" + } + }, + "readable-stream": { + "version": "3.5.0", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "semver": { + "version": "6.3.0" + }, + "string_decoder": { + "version": "1.3.0", + "requires": { + "safe-buffer": "~5.2.0" + } + }, + "through2": { + "version": "3.0.1", + "requires": { + "readable-stream": "2 || 3" + } + } + } + }, + "conventional-changelog-ember": { + "version": "2.0.4", + "requires": { + "q": "^1.5.1" + } + }, + "conventional-changelog-eslint": { + "version": "3.0.4", + "requires": { + "q": "^1.5.1" + } + }, + "conventional-changelog-express": { + "version": "2.0.1", + "requires": { + "q": "^1.5.1" + } + }, + "conventional-changelog-jquery": { + "version": "3.0.6", + "requires": { + "q": "^1.5.1" + } + }, + "conventional-changelog-jscs": { + "version": "0.1.0", + "requires": { + "q": "^1.4.1" + } + }, + "conventional-changelog-jshint": { + "version": "2.0.3", + "requires": { + "compare-func": "^1.3.1", + "q": "^1.5.1" + } + }, + "conventional-changelog-preset-loader": { + "version": "2.3.0" + }, + "conventional-changelog-writer": { + "version": "4.0.11", + "requires": { + "compare-func": "^1.3.1", + "conventional-commits-filter": "^2.0.2", + "dateformat": "^3.0.0", + "handlebars": "^4.4.0", + "json-stringify-safe": "^5.0.1", + "lodash": "^4.17.15", + "meow": "^5.0.0", + "semver": "^6.0.0", + "split": "^1.0.0", + "through2": "^3.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.5.0", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "semver": { + "version": "6.3.0" + }, + "string_decoder": { + "version": "1.3.0", + "requires": { + "safe-buffer": "~5.2.0" + } + }, + "through2": { + "version": "3.0.1", + "requires": { + "readable-stream": "2 || 3" + } + } + } + }, + "conventional-commits-filter": { + "version": "2.0.2", + "requires": { + "lodash.ismatch": "^4.4.0", + "modify-values": "^1.0.0" + } + }, + "conventional-commits-parser": { + "version": "3.0.8", + "requires": { + "JSONStream": "^1.0.4", + "is-text-path": "^1.0.1", + "lodash": "^4.17.15", + "meow": "^5.0.0", + "split2": "^2.0.0", + "through2": "^3.0.0", + "trim-off-newlines": "^1.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.5.0", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "string_decoder": { + "version": "1.3.0", + "requires": { + "safe-buffer": "~5.2.0" + } + }, + "through2": { + "version": "3.0.1", + "requires": { + "readable-stream": "2 || 3" + } + } + } + }, + "conventional-github-releaser": { + "version": "3.1.3", + "requires": { + "conventional-changelog": "^2.0.0", + "dateformat": "^3.0.0", + "debug": "^3.1.0", + "gh-got": "^7.0.0", + "git-semver-tags": "^2.0.0", + "lodash.merge": "^4.0.2", + "meow": "^5.0.0", + "object-assign": "^4.0.1", + "q": "^1.4.1", + "semver": "^5.0.1", + "semver-regex": "^2.0.0", + "through2": "^2.0.0" + }, + "dependencies": { + "conventional-changelog": { + "version": "2.0.3", + "requires": { + "conventional-changelog-angular": "^1.6.6", + "conventional-changelog-atom": "^2.0.0", + "conventional-changelog-codemirror": "^2.0.0", + "conventional-changelog-core": "^3.1.0", + "conventional-changelog-ember": "^2.0.1", + "conventional-changelog-eslint": "^3.0.0", + "conventional-changelog-express": "^2.0.0", + "conventional-changelog-jquery": "^0.1.0", + "conventional-changelog-jscs": "^0.1.0", + "conventional-changelog-jshint": "^2.0.0", + "conventional-changelog-preset-loader": "^2.0.1" + } + }, + "conventional-changelog-core": { + "version": "3.2.3", + "requires": { + "conventional-changelog-writer": "^4.0.6", + "conventional-commits-parser": "^3.0.3", + "dateformat": "^3.0.0", + "get-pkg-repo": "^1.0.0", + "git-raw-commits": "2.0.0", + "git-remote-origin-url": "^2.0.0", + "git-semver-tags": "^2.0.3", + "lodash": "^4.2.1", + "normalize-package-data": "^2.3.5", + "q": "^1.5.1", + "read-pkg": "^3.0.0", + "read-pkg-up": "^3.0.0", + "through2": "^3.0.0" + }, + "dependencies": { + "through2": { + "version": "3.0.1", + "requires": { + "readable-stream": "2 || 3" + } + } + } + }, + "conventional-changelog-jquery": { + "version": "0.1.0", + "requires": { + "q": "^1.4.1" + } + }, + "debug": { + "version": "3.2.6", + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.2" + }, + "readable-stream": { + "version": "3.5.0", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "string_decoder": { + "version": "1.3.0", + "requires": { + "safe-buffer": "~5.2.0" + } + } + } + }, + "convert-source-map": { + "version": "1.7.0", + "requires": { + "safe-buffer": "~5.1.1" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2" + } + } + }, + "cookie": { + "version": "0.3.1" + }, + "cookie-signature": { + "version": "1.0.6" + }, + "copy-concurrently": { + "version": "1.0.5", + "requires": { + "aproba": "^1.1.1", + "fs-write-stream-atomic": "^1.0.8", + "iferr": "^0.1.5", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.0" + } + }, + "copy-descriptor": { + "version": "0.1.1" + }, + "core-js": { + "version": "2.6.11" + }, + "core-js-compat": { + "version": "3.6.4", + "requires": { + "browserslist": "^4.8.3", + "semver": "7.0.0" + }, + "dependencies": { + "semver": { + "version": "7.0.0" + } + } + }, + "core-util-is": { + "version": "1.0.2" + }, + "cosmiconfig": { + "version": "5.2.1", + "requires": { + "import-fresh": "^2.0.0", + "is-directory": "^0.3.1", + "js-yaml": "^3.13.1", + "parse-json": "^4.0.0" + }, + "dependencies": { + "import-fresh": { + "version": "2.0.0", + "requires": { + "caller-path": "^2.0.0", + "resolve-from": "^3.0.0" + } + }, + "resolve-from": { + "version": "3.0.0" + } + } + }, + "cp-file": { + "version": "6.2.0", + "requires": { + "graceful-fs": "^4.1.2", + "make-dir": "^2.0.0", + "nested-error-stacks": "^2.0.0", + "pify": "^4.0.1", + "safe-buffer": "^5.0.1" + } + }, + "create-ecdh": { + "version": "4.0.3", + "requires": { + "bn.js": "^4.1.0", + "elliptic": "^6.0.0" + } + }, + "create-hash": { + "version": "1.2.0", + "requires": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" + } + }, + "create-hmac": { + "version": "1.1.7", + "requires": { + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "cross-spawn": { + "version": "6.0.5", + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "crypto-browserify": { + "version": "3.12.0", + "requires": { + "browserify-cipher": "^1.0.0", + "browserify-sign": "^4.0.0", + "create-ecdh": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.0", + "diffie-hellman": "^5.0.0", + "inherits": "^2.0.1", + "pbkdf2": "^3.0.3", + "public-encrypt": "^4.0.0", + "randombytes": "^2.0.0", + "randomfill": "^1.0.3" + } + }, + "crypto-random-string": { + "version": "1.0.0" + }, + "currently-unhandled": { + "version": "0.4.1", + "requires": { + "array-find-index": "^1.0.1" + } + }, + "custom-event": { + "version": "1.0.1" + }, + "cyclist": { + "version": "1.0.1" + }, + "dag-cbor-links": { + "version": "1.3.2", + "requires": { + "cids": "^0.7.1", + "dag-cbor-sync": "^0.6.2" + } + }, + "dag-cbor-sync": { + "version": "0.6.2", + "requires": { + "borc": "^2.0.3", + "cids": "^0.7.1", + "ipfs-block": "^0.8.0", + "is-circular": "^1.0.1", + "multihashing-async": "^0.8.0" + } + }, + "dargs": { + "version": "4.1.0", + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "dashdash": { + "version": "1.14.1", + "requires": { + "assert-plus": "^1.0.0" + } + }, + "data-queue": { + "version": "0.0.3" + }, + "datastore-core": { + "version": "0.7.0", + "requires": { + "debug": "^4.1.1", + "interface-datastore": "~0.7.0" + } + }, + "datastore-fs": { + "version": "0.9.1", + "requires": { + "datastore-core": "~0.7.0", + "fast-write-atomic": "~0.2.0", + "glob": "^7.1.3", + "interface-datastore": "~0.7.0", + "mkdirp": "~0.5.1" + } + }, + "datastore-level": { + "version": "0.14.1", + "requires": { + "datastore-core": "~0.7.0", + "interface-datastore": "^0.8.0", + "level": "^5.0.1" + }, + "dependencies": { + "interface-datastore": { + "version": "0.8.0", + "requires": { + "class-is": "^1.1.0", + "err-code": "^2.0.0", + "uuid": "^3.2.2" + } + } + } + }, + "datastore-pubsub": { + "version": "0.2.3", + "requires": { + "debug": "^4.1.1", + "err-code": "^2.0.0", + "interface-datastore": "~0.7.0", + "multibase": "~0.6.0" + } + }, + "date-fns": { + "version": "2.9.0" + }, + "date-format": { + "version": "2.1.0" + }, + "dateformat": { + "version": "3.0.3" + }, + "de-indent": { + "version": "1.0.2" + }, + "debug": { + "version": "4.1.1", + "requires": { + "ms": "^2.1.1" + }, + "dependencies": { + "ms": { + "version": "2.1.2" + } + } + }, + "decamelize": { + "version": "1.2.0" + }, + "decamelize-keys": { + "version": "1.1.0", + "requires": { + "decamelize": "^1.1.0", + "map-obj": "^1.0.0" + } + }, + "decode-uri-component": { + "version": "0.2.0" + }, + "decompress-response": { + "version": "3.3.0", + "requires": { + "mimic-response": "^1.0.0" + } + }, + "deep-eql": { + "version": "3.0.1", + "requires": { + "type-detect": "^4.0.0" + } + }, + "deep-extend": { + "version": "0.6.0" + }, + "deep-is": { + "version": "0.1.3" + }, + "default-require-extensions": { + "version": "2.0.0", + "requires": { + "strip-bom": "^3.0.0" + } + }, + "defer-to-connect": { + "version": "1.1.1" + }, + "deferred-leveldown": { + "version": "1.2.2", + "requires": { + "abstract-leveldown": "~2.6.0" + }, + "dependencies": { + "abstract-leveldown": { + "version": "2.6.3", + "requires": { + "xtend": "~4.0.0" + } + } + } + }, + "define-properties": { + "version": "1.1.3", + "requires": { + "object-keys": "^1.0.12" + } + }, + "define-property": { + "version": "0.2.5", + "requires": { + "is-descriptor": "^0.1.0" + }, + "dependencies": { + "is-accessor-descriptor": { + "version": "0.1.6", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-buffer": { + "version": "1.1.6" + }, + "is-data-descriptor": { + "version": "0.1.4", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "kind-of": { + "version": "5.1.0" + } + } + }, + "defined": { + "version": "1.0.0" + }, + "del": { + "version": "5.1.0", + "requires": { + "globby": "^10.0.1", + "graceful-fs": "^4.2.2", + "is-glob": "^4.0.1", + "is-path-cwd": "^2.2.0", + "is-path-inside": "^3.0.1", + "p-map": "^3.0.0", + "rimraf": "^3.0.0", + "slash": "^3.0.0" + }, + "dependencies": { + "rimraf": { + "version": "3.0.0", + "requires": { + "glob": "^7.1.3" + } + } + } + }, + "delay": { + "version": "4.3.0" + }, + "delayed-stream": { + "version": "1.0.0" + }, + "delegates": { + "version": "1.0.0" + }, + "delimit-stream": { + "version": "0.1.0" + }, + "depd": { + "version": "1.1.2" + }, + "dependency-check": { + "version": "4.1.0", + "requires": { + "debug": "^4.0.0", + "detective": "^5.0.2", + "globby": "^10.0.1", + "is-relative": "^1.0.0", + "micromatch": "^4.0.2", + "minimist": "^1.2.0", + "pkg-up": "^3.1.0", + "read-package-json": "^2.0.10", + "resolve": "^1.1.7" + }, + "dependencies": { + "micromatch": { + "version": "4.0.2", + "requires": { + "braces": "^3.0.1", + "picomatch": "^2.0.5" + } + } + } + }, + "des.js": { + "version": "1.0.1", + "requires": { + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, + "destroy": { + "version": "1.0.4" + }, + "detab": { + "version": "2.0.2", + "requires": { + "repeat-string": "^1.5.4" + } + }, + "detect-file": { + "version": "1.0.0" + }, + "detect-libc": { + "version": "1.0.3" + }, + "detect-node": { + "version": "2.0.4" + }, + "detective": { + "version": "5.2.0", + "requires": { + "acorn-node": "^1.6.1", + "defined": "^1.0.0", + "minimist": "^1.1.1" + } + }, + "di": { + "version": "0.0.1" + }, + "diff": { + "version": "3.5.0" + }, + "diff-match-patch": { + "version": "1.0.4" + }, + "diffie-hellman": { + "version": "5.0.3", + "requires": { + "bn.js": "^4.1.0", + "miller-rabin": "^4.0.0", + "randombytes": "^2.0.0" + } + }, + "dir-glob": { + "version": "3.0.1", + "requires": { + "path-type": "^4.0.0" + }, + "dependencies": { + "path-type": { + "version": "4.0.0" + } + } + }, + "dirty-chai": { + "version": "2.0.1" + }, + "dlv": { + "version": "1.1.3" + }, + "dns-packet": { + "version": "4.2.0", + "requires": { + "ip": "^1.1.5", + "safe-buffer": "^5.1.1" + } + }, + "doctrine": { + "version": "1.5.0", + "requires": { + "esutils": "^2.0.2", + "isarray": "^1.0.0" + } + }, + "doctrine-temporary-fork": { + "version": "2.1.0", + "requires": { + "esutils": "^2.0.2" + } + }, + "documentation": { + "version": "12.1.4", + "requires": { + "@babel/core": "^7.1.2", + "@babel/generator": "^7.1.3", + "@babel/parser": "7.1.3", + "@babel/plugin-proposal-class-properties": "^7.1.0", + "@babel/plugin-proposal-decorators": "^7.1.2", + "@babel/plugin-proposal-do-expressions": "^7.0.0", + "@babel/plugin-proposal-export-default-from": "^7.0.0", + "@babel/plugin-proposal-export-namespace-from": "^7.0.0", + "@babel/plugin-proposal-function-bind": "^7.0.0", + "@babel/plugin-proposal-function-sent": "^7.1.0", + "@babel/plugin-proposal-json-strings": "^7.0.0", + "@babel/plugin-proposal-logical-assignment-operators": "^7.0.0", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.0.0", + "@babel/plugin-proposal-numeric-separator": "^7.0.0", + "@babel/plugin-proposal-optional-chaining": "^7.0.0", + "@babel/plugin-proposal-pipeline-operator": "^7.0.0", + "@babel/plugin-proposal-throw-expressions": "^7.0.0", + "@babel/plugin-syntax-dynamic-import": "^7.0.0", + "@babel/plugin-syntax-import-meta": "^7.0.0", + "@babel/preset-env": "^7.1.0", + "@babel/preset-flow": "^7.0.0", + "@babel/preset-react": "^7.0.0", + "@babel/preset-stage-0": "^7.0.0", + "@babel/traverse": "^7.1.4", + "@babel/types": "^7.1.3", + "ansi-html": "^0.0.7", + "babelify": "^10.0.0", + "chalk": "^2.3.0", + "chokidar": "^2.0.4", + "concat-stream": "^1.6.0", + "diff": "^4.0.1", + "doctrine-temporary-fork": "2.1.0", + "get-port": "^4.0.0", + "git-url-parse": "^11.1.2", + "github-slugger": "1.2.0", + "glob": "^7.1.2", + "globals-docs": "^2.4.0", + "highlight.js": "^9.15.5", + "ini": "^1.3.5", + "js-yaml": "^3.10.0", + "lodash": "^4.17.10", + "mdast-util-inject": "^1.1.0", + "micromatch": "^3.1.5", + "mime": "^2.2.0", + "module-deps-sortable": "5.0.0", + "parse-filepath": "^1.0.2", + "pify": "^4.0.0", + "read-pkg-up": "^4.0.0", + "remark": "^9.0.0", + "remark-html": "^8.0.0", + "remark-reference-links": "^4.0.1", + "remark-toc": "^5.0.0", + "resolve": "^1.8.1", + "stream-array": "^1.1.2", + "strip-json-comments": "^2.0.1", + "tiny-lr": "^1.1.0", + "unist-builder": "^1.0.2", + "unist-util-visit": "^1.3.0", + "vfile": "^4.0.0", + "vfile-reporter": "^6.0.0", + "vfile-sort": "^2.1.0", + "vinyl": "^2.1.0", + "vinyl-fs": "^3.0.2", + "vue-template-compiler": "^2.5.16", + "yargs": "^12.0.2" + }, + "dependencies": { + "@babel/parser": { + "version": "7.1.3" + }, + "ansi-regex": { + "version": "3.0.0" + }, + "cliui": { + "version": "4.1.0", + "requires": { + "string-width": "^2.1.1", + "strip-ansi": "^4.0.0", + "wrap-ansi": "^2.0.0" + } + }, + "diff": { + "version": "4.0.2" + }, + "get-caller-file": { + "version": "1.0.3" + }, + "github-slugger": { + "version": "1.2.0", + "requires": { + "emoji-regex": ">=6.0.0 <=6.1.1" + } + }, + "read-pkg-up": { + "version": "4.0.0", + "requires": { + "find-up": "^3.0.0", + "read-pkg": "^3.0.0" + } + }, + "require-main-filename": { + "version": "1.0.1" + }, + "string-width": { + "version": "2.1.1", + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "requires": { + "ansi-regex": "^3.0.0" + } + }, + "wrap-ansi": { + "version": "2.1.0", + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1" + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "string-width": { + "version": "1.0.2", + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "requires": { + "ansi-regex": "^2.0.0" + } + } + } + }, + "yargs": { + "version": "12.0.5", + "requires": { + "cliui": "^4.0.0", + "decamelize": "^1.2.0", + "find-up": "^3.0.0", + "get-caller-file": "^1.0.1", + "os-locale": "^3.0.0", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^2.0.0", + "which-module": "^2.0.0", + "y18n": "^3.2.1 || ^4.0.0", + "yargs-parser": "^11.1.1" + } + }, + "yargs-parser": { + "version": "11.1.1", + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } + } + }, + "dom-serialize": { + "version": "2.2.1", + "requires": { + "custom-event": "~1.0.0", + "ent": "~2.2.0", + "extend": "^3.0.0", + "void-elements": "^2.0.0" + } + }, + "domain-browser": { + "version": "1.2.0" + }, + "dot-prop": { + "version": "3.0.0", + "requires": { + "is-obj": "^1.0.0" + } + }, + "drbg.js": { + "version": "1.0.1", + "requires": { + "browserify-aes": "^1.0.6", + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4" + } + }, + "duplexer": { + "version": "0.1.1" + }, + "duplexer2": { + "version": "0.1.4", + "requires": { + "readable-stream": "^2.0.2" + } + }, + "duplexer3": { + "version": "0.1.4" + }, + "duplexify": { + "version": "3.7.1", + "requires": { + "end-of-stream": "^1.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.0.0", + "stream-shift": "^1.0.0" + } + }, + "ecc-jsbn": { + "version": "0.1.2", + "requires": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "edge-launcher": { + "version": "1.2.2" + }, + "ee-first": { + "version": "1.1.1" + }, + "ejs": { + "version": "2.7.4" + }, + "electron": { + "version": "6.1.7", + "requires": { + "@types/node": "^10.12.18", + "electron-download": "^4.1.0", + "extract-zip": "^1.0.3" + }, + "dependencies": { + "@types/node": { + "version": "10.17.13" + } + } + }, + "electron-download": { + "version": "4.1.1", + "requires": { + "debug": "^3.0.0", + "env-paths": "^1.0.0", + "fs-extra": "^4.0.1", + "minimist": "^1.2.0", + "nugget": "^2.0.1", + "path-exists": "^3.0.0", + "rc": "^1.2.1", + "semver": "^5.4.1", + "sumchecker": "^2.0.2" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "requires": { + "ms": "^2.1.1" + } + }, + "fs-extra": { + "version": "4.0.3", + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "ms": { + "version": "2.1.2" + } + } + }, + "electron-mocha": { + "version": "8.2.0", + "requires": { + "ansi-colors": "^4.1.1", + "electron-window": "^0.8.0", + "fs-extra": "^8.1.0", + "log-symbols": "^3.0.0", + "mocha": "^7.0.0", + "which": "^2.0.2", + "yargs": "^15.1.0" + }, + "dependencies": { + "ansi-colors": { + "version": "4.1.1" + }, + "ansi-regex": { + "version": "5.0.0" + }, + "ansi-styles": { + "version": "4.2.1", + "requires": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + } + }, + "chokidar": { + "version": "3.3.0", + "requires": { + "anymatch": "~3.1.1", + "braces": "~3.0.2", + "fsevents": "~2.1.1", + "glob-parent": "~5.1.0", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.2.0" + } + }, + "cliui": { + "version": "6.0.0", + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + } + }, + "color-convert": { + "version": "2.0.1", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4" + }, + "debug": { + "version": "3.2.6", + "requires": { + "ms": "^2.1.1" + }, + "dependencies": { + "ms": { + "version": "2.1.2" + } + } + }, + "emoji-regex": { + "version": "8.0.0" + }, + "glob": { + "version": "7.1.3", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "is-fullwidth-code-point": { + "version": "3.0.0" + }, + "locate-path": { + "version": "5.0.0", + "requires": { + "p-locate": "^4.1.0" + } + }, + "log-symbols": { + "version": "3.0.0", + "requires": { + "chalk": "^2.4.2" + } + }, + "mocha": { + "version": "7.0.0", + "requires": { + "ansi-colors": "3.2.3", + "browser-stdout": "1.3.1", + "chokidar": "3.3.0", + "debug": "3.2.6", + "diff": "3.5.0", + "escape-string-regexp": "1.0.5", + "find-up": "3.0.0", + "glob": "7.1.3", + "growl": "1.10.5", + "he": "1.2.0", + "js-yaml": "3.13.1", + "log-symbols": "2.2.0", + "minimatch": "3.0.4", + "mkdirp": "0.5.1", + "ms": "2.1.1", + "node-environment-flags": "1.0.6", + "object.assign": "4.1.0", + "strip-json-comments": "2.0.1", + "supports-color": "6.0.0", + "which": "1.3.1", + "wide-align": "1.1.3", + "yargs": "13.3.0", + "yargs-parser": "13.1.1", + "yargs-unparser": "1.6.0" + }, + "dependencies": { + "ansi-colors": { + "version": "3.2.3" + }, + "ansi-regex": { + "version": "4.1.0" + }, + "ansi-styles": { + "version": "3.2.1", + "requires": { + "color-convert": "^1.9.0" + } + }, + "cliui": { + "version": "5.0.0", + "requires": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + } + }, + "color-convert": { + "version": "1.9.3", + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3" + }, + "emoji-regex": { + "version": "7.0.3" + }, + "is-fullwidth-code-point": { + "version": "2.0.0" + }, + "log-symbols": { + "version": "2.2.0", + "requires": { + "chalk": "^2.0.1" + } + }, + "string-width": { + "version": "3.1.0", + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "requires": { + "ansi-regex": "^4.1.0" + } + }, + "which": { + "version": "1.3.1", + "requires": { + "isexe": "^2.0.0" + } + }, + "wrap-ansi": { + "version": "5.1.0", + "requires": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + } + }, + "yargs": { + "version": "13.3.0", + "requires": { + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.1" + } + } + } + }, + "node-environment-flags": { + "version": "1.0.6", + "requires": { + "object.getownpropertydescriptors": "^2.0.3", + "semver": "^5.7.0" + } + }, + "p-locate": { + "version": "4.1.0", + "requires": { + "p-limit": "^2.2.0" + } + }, + "path-exists": { + "version": "4.0.0" + }, + "readdirp": { + "version": "3.2.0", + "requires": { + "picomatch": "^2.0.4" + } + }, + "string-width": { + "version": "4.2.0", + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + } + }, + "strip-ansi": { + "version": "6.0.0", + "requires": { + "ansi-regex": "^5.0.0" + } + }, + "supports-color": { + "version": "6.0.0", + "requires": { + "has-flag": "^3.0.0" + } + }, + "which": { + "version": "2.0.2", + "requires": { + "isexe": "^2.0.0" + } + }, + "wrap-ansi": { + "version": "6.2.0", + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, + "yargs": { + "version": "15.1.0", + "requires": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^16.1.0" + }, + "dependencies": { + "find-up": { + "version": "4.1.0", + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "yargs-parser": { + "version": "16.1.0", + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } + } + } + } + }, + "electron-to-chromium": { + "version": "1.3.338" + }, + "electron-window": { + "version": "0.8.1", + "requires": { + "is-electron-renderer": "^2.0.0" + } + }, + "elegant-spinner": { + "version": "1.0.1" + }, + "elliptic": { + "version": "6.5.2", + "requires": { + "bn.js": "^4.4.0", + "brorand": "^1.0.1", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.0" + } + }, + "email-addresses": { + "version": "3.1.0" + }, + "emoji-regex": { + "version": "6.1.1" + }, + "emojis-list": { + "version": "2.1.0" + }, + "encodeurl": { + "version": "1.0.2" + }, + "encoding-down": { + "version": "6.3.0", + "requires": { + "abstract-leveldown": "^6.2.1", + "inherits": "^2.0.3", + "level-codec": "^9.0.0", + "level-errors": "^2.0.0" + }, + "dependencies": { + "abstract-leveldown": { + "version": "6.2.2", + "requires": { + "level-concat-iterator": "~2.0.0", + "level-supports": "~1.0.0", + "xtend": "~4.0.0" + } + } + } + }, + "end-of-stream": { + "version": "1.4.4", + "requires": { + "once": "^1.4.0" + } + }, + "engine.io": { + "version": "3.2.1", + "requires": { + "accepts": "~1.3.4", + "base64id": "1.0.0", + "cookie": "0.3.1", + "debug": "~3.1.0", + "engine.io-parser": "~2.1.0", + "ws": "~3.3.1" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0" + } + } + }, + "engine.io-client": { + "version": "3.4.0", + "requires": { + "component-emitter": "1.2.1", + "component-inherit": "0.0.3", + "debug": "~4.1.0", + "engine.io-parser": "~2.2.0", + "has-cors": "1.1.0", + "indexof": "0.0.1", + "parseqs": "0.0.5", + "parseuri": "0.0.5", + "ws": "~6.1.0", + "xmlhttprequest-ssl": "~1.5.4", + "yeast": "0.1.2" + }, + "dependencies": { + "engine.io-parser": { + "version": "2.2.0", + "requires": { + "after": "0.8.2", + "arraybuffer.slice": "~0.0.7", + "base64-arraybuffer": "0.1.5", + "blob": "0.0.5", + "has-binary2": "~1.0.2" + } + }, + "ws": { + "version": "6.1.4", + "requires": { + "async-limiter": "~1.0.0" + } + } + } + }, + "engine.io-parser": { + "version": "2.1.3", + "requires": { + "after": "0.8.2", + "arraybuffer.slice": "~0.0.7", + "base64-arraybuffer": "0.1.5", + "blob": "0.0.5", + "has-binary2": "~1.0.2" + } + }, + "enhanced-resolve": { + "version": "4.1.0", + "requires": { + "graceful-fs": "^4.1.2", + "memory-fs": "^0.4.0", + "tapable": "^1.0.0" + } + }, + "ent": { + "version": "2.2.0" + }, + "env-paths": { + "version": "1.0.0" + }, + "epimetheus": { + "version": "1.0.92", + "requires": { + "prom-client": "^10.0.0" + }, + "dependencies": { + "prom-client": { + "version": "10.2.3", + "requires": { + "tdigest": "^0.1.1" + } + } + } + }, + "err-code": { + "version": "2.0.0" + }, + "errno": { + "version": "0.1.7", + "requires": { + "prr": "~1.0.1" + } + }, + "error": { + "version": "7.2.1", + "requires": { + "string-template": "~0.2.1" + } + }, + "error-ex": { + "version": "1.3.2", + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "es-abstract": { + "version": "1.17.3", + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.1.5", + "is-regex": "^1.0.5", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimleft": "^2.1.1", + "string.prototype.trimright": "^2.1.1" + } + }, + "es-to-primitive": { + "version": "1.2.1", + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "es6-error": { + "version": "4.1.1" + }, + "es6-promise": { + "version": "4.2.8" + }, + "es6-promisify": { + "version": "6.0.2" + }, + "escape-html": { + "version": "1.0.3" + }, + "escape-string-regexp": { + "version": "1.0.5" + }, + "eslint": { + "version": "6.8.0", + "requires": { + "@babel/code-frame": "^7.0.0", + "ajv": "^6.10.0", + "chalk": "^2.1.0", + "cross-spawn": "^6.0.5", + "debug": "^4.0.1", + "doctrine": "^3.0.0", + "eslint-scope": "^5.0.0", + "eslint-utils": "^1.4.3", + "eslint-visitor-keys": "^1.1.0", + "espree": "^6.1.2", + "esquery": "^1.0.1", + "esutils": "^2.0.2", + "file-entry-cache": "^5.0.1", + "functional-red-black-tree": "^1.0.1", + "glob-parent": "^5.0.0", + "globals": "^12.1.0", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "inquirer": "^7.0.0", + "is-glob": "^4.0.0", + "js-yaml": "^3.13.1", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.3.0", + "lodash": "^4.17.14", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.1", + "natural-compare": "^1.4.0", + "optionator": "^0.8.3", + "progress": "^2.0.0", + "regexpp": "^2.0.1", + "semver": "^6.1.2", + "strip-ansi": "^5.2.0", + "strip-json-comments": "^3.0.1", + "table": "^5.2.3", + "text-table": "^0.2.0", + "v8-compile-cache": "^2.0.3" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0" + }, + "doctrine": { + "version": "3.0.0", + "requires": { + "esutils": "^2.0.2" + } + }, + "eslint-scope": { + "version": "5.0.0", + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, + "globals": { + "version": "12.3.0", + "requires": { + "type-fest": "^0.8.1" + } + }, + "ignore": { + "version": "4.0.6" + }, + "semver": { + "version": "6.3.0" + }, + "strip-ansi": { + "version": "5.2.0", + "requires": { + "ansi-regex": "^4.1.0" + } + }, + "strip-json-comments": { + "version": "3.0.1" + }, + "v8-compile-cache": { + "version": "2.1.0" + } + } + }, + "eslint-config-standard": { + "version": "14.1.0" + }, + "eslint-import-resolver-node": { + "version": "0.3.3", + "requires": { + "debug": "^2.6.9", + "resolve": "^1.13.1" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0" + } + } + }, + "eslint-module-utils": { + "version": "2.5.2", + "requires": { + "debug": "^2.6.9", + "pkg-dir": "^2.0.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "requires": { + "ms": "2.0.0" + } + }, + "find-up": { + "version": "2.1.0", + "requires": { + "locate-path": "^2.0.0" + } + }, + "locate-path": { + "version": "2.0.0", + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } + }, + "ms": { + "version": "2.0.0" + }, + "p-limit": { + "version": "1.3.0", + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "requires": { + "p-limit": "^1.1.0" + } + }, + "p-try": { + "version": "1.0.0" + }, + "pkg-dir": { + "version": "2.0.0", + "requires": { + "find-up": "^2.1.0" + } + } + } + }, + "eslint-plugin-es": { + "version": "2.0.0", + "requires": { + "eslint-utils": "^1.4.2", + "regexpp": "^3.0.0" + }, + "dependencies": { + "regexpp": { + "version": "3.0.0" + } + } + }, + "eslint-plugin-import": { + "version": "2.20.0", + "requires": { + "array-includes": "^3.0.3", + "array.prototype.flat": "^1.2.1", + "contains-path": "^0.1.0", + "debug": "^2.6.9", + "doctrine": "1.5.0", + "eslint-import-resolver-node": "^0.3.2", + "eslint-module-utils": "^2.4.1", + "has": "^1.0.3", + "minimatch": "^3.0.4", + "object.values": "^1.1.0", + "read-pkg-up": "^2.0.0", + "resolve": "^1.12.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "requires": { + "ms": "2.0.0" + } + }, + "find-up": { + "version": "2.1.0", + "requires": { + "locate-path": "^2.0.0" + } + }, + "load-json-file": { + "version": "2.0.0", + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "strip-bom": "^3.0.0" + } + }, + "locate-path": { + "version": "2.0.0", + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } + }, + "ms": { + "version": "2.0.0" + }, + "p-limit": { + "version": "1.3.0", + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "requires": { + "p-limit": "^1.1.0" + } + }, + "p-try": { + "version": "1.0.0" + }, + "parse-json": { + "version": "2.2.0", + "requires": { + "error-ex": "^1.2.0" + } + }, + "path-type": { + "version": "2.0.0", + "requires": { + "pify": "^2.0.0" + } + }, + "pify": { + "version": "2.3.0" + }, + "read-pkg": { + "version": "2.0.0", + "requires": { + "load-json-file": "^2.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^2.0.0" + } + }, + "read-pkg-up": { + "version": "2.0.0", + "requires": { + "find-up": "^2.0.0", + "read-pkg": "^2.0.0" + } + } + } + }, + "eslint-plugin-no-only-tests": { + "version": "2.4.0" + }, + "eslint-plugin-node": { + "version": "10.0.0", + "requires": { + "eslint-plugin-es": "^2.0.0", + "eslint-utils": "^1.4.2", + "ignore": "^5.1.1", + "minimatch": "^3.0.4", + "resolve": "^1.10.1", + "semver": "^6.1.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0" + } + } + }, + "eslint-plugin-promise": { + "version": "4.2.1" + }, + "eslint-plugin-standard": { + "version": "4.0.1" + }, + "eslint-scope": { + "version": "4.0.3", + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, + "eslint-utils": { + "version": "1.4.3", + "requires": { + "eslint-visitor-keys": "^1.1.0" + } + }, + "eslint-visitor-keys": { + "version": "1.1.0" + }, + "espree": { + "version": "6.1.2", + "requires": { + "acorn": "^7.1.0", + "acorn-jsx": "^5.1.0", + "eslint-visitor-keys": "^1.1.0" + } + }, + "esprima": { + "version": "4.0.1" + }, + "esquery": { + "version": "1.0.1", + "requires": { + "estraverse": "^4.0.0" + } + }, + "esrecurse": { + "version": "4.2.1", + "requires": { + "estraverse": "^4.1.0" + } + }, + "estraverse": { + "version": "4.3.0" + }, + "esutils": { + "version": "2.0.3" + }, + "etag": { + "version": "1.8.1" + }, + "ethereumjs-account": { + "version": "3.0.0", + "requires": { + "ethereumjs-util": "^6.0.0", + "rlp": "^2.2.1", + "safe-buffer": "^5.1.1" + }, + "dependencies": { + "ethereumjs-util": { + "version": "6.2.0", + "requires": { + "@types/bn.js": "^4.11.3", + "bn.js": "^4.11.0", + "create-hash": "^1.1.2", + "ethjs-util": "0.1.6", + "keccak": "^2.0.0", + "rlp": "^2.2.3", + "secp256k1": "^3.0.1" + } + }, + "keccak": { + "version": "2.1.0", + "requires": { + "bindings": "^1.5.0", + "inherits": "^2.0.4", + "nan": "^2.14.0", + "safe-buffer": "^5.2.0" + } + } + } + }, + "ethereumjs-block": { + "version": "2.2.2", + "requires": { + "async": "^2.0.1", + "ethereumjs-common": "^1.5.0", + "ethereumjs-tx": "^2.1.1", + "ethereumjs-util": "^5.0.0", + "merkle-patricia-tree": "^2.1.2" + }, + "dependencies": { + "async": { + "version": "2.6.3", + "requires": { + "lodash": "^4.17.14" + } + }, + "isarray": { + "version": "0.0.1" + }, + "level-ws": { + "version": "0.0.0", + "requires": { + "readable-stream": "~1.0.15", + "xtend": "~2.1.1" + }, + "dependencies": { + "readable-stream": { + "version": "1.0.34", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + } + } + }, + "merkle-patricia-tree": { + "version": "2.3.2", + "requires": { + "async": "^1.4.2", + "ethereumjs-util": "^5.0.0", + "level-ws": "0.0.0", + "levelup": "^1.2.1", + "memdown": "^1.0.0", + "readable-stream": "^2.0.0", + "rlp": "^2.0.0", + "semaphore": ">=1.0.1" + }, + "dependencies": { + "async": { + "version": "1.5.2" + } + } + }, + "object-keys": { + "version": "0.4.0" + }, + "xtend": { + "version": "2.1.2", + "requires": { + "object-keys": "~0.4.0" + } + } + } + }, + "ethereumjs-common": { + "version": "1.5.0" + }, + "ethereumjs-tx": { + "version": "2.1.2", + "requires": { + "ethereumjs-common": "^1.5.0", + "ethereumjs-util": "^6.0.0" + }, + "dependencies": { + "ethereumjs-util": { + "version": "6.2.0", + "requires": { + "@types/bn.js": "^4.11.3", + "bn.js": "^4.11.0", + "create-hash": "^1.1.2", + "ethjs-util": "0.1.6", + "keccak": "^2.0.0", + "rlp": "^2.2.3", + "secp256k1": "^3.0.1" + } + }, + "keccak": { + "version": "2.1.0", + "requires": { + "bindings": "^1.5.0", + "inherits": "^2.0.4", + "nan": "^2.14.0", + "safe-buffer": "^5.2.0" + } + } + } + }, + "ethereumjs-util": { + "version": "5.2.0", + "requires": { + "bn.js": "^4.11.0", + "create-hash": "^1.1.2", + "ethjs-util": "^0.1.3", + "keccak": "^1.0.2", + "rlp": "^2.0.0", + "safe-buffer": "^5.1.1", + "secp256k1": "^3.0.1" + } + }, + "ethjs-util": { + "version": "0.1.6", + "requires": { + "is-hex-prefixed": "1.0.0", + "strip-hex-prefix": "1.0.0" + } + }, + "event-iterator": { + "version": "1.2.0" + }, + "event-target-shim": { + "version": "5.0.1" + }, + "eventemitter3": { + "version": "4.0.0" + }, + "events": { + "version": "3.1.0" + }, + "evp_bytestokey": { + "version": "1.0.3", + "requires": { + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" + } + }, + "execa": { + "version": "1.0.0", + "requires": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + }, + "dependencies": { + "get-stream": { + "version": "4.1.0", + "requires": { + "pump": "^3.0.0" + } + }, + "is-stream": { + "version": "1.1.0" + } + } + }, + "expand-brackets": { + "version": "2.1.4", + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0" + } + } + }, + "expand-template": { + "version": "2.0.3" + }, + "expand-tilde": { + "version": "2.0.2", + "requires": { + "homedir-polyfill": "^1.0.1" + } + }, + "explain-error": { + "version": "1.0.4" + }, + "express": { + "version": "4.17.1", + "requires": { + "accepts": "~1.3.7", + "array-flatten": "1.1.1", + "body-parser": "1.19.0", + "content-disposition": "0.5.3", + "content-type": "~1.0.4", + "cookie": "0.4.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~1.1.2", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "~1.1.2", + "fresh": "0.5.2", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.5", + "qs": "6.7.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.1.2", + "send": "0.17.1", + "serve-static": "1.14.1", + "setprototypeof": "1.1.1", + "statuses": "~1.5.0", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "dependencies": { + "cookie": { + "version": "0.4.0" + }, + "debug": { + "version": "2.6.9", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0" + }, + "qs": { + "version": "6.7.0" + }, + "safe-buffer": { + "version": "5.1.2" + } + } + }, + "extend": { + "version": "3.0.2" + }, + "extend-shallow": { + "version": "2.0.1", + "requires": { + "is-extendable": "^0.1.0" + } + }, + "external-editor": { + "version": "3.1.0", + "requires": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + } + }, + "extglob": { + "version": "2.0.4", + "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.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "requires": { + "is-descriptor": "^1.0.0" + } + } + } + }, + "extract-zip": { + "version": "1.6.7", + "requires": { + "concat-stream": "1.6.2", + "debug": "2.6.9", + "mkdirp": "0.5.1", + "yauzl": "2.4.1" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0" + } + } + }, + "extsprintf": { + "version": "1.3.0" + }, + "fast-deep-equal": { + "version": "3.1.1" + }, + "fast-fifo": { + "version": "1.0.0" + }, + "fast-glob": { + "version": "3.1.1", + "requires": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.0", + "merge2": "^1.3.0", + "micromatch": "^4.0.2" + }, + "dependencies": { + "micromatch": { + "version": "4.0.2", + "requires": { + "braces": "^3.0.1", + "picomatch": "^2.0.5" + } + } + } + }, + "fast-json-stable-stringify": { + "version": "2.1.0" + }, + "fast-levenshtein": { + "version": "2.0.6" + }, + "fast-redact": { + "version": "2.0.0" + }, + "fast-safe-stringify": { + "version": "2.0.7" + }, + "fast-write-atomic": { + "version": "0.2.1" + }, + "fastq": { + "version": "1.6.0", + "requires": { + "reusify": "^1.0.0" + } + }, + "faye-websocket": { + "version": "0.10.0", + "requires": { + "websocket-driver": ">=0.5.1" + } + }, + "fd-slicer": { + "version": "1.0.1", + "requires": { + "pend": "~1.2.0" + } + }, + "figgy-pudding": { + "version": "3.5.1" + }, + "figures": { + "version": "2.0.0", + "requires": { + "escape-string-regexp": "^1.0.5" + } + }, + "file-entry-cache": { + "version": "5.0.1", + "requires": { + "flat-cache": "^2.0.1" + } + }, + "file-type": { + "version": "12.4.2" + }, + "file-uri-to-path": { + "version": "1.0.0" + }, + "filename-reserved-regex": { + "version": "1.0.0" + }, + "filenamify": { + "version": "1.2.1", + "requires": { + "filename-reserved-regex": "^1.0.0", + "strip-outer": "^1.0.0", + "trim-repeated": "^1.0.0" + } + }, + "filenamify-url": { + "version": "1.0.0", + "requires": { + "filenamify": "^1.0.0", + "humanize-url": "^1.0.0" + } + }, + "filesize": { + "version": "3.6.1" + }, + "fill-range": { + "version": "7.0.1", + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "finalhandler": { + "version": "1.1.2", + "requires": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0" + } + } + }, + "find-cache-dir": { + "version": "2.1.0", + "requires": { + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" + } + }, + "find-parent-dir": { + "version": "0.3.0" + }, + "find-up": { + "version": "3.0.0", + "requires": { + "locate-path": "^3.0.0" + } + }, + "findup-sync": { + "version": "4.0.0", + "requires": { + "detect-file": "^1.0.0", + "is-glob": "^4.0.0", + "micromatch": "^4.0.2", + "resolve-dir": "^1.0.1" + }, + "dependencies": { + "micromatch": { + "version": "4.0.2", + "requires": { + "braces": "^3.0.1", + "picomatch": "^2.0.5" + } + } + } + }, + "flat": { + "version": "4.1.0", + "requires": { + "is-buffer": "~2.0.3" + } + }, + "flat-cache": { + "version": "2.0.1", + "requires": { + "flatted": "^2.0.0", + "rimraf": "2.6.3", + "write": "1.0.3" + }, + "dependencies": { + "rimraf": { + "version": "2.6.3", + "requires": { + "glob": "^7.1.3" + } + } + } + }, + "flatmap": { + "version": "0.0.3" + }, + "flatstr": { + "version": "1.0.12" + }, + "flatted": { + "version": "2.0.1" + }, + "flush-write-stream": { + "version": "1.1.1", + "requires": { + "inherits": "^2.0.3", + "readable-stream": "^2.3.6" + } + }, + "fnv1a": { + "version": "1.0.1" + }, + "follow-redirects": { + "version": "1.5.10", + "requires": { + "debug": "=3.1.0" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0" + } + } + }, + "for-in": { + "version": "1.0.2" + }, + "for-own": { + "version": "1.0.0", + "requires": { + "for-in": "^1.0.1" + } + }, + "foreground-child": { + "version": "1.5.6", + "requires": { + "cross-spawn": "^4", + "signal-exit": "^3.0.0" + }, + "dependencies": { + "cross-spawn": { + "version": "4.0.2", + "requires": { + "lru-cache": "^4.0.1", + "which": "^1.2.9" + } + } + } + }, + "forever-agent": { + "version": "0.6.1" + }, + "form-data": { + "version": "3.0.0", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + }, + "forwarded": { + "version": "0.1.2" + }, + "fragment-cache": { + "version": "0.2.1", + "requires": { + "map-cache": "^0.2.2" + } + }, + "fresh": { + "version": "0.5.2" + }, + "from2": { + "version": "2.3.0", + "requires": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.0" + } + }, + "fs-constants": { + "version": "1.0.0" + }, + "fs-extra": { + "version": "8.1.0", + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "fs-minipass": { + "version": "2.0.1", + "requires": { + "minipass": "^3.0.0" + } + }, + "fs-mkdirp-stream": { + "version": "1.0.0", + "requires": { + "graceful-fs": "^4.1.11", + "through2": "^2.0.3" + } + }, + "fs-readdir-recursive": { + "version": "1.1.0" + }, + "fs-write-stream-atomic": { + "version": "1.0.10", + "requires": { + "graceful-fs": "^4.1.2", + "iferr": "^0.1.5", + "imurmurhash": "^0.1.4", + "readable-stream": "1 || 2" + } + }, + "fs.realpath": { + "version": "1.0.0" + }, + "fsevents": { + "version": "2.1.2", + "optional": true + }, + "fsm": { + "version": "1.0.2", + "requires": { + "split": "~0.3.0" + }, + "dependencies": { + "split": { + "version": "0.3.3", + "requires": { + "through": "2" + } + } + } + }, + "fsm-event": { + "version": "2.1.0", + "requires": { + "fsm": "^1.0.2" + } + }, + "function-bind": { + "version": "1.1.1" + }, + "functional-red-black-tree": { + "version": "1.0.1" + }, + "gar": { + "version": "1.0.4" + }, + "gauge": { + "version": "2.7.4", + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + }, + "dependencies": { + "is-fullwidth-code-point": { + "version": "1.0.0", + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "string-width": { + "version": "1.0.2", + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + } + } + }, + "gc-stats": { + "version": "1.4.0", + "optional": true, + "requires": { + "nan": "^2.13.2", + "node-pre-gyp": "^0.13.0" + }, + "dependencies": { + "abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "optional": true + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "optional": true + }, + "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.5", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", + "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", + "optional": true, + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "optional": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "optional": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "chownr": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.1.tgz", + "integrity": "sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g==", + "optional": true + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "optional": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "optional": true + }, + "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=", + "optional": true + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "optional": true + }, + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "optional": true, + "requires": { + "ms": "^2.1.1" + } + }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "optional": true + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", + "optional": true + }, + "detect-libc": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", + "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=", + "optional": true + }, + "fs-minipass": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.5.tgz", + "integrity": "sha512-JhBl0skXjUPCFH7x6x61gQxrKyXsxB5gcgePLZCwfyCGGsTISMoIeObbrvVeP6Xmyaudw4TT43qV2Gz+iyd2oQ==", + "optional": true, + "requires": { + "minipass": "^2.2.1" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "optional": true + }, + "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.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "optional": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "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 + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "optional": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "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" + } + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "optional": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "optional": true + }, + "ini": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", + "optional": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "optional": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "optional": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "optional": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "optional": true + }, + "minipass": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.3.5.tgz", + "integrity": "sha512-Gi1W4k059gyRbyVUZQ4mEqLm0YIUiGYfvxhF6SIlk3ui1WVxMTGfGdQ2SInh3PDrRTVvPKgULkpJtT4RH10+VA==", + "optional": true, + "requires": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + } + }, + "minizlib": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.2.1.tgz", + "integrity": "sha512-7+4oTUOWKg7AuL3vloEWekXY2/D20cevzsrNT2kGWm+39J9hGTCBv8VI5Pm5lXZ/o3/mdR4f8rflAPhnQb8mPA==", + "optional": true, + "requires": { + "minipass": "^2.2.1" + } + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "optional": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "optional": true + }, + "needle": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/needle/-/needle-2.3.1.tgz", + "integrity": "sha512-CaLXV3W8Vnbps8ZANqDGz7j4x7Yj1LW4TWF/TQuDfj7Cfx4nAPTvw98qgTevtto1oHDrh3pQkaODbqupXlsWTg==", + "optional": true, + "requires": { + "debug": "^4.1.0", + "iconv-lite": "^0.4.4", + "sax": "^1.2.4" + } + }, + "node-pre-gyp": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.13.0.tgz", + "integrity": "sha512-Md1D3xnEne8b/HGVQkZZwV27WUi1ZRuZBij24TNaZwUPU3ZAFtvT6xxJGaUVillfmMKnn5oD1HoGsp2Ftik7SQ==", + "optional": true, + "requires": { + "detect-libc": "^1.0.2", + "mkdirp": "^0.5.1", + "needle": "^2.2.1", + "nopt": "^4.0.1", + "npm-packlist": "^1.1.6", + "npmlog": "^4.0.2", + "rc": "^1.2.7", + "rimraf": "^2.6.1", + "semver": "^5.3.0", + "tar": "^4" + } + }, + "nopt": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.1.tgz", + "integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=", + "optional": true, + "requires": { + "abbrev": "1", + "osenv": "^0.1.4" + } + }, + "npm-bundled": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.0.6.tgz", + "integrity": "sha512-8/JCaftHwbd//k6y2rEWp6k1wxVfpFzB6t1p825+cUb7Ym2XQfhwIC5KwhrvzZRJu+LtDE585zVaS32+CGtf0g==", + "optional": true + }, + "npm-packlist": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.4.1.tgz", + "integrity": "sha512-+TcdO7HJJ8peiiYhvPxsEDhF3PJFGUGRcFsGve3vxvxdcpO2Z4Z7rkosRM0kWj6LfbK/P0gu3dzk5RU1ffvFcw==", + "optional": true, + "requires": { + "ignore-walk": "^3.0.1", + "npm-bundled": "^1.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.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "optional": true + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "optional": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "optional": true, + "requires": { + "wrappy": "1" + } + }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "optional": true + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "optional": true + }, + "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.0", + "os-tmpdir": "^1.0.0" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "optional": true + }, + "process-nextick-args": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", + "optional": true + }, + "rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "optional": true, + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "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 + } + } + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "optional": true, + "requires": { + "core-util-is": "~1.0.0", + "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.1" + } + }, + "rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "optional": true, + "requires": { + "glob": "^7.1.3" + } + }, + "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==", + "optional": true + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "optional": true + }, + "sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", + "optional": true + }, + "semver": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", + "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==", + "optional": true + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "optional": true + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "optional": true + }, + "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.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "optional": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "optional": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "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=", + "optional": true + }, + "tar": { + "version": "4.4.8", + "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.8.tgz", + "integrity": "sha512-LzHF64s5chPQQS0IYBn9IN5h3i98c12bo4NCO7e0sGM2llXQ3p2FGC5sdENN4cTW48O915Sh+x+EXx7XW96xYQ==", + "optional": true, + "requires": { + "chownr": "^1.1.1", + "fs-minipass": "^1.2.5", + "minipass": "^2.3.4", + "minizlib": "^1.1.1", + "mkdirp": "^0.5.0", + "safe-buffer": "^5.1.2", + "yallist": "^3.0.2" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "optional": true + }, + "wide-align": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", + "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "optional": true, + "requires": { + "string-width": "^1.0.2 || 2" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "optional": true + }, + "yallist": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz", + "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==", + "optional": true + } + } + }, + "gensync": { + "version": "1.0.0-beta.1" + }, + "get-browser-rtc": { + "version": "1.0.2" + }, + "get-caller-file": { + "version": "2.0.5" + }, + "get-folder-size": { + "version": "2.0.1", + "requires": { + "gar": "^1.0.4", + "tiny-each-async": "2.0.3" + } + }, + "get-func-name": { + "version": "2.0.0" + }, + "get-iterator": { + "version": "1.0.2" + }, + "get-pkg-repo": { + "version": "1.4.0", + "requires": { + "hosted-git-info": "^2.1.4", + "meow": "^3.3.0", + "normalize-package-data": "^2.3.0", + "parse-github-repo-url": "^1.3.0", + "through2": "^2.0.0" + }, + "dependencies": { + "camelcase": { + "version": "2.1.1" + }, + "camelcase-keys": { + "version": "2.1.0", + "requires": { + "camelcase": "^2.0.0", + "map-obj": "^1.0.0" + } + }, + "find-up": { + "version": "1.1.2", + "requires": { + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "indent-string": { + "version": "2.1.0", + "requires": { + "repeating": "^2.0.0" + } + }, + "load-json-file": { + "version": "1.1.0", + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "strip-bom": "^2.0.0" + } + }, + "meow": { + "version": "3.7.0", + "requires": { + "camelcase-keys": "^2.0.0", + "decamelize": "^1.1.2", + "loud-rejection": "^1.0.0", + "map-obj": "^1.0.1", + "minimist": "^1.1.3", + "normalize-package-data": "^2.3.4", + "object-assign": "^4.0.1", + "read-pkg-up": "^1.0.1", + "redent": "^1.0.0", + "trim-newlines": "^1.0.0" + } + }, + "parse-json": { + "version": "2.2.0", + "requires": { + "error-ex": "^1.2.0" + } + }, + "path-exists": { + "version": "2.1.0", + "requires": { + "pinkie-promise": "^2.0.0" + } + }, + "path-type": { + "version": "1.1.0", + "requires": { + "graceful-fs": "^4.1.2", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "pify": { + "version": "2.3.0" + }, + "read-pkg": { + "version": "1.1.0", + "requires": { + "load-json-file": "^1.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^1.0.0" + } + }, + "read-pkg-up": { + "version": "1.0.1", + "requires": { + "find-up": "^1.0.0", + "read-pkg": "^1.0.0" + } + }, + "redent": { + "version": "1.0.0", + "requires": { + "indent-string": "^2.1.0", + "strip-indent": "^1.0.1" + } + }, + "strip-bom": { + "version": "2.0.0", + "requires": { + "is-utf8": "^0.2.0" + } + }, + "strip-indent": { + "version": "1.0.1", + "requires": { + "get-stdin": "^4.0.1" + } + }, + "trim-newlines": { + "version": "1.0.0" + } + } + }, + "get-port": { + "version": "4.2.0" + }, + "get-stdin": { + "version": "4.0.1" + }, + "get-stream": { + "version": "3.0.0" + }, + "get-value": { + "version": "2.0.6" + }, + "getpass": { + "version": "0.1.7", + "requires": { + "assert-plus": "^1.0.0" + } + }, + "gh-got": { + "version": "7.1.0", + "requires": { + "got": "^8.0.0", + "is-plain-obj": "^1.1.0" + } + }, + "gh-pages": { + "version": "2.2.0", + "requires": { + "async": "^2.6.1", + "commander": "^2.18.0", + "email-addresses": "^3.0.1", + "filenamify-url": "^1.0.0", + "fs-extra": "^8.1.0", + "globby": "^6.1.0" + }, + "dependencies": { + "array-union": { + "version": "1.0.2", + "requires": { + "array-uniq": "^1.0.1" + } + }, + "async": { + "version": "2.6.3", + "requires": { + "lodash": "^4.17.14" + } + }, + "globby": { + "version": "6.1.0", + "requires": { + "array-union": "^1.0.1", + "glob": "^7.0.3", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "pify": { + "version": "2.3.0" + } + } + }, + "git-raw-commits": { + "version": "2.0.0", + "requires": { + "dargs": "^4.0.1", + "lodash.template": "^4.0.2", + "meow": "^4.0.0", + "split2": "^2.0.0", + "through2": "^2.0.0" + }, + "dependencies": { + "meow": { + "version": "4.0.1", + "requires": { + "camelcase-keys": "^4.0.0", + "decamelize-keys": "^1.0.0", + "loud-rejection": "^1.0.0", + "minimist": "^1.1.3", + "minimist-options": "^3.0.1", + "normalize-package-data": "^2.3.4", + "read-pkg-up": "^3.0.0", + "redent": "^2.0.0", + "trim-newlines": "^2.0.0" + } + } + } + }, + "git-remote-origin-url": { + "version": "2.0.0", + "requires": { + "gitconfiglocal": "^1.0.0", + "pify": "^2.3.0" + }, + "dependencies": { + "pify": { + "version": "2.3.0" + } + } + }, + "git-semver-tags": { + "version": "2.0.3", + "requires": { + "meow": "^4.0.0", + "semver": "^6.0.0" + }, + "dependencies": { + "meow": { + "version": "4.0.1", + "requires": { + "camelcase-keys": "^4.0.0", + "decamelize-keys": "^1.0.0", + "loud-rejection": "^1.0.0", + "minimist": "^1.1.3", + "minimist-options": "^3.0.1", + "normalize-package-data": "^2.3.4", + "read-pkg-up": "^3.0.0", + "redent": "^2.0.0", + "trim-newlines": "^2.0.0" + } + }, + "semver": { + "version": "6.3.0" + } + } + }, + "git-up": { + "version": "4.0.1", + "requires": { + "is-ssh": "^1.3.0", + "parse-url": "^5.0.0" + } + }, + "git-url-parse": { + "version": "11.1.2", + "requires": { + "git-up": "^4.0.0" + } + }, + "git-validate": { + "version": "2.2.4" + }, + "gitconfiglocal": { + "version": "1.0.0", + "requires": { + "ini": "^1.3.2" + } + }, + "github-build": { + "version": "1.2.1", + "requires": { + "axios": "0.19.0" + }, + "dependencies": { + "axios": { + "version": "0.19.0", + "requires": { + "follow-redirects": "1.5.10", + "is-buffer": "^2.0.2" + } + } + } + }, + "github-from-package": { + "version": "0.0.0" + }, + "github-slugger": { + "version": "1.2.1", + "requires": { + "emoji-regex": ">=6.0.0 <=6.1.1" + } + }, + "glob": { + "version": "7.1.6", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-parent": { + "version": "5.1.0", + "requires": { + "is-glob": "^4.0.1" + } + }, + "glob-stream": { + "version": "6.1.0", + "requires": { + "extend": "^3.0.0", + "glob": "^7.1.1", + "glob-parent": "^3.1.0", + "is-negated-glob": "^1.0.0", + "ordered-read-streams": "^1.0.0", + "pumpify": "^1.3.5", + "readable-stream": "^2.1.5", + "remove-trailing-separator": "^1.0.1", + "to-absolute-glob": "^2.0.0", + "unique-stream": "^2.0.2" + }, + "dependencies": { + "glob-parent": { + "version": "3.1.0", + "requires": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + } + }, + "is-glob": { + "version": "3.1.0", + "requires": { + "is-extglob": "^2.1.0" + } + } + } + }, + "global-dirs": { + "version": "0.1.1", + "requires": { + "ini": "^1.3.4" + } + }, + "global-modules": { + "version": "2.0.0", + "requires": { + "global-prefix": "^3.0.0" + } + }, + "global-prefix": { + "version": "3.0.0", + "requires": { + "ini": "^1.3.5", + "kind-of": "^6.0.2", + "which": "^1.3.1" + } + }, + "globals": { + "version": "11.12.0" + }, + "globals-docs": { + "version": "2.4.1" + }, + "globalthis": { + "version": "1.0.1", + "requires": { + "define-properties": "^1.1.3" + } + }, + "globby": { + "version": "10.0.2", + "requires": { + "@types/glob": "^7.1.1", + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.0.3", + "glob": "^7.1.3", + "ignore": "^5.1.1", + "merge2": "^1.2.3", + "slash": "^3.0.0" + } + }, + "go-ipfs-dep": { + "version": "0.4.22", + "requires": { + "go-platform": "^1.0.0", + "gunzip-maybe": "^1.4.1", + "node-fetch": "^2.3.0", + "pkg-conf": "^3.1.0", + "tar-fs": "^2.0.0", + "unzip-stream": "^0.3.0" + } + }, + "go-platform": { + "version": "1.0.0" + }, + "got": { + "version": "8.3.2", + "requires": { + "@sindresorhus/is": "^0.7.0", + "cacheable-request": "^2.1.1", + "decompress-response": "^3.3.0", + "duplexer3": "^0.1.4", + "get-stream": "^3.0.0", + "into-stream": "^3.1.0", + "is-retry-allowed": "^1.1.0", + "isurl": "^1.0.0-alpha5", + "lowercase-keys": "^1.0.0", + "mimic-response": "^1.0.0", + "p-cancelable": "^0.4.0", + "p-timeout": "^2.0.1", + "pify": "^3.0.0", + "safe-buffer": "^5.1.1", + "timed-out": "^4.0.1", + "url-parse-lax": "^3.0.0", + "url-to-options": "^1.0.1" + }, + "dependencies": { + "p-timeout": { + "version": "2.0.1", + "requires": { + "p-finally": "^1.0.0" + } + }, + "pify": { + "version": "3.0.0" + } + } + }, + "graceful-fs": { + "version": "4.2.3" + }, + "growl": { + "version": "1.10.5" + }, + "gunzip-maybe": { + "version": "1.4.1", + "requires": { + "browserify-zlib": "^0.1.4", + "is-deflate": "^1.0.0", + "is-gzip": "^1.0.0", + "peek-stream": "^1.1.0", + "pumpify": "^1.3.3", + "through2": "^2.0.3" + }, + "dependencies": { + "browserify-zlib": { + "version": "0.1.4", + "requires": { + "pako": "~0.2.0" + } + }, + "pako": { + "version": "0.2.9" + } + } + }, + "gzip-size": { + "version": "4.1.0", + "requires": { + "duplexer": "^0.1.1", + "pify": "^3.0.0" + }, + "dependencies": { + "pify": { + "version": "3.0.0" + } + } + }, + "hamt-sharding": { + "version": "0.0.2", + "requires": { + "sparse-array": "^1.3.1" + } + }, + "handlebars": { + "version": "4.7.2", + "requires": { + "neo-async": "^2.6.0", + "optimist": "^0.6.1", + "source-map": "^0.6.1", + "uglify-js": "^3.1.4" + } + }, + "hapi-pino": { + "version": "6.3.0", + "requires": { + "@hapi/hoek": "^8.3.0", + "abstract-logging": "^1.0.0", + "pino": "^5.13.5", + "pino-pretty": "^3.2.2" + } + }, + "har-schema": { + "version": "2.0.0" + }, + "har-validator": { + "version": "5.1.3", + "requires": { + "ajv": "^6.5.5", + "har-schema": "^2.0.0" + } + }, + "hard-rejection": { + "version": "2.1.0" + }, + "has": { + "version": "1.0.3", + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-ansi": { + "version": "2.0.0", + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "has-binary2": { + "version": "1.0.3", + "requires": { + "isarray": "2.0.1" + }, + "dependencies": { + "isarray": { + "version": "2.0.1" + } + } + }, + "has-cors": { + "version": "1.1.0" + }, + "has-flag": { + "version": "3.0.0" + }, + "has-symbol-support-x": { + "version": "1.4.2" + }, + "has-symbols": { + "version": "1.0.1" + }, + "has-to-string-tag-x": { + "version": "1.4.1", + "requires": { + "has-symbol-support-x": "^1.4.1" + } + }, + "has-unicode": { + "version": "2.0.1" + }, + "has-value": { + "version": "1.0.0", + "requires": { + "get-value": "^2.0.6", + "has-values": "^1.0.0", + "isobject": "^3.0.0" + } + }, + "has-values": { + "version": "1.0.0", + "requires": { + "is-number": "^3.0.0", + "kind-of": "^4.0.0" + }, + "dependencies": { + "is-buffer": { + "version": "1.1.6" + }, + "kind-of": { + "version": "4.0.0", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "has-yarn": { + "version": "2.1.0" + }, + "hash-base": { + "version": "3.0.4", + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "hash.js": { + "version": "1.1.7", + "requires": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, + "hasha": { + "version": "3.0.0", + "requires": { + "is-stream": "^1.0.1" + }, + "dependencies": { + "is-stream": { + "version": "1.1.0" + } + } + }, + "hashlru": { + "version": "2.3.0" + }, + "hast-util-is-element": { + "version": "1.0.3" + }, + "hast-util-sanitize": { + "version": "1.3.1", + "requires": { + "xtend": "^4.0.1" + } + }, + "hast-util-to-html": { + "version": "4.0.1", + "requires": { + "ccount": "^1.0.0", + "comma-separated-tokens": "^1.0.1", + "hast-util-is-element": "^1.0.0", + "hast-util-whitespace": "^1.0.0", + "html-void-elements": "^1.0.0", + "property-information": "^4.0.0", + "space-separated-tokens": "^1.0.0", + "stringify-entities": "^1.0.1", + "unist-util-is": "^2.0.0", + "xtend": "^4.0.1" + } + }, + "hast-util-whitespace": { + "version": "1.0.3" + }, + "hat": { + "version": "0.0.3" + }, + "he": { + "version": "1.2.0" + }, + "heap": { + "version": "0.2.6" + }, + "hi-base32": { + "version": "0.5.0" + }, + "highlight.js": { + "version": "9.18.0" + }, + "hmac-drbg": { + "version": "1.0.1", + "requires": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "homedir-polyfill": { + "version": "1.0.3", + "requires": { + "parse-passwd": "^1.0.0" + } + }, + "hoopy": { + "version": "0.1.4" + }, + "hosted-git-info": { + "version": "2.8.5" + }, + "html-escaper": { + "version": "2.0.0" + }, + "html-void-elements": { + "version": "1.0.4" + }, + "http-cache-semantics": { + "version": "3.8.1" + }, + "http-errors": { + "version": "1.7.2", + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + }, + "dependencies": { + "inherits": { + "version": "2.0.3" + } + } + }, + "http-parser-js": { + "version": "0.4.10" + }, + "http-proxy": { + "version": "1.18.0", + "requires": { + "eventemitter3": "^4.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "requires": { + "ms": "^2.1.1" + } + }, + "follow-redirects": { + "version": "1.9.0", + "requires": { + "debug": "^3.0.0" + } + }, + "ms": { + "version": "2.1.2" + } + } + }, + "http-signature": { + "version": "1.2.0", + "requires": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } + }, + "https-browserify": { + "version": "1.0.0" + }, + "https-proxy-agent": { + "version": "2.2.4", + "requires": { + "agent-base": "^4.3.0", + "debug": "^3.1.0" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.2" + } + } + }, + "human-signals": { + "version": "1.1.1" + }, + "human-to-milliseconds": { + "version": "2.0.0" + }, + "humanize-url": { + "version": "1.0.1", + "requires": { + "normalize-url": "^1.0.0", + "strip-url-auth": "^1.0.0" + } + }, + "iconv-lite": { + "version": "0.4.24", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ieee754": { + "version": "1.1.13" + }, + "iferr": { + "version": "0.1.5" + }, + "ignore": { + "version": "5.1.4" + }, + "ignore-walk": { + "version": "3.0.3", + "requires": { + "minimatch": "^3.0.4" + } + }, + "iltorb": { + "version": "2.4.4", + "requires": { + "detect-libc": "^1.0.3", + "nan": "^2.14.0", + "npmlog": "^4.1.2", + "prebuild-install": "^5.3.2", + "which-pm-runs": "^1.0.0" + } + }, + "immediate": { + "version": "3.2.3" + }, + "import-fresh": { + "version": "3.2.1", + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "dependencies": { + "resolve-from": { + "version": "4.0.0" + } + } + }, + "import-lazy": { + "version": "2.1.0" + }, + "import-local": { + "version": "2.0.0", + "requires": { + "pkg-dir": "^3.0.0", + "resolve-cwd": "^2.0.0" + }, + "dependencies": { + "resolve-cwd": { + "version": "2.0.0", + "requires": { + "resolve-from": "^3.0.0" + } + }, + "resolve-from": { + "version": "3.0.0" + } + } + }, + "imurmurhash": { + "version": "0.1.4" + }, + "indent-string": { + "version": "3.2.0" + }, + "indexof": { + "version": "0.0.1" + }, + "infer-owner": { + "version": "1.0.4" + }, + "inflight": { + "version": "1.0.6", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4" + }, + "ini": { + "version": "1.3.5" + }, + "inquirer": { + "version": "7.0.3", + "requires": { + "ansi-escapes": "^4.2.1", + "chalk": "^2.4.2", + "cli-cursor": "^3.1.0", + "cli-width": "^2.0.0", + "external-editor": "^3.0.3", + "figures": "^3.0.0", + "lodash": "^4.17.15", + "mute-stream": "0.0.8", + "run-async": "^2.2.0", + "rxjs": "^6.5.3", + "string-width": "^4.1.0", + "strip-ansi": "^5.1.0", + "through": "^2.3.6" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0" + }, + "cli-cursor": { + "version": "3.1.0", + "requires": { + "restore-cursor": "^3.1.0" + } + }, + "emoji-regex": { + "version": "8.0.0" + }, + "figures": { + "version": "3.1.0", + "requires": { + "escape-string-regexp": "^1.0.5" + } + }, + "is-fullwidth-code-point": { + "version": "3.0.0" + }, + "restore-cursor": { + "version": "3.1.0", + "requires": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + } + }, + "string-width": { + "version": "4.2.0", + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.0" + }, + "strip-ansi": { + "version": "6.0.0", + "requires": { + "ansi-regex": "^5.0.0" + } + } + } + }, + "strip-ansi": { + "version": "5.2.0", + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "interface-connection": { + "version": "0.3.3", + "requires": { + "pull-defer": "~0.2.3" + } + }, + "interface-datastore": { + "version": "0.7.0", + "requires": { + "class-is": "^1.1.0", + "err-code": "^1.1.2", + "uuid": "^3.2.2" + }, + "dependencies": { + "err-code": { + "version": "1.1.2" + } + } + }, + "interface-ipfs-core": { + "version": "0.127.0", + "requires": { + "chai": "^4.2.0", + "chai-as-promised": "^7.1.1", + "cids": "~0.7.1", + "delay": "^4.3.0", + "dirty-chai": "^2.0.1", + "hat": "0.0.3", + "ipfs-block": "~0.8.0", + "ipfs-unixfs": "^0.3.0", + "ipfs-utils": "^0.6.0", + "ipld-dag-cbor": "~0.15.0", + "ipld-dag-pb": "^0.18.1", + "is-ipfs": "~0.6.1", + "it-all": "^1.0.1", + "it-concat": "^1.0.0", + "it-last": "^1.0.1", + "it-pushable": "^1.3.1", + "multiaddr": "^7.2.1", + "multibase": "~0.6.0", + "multihashes": "~0.4.14", + "multihashing-async": "^0.8.0", + "peer-id": "~0.13.5", + "readable-stream": "^3.4.0" + }, + "dependencies": { + "bn.js": { + "version": "5.1.1" + }, + "ipfs-unixfs": { + "version": "0.3.0", + "requires": { + "err-code": "^2.0.0", + "protons": "^1.1.0" + } + }, + "libp2p-crypto": { + "version": "0.17.2", + "requires": { + "asmcrypto.js": "^2.3.2", + "asn1.js": "^5.2.0", + "bn.js": "^5.0.0", + "browserify-aes": "^1.2.0", + "bs58": "^4.0.1", + "err-code": "^1.1.2", + "iso-random-stream": "^1.1.0", + "keypair": "^1.0.1", + "libp2p-crypto-secp256k1": "~0.4.0", + "multihashing-async": "~0.8.0", + "node-forge": "~0.9.1", + "pem-jwk": "^2.0.0", + "protons": "^1.0.1", + "rsa-pem-to-jwk": "^1.1.3", + "tweetnacl": "^1.0.1", + "ursa-optional": "~0.10.1" + }, + "dependencies": { + "err-code": { + "version": "1.1.2" + } + } + }, + "libp2p-crypto-secp256k1": { + "version": "0.4.1", + "requires": { + "bs58": "^4.0.1", + "multihashing-async": "^0.8.0", + "nodeify": "^1.0.1", + "safe-buffer": "^5.1.2", + "secp256k1": "^3.6.2" + } + }, + "peer-id": { + "version": "0.13.6", + "requires": { + "cids": "~0.7.1", + "class-is": "^1.1.0", + "libp2p-crypto": "~0.17.0", + "multihashes": "~0.4.15", + "protons": "^1.0.1" + } + }, + "readable-stream": { + "version": "3.5.0", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "string_decoder": { + "version": "1.3.0", + "requires": { + "safe-buffer": "~5.2.0" + } + }, + "tweetnacl": { + "version": "1.0.2" + } + } + }, + "interpret": { + "version": "1.2.0" + }, + "into-stream": { + "version": "3.1.0", + "requires": { + "from2": "^2.1.1", + "p-is-promise": "^1.1.0" + } + }, + "invariant": { + "version": "2.2.4", + "requires": { + "loose-envify": "^1.0.0" + } + }, + "invert-kv": { + "version": "2.0.0" + }, + "ip": { + "version": "1.1.5" + }, + "ip-address": { + "version": "6.2.0", + "requires": { + "jsbn": "1.1.0", + "lodash.find": "4.6.0", + "lodash.max": "4.0.1", + "lodash.merge": "4.6.2", + "lodash.padstart": "4.6.1", + "lodash.repeat": "4.1.0", + "sprintf-js": "1.1.2" + }, + "dependencies": { + "jsbn": { + "version": "1.1.0" + }, + "sprintf-js": { + "version": "1.1.2" + } + } + }, + "ip-regex": { + "version": "4.1.0" + }, + "ipaddr.js": { + "version": "1.9.0" + }, + "ipfs": { + "version": "0.40.0", + "requires": { + "@hapi/ammo": "^4.0.0", + "@hapi/boom": "^7.4.3", + "@hapi/hapi": "^18.3.2", + "@hapi/joi": "^15.0.0", + "abort-controller": "^3.0.0", + "array-shuffle": "^1.0.1", + "async-iterator-all": "^1.0.0", + "async-iterator-first": "^1.0.0", + "async-iterator-to-pull-stream": "^1.3.0", + "async-iterator-to-stream": "^1.1.0", + "base32.js": "~0.1.0", + "bignumber.js": "^9.0.0", + "binary-querystring": "~0.1.2", + "bl": "^4.0.0", + "bs58": "^4.0.1", + "buffer-peek-stream": "^1.0.1", + "byteman": "^1.3.5", + "callbackify": "^1.1.0", + "cid-tool": "~0.4.0", + "cids": "~0.7.1", + "class-is": "^1.1.0", + "dag-cbor-links": "^1.3.2", + "datastore-core": "~0.7.0", + "datastore-pubsub": "^0.2.1", + "debug": "^4.1.0", + "dlv": "^1.1.3", + "err-code": "^2.0.0", + "explain-error": "^1.0.4", + "file-type": "^12.0.1", + "fnv1a": "^1.0.1", + "fsm-event": "^2.1.0", + "get-folder-size": "^2.0.0", + "glob": "^7.1.3", + "hapi-pino": "^6.1.0", + "hashlru": "^2.3.0", + "human-to-milliseconds": "^2.0.0", + "interface-datastore": "~0.8.0", + "ipfs-bitswap": "^0.26.0", + "ipfs-block": "~0.8.1", + "ipfs-block-service": "~0.16.0", + "ipfs-http-client": "^39.0.2", + "ipfs-http-response": "~0.4.0", + "ipfs-mfs": "^0.13.0", + "ipfs-multipart": "^0.2.0", + "ipfs-repo": "^0.29.3", + "ipfs-unixfs": "~0.1.16", + "ipfs-unixfs-exporter": "^0.38.0", + "ipfs-unixfs-importer": "^0.40.0", + "ipfs-utils": "~0.4.0", + "ipld": "~0.25.0", + "ipld-bitcoin": "~0.3.0", + "ipld-dag-cbor": "~0.15.0", + "ipld-dag-pb": "~0.18.0", + "ipld-ethereum": "^4.0.0", + "ipld-git": "~0.5.0", + "ipld-raw": "^4.0.0", + "ipld-zcash": "~0.4.0", + "ipns": "^0.6.1", + "is-domain-name": "^1.0.1", + "is-ipfs": "~0.6.1", + "is-pull-stream": "~0.0.0", + "is-stream": "^2.0.0", + "iso-url": "~0.4.6", + "it-pipe": "^1.0.1", + "it-to-stream": "^0.1.1", + "jsondiffpatch": "~0.3.11", + "just-safe-set": "^2.1.0", + "kind-of": "^6.0.2", + "ky": "^0.15.0", + "ky-universal": "~0.3.0", + "libp2p": "^0.26.2", + "libp2p-bootstrap": "~0.9.3", + "libp2p-crypto": "^0.16.2", + "libp2p-delegated-content-routing": "^0.3.1", + "libp2p-delegated-peer-routing": "^0.3.1", + "libp2p-floodsub": "^0.18.0", + "libp2p-gossipsub": "~0.0.5", + "libp2p-kad-dht": "~0.16.0", + "libp2p-keychain": "^0.5.1", + "libp2p-mdns": "~0.12.0", + "libp2p-record": "~0.7.0", + "libp2p-secio": "~0.11.0", + "libp2p-tcp": "^0.13.0", + "libp2p-webrtc-star": "~0.16.0", + "libp2p-websocket-star-multi": "~0.4.3", + "libp2p-websockets": "~0.12.3", + "lodash.flatten": "^4.4.0", + "mafmt": "^6.0.10", + "merge-options": "^2.0.0", + "mime-types": "^2.1.21", + "mkdirp": "~0.5.1", + "mortice": "^2.0.0", + "multiaddr": "^6.1.1", + "multiaddr-to-uri": "^5.0.0", + "multibase": "~0.6.0", + "multicodec": "~0.5.5", + "multihashes": "~0.4.14", + "multihashing-async": "^0.8.0", + "node-fetch": "^2.3.0", + "p-iteration": "^1.1.8", + "p-queue": "^6.1.0", + "peer-book": "^0.9.1", + "peer-id": "^0.12.2", + "peer-info": "~0.15.1", + "progress": "^2.0.1", + "prom-client": "^11.5.3", + "prometheus-gc-stats": "~0.6.0", + "promise-nodeify": "^3.0.1", + "promisify-es6": "^1.0.3", + "protons": "^1.0.1", + "pull-abortable": "^4.1.1", + "pull-cat": "^1.1.11", + "pull-defer": "~0.2.3", + "pull-file": "^1.1.0", + "pull-mplex": "~0.1.1", + "pull-ndjson": "^0.2.0", + "pull-pushable": "^2.2.0", + "pull-sort": "^1.0.1", + "pull-stream": "^3.6.14", + "pull-stream-to-async-iterator": "^1.0.2", + "pull-stream-to-stream": "^2.0.0", + "pull-traverse": "^1.0.3", + "readable-stream": "^3.4.0", + "receptacle": "^1.3.2", + "semver": "^6.3.0", + "stream-to-pull-stream": "^1.7.3", + "superstruct": "~0.6.2", + "tar-stream": "^2.0.0", + "temp": "~0.9.0", + "update-notifier": "^3.0.1", + "uri-to-multiaddr": "^3.0.1", + "varint": "^5.0.0", + "yargs": "^14.0.0", + "yargs-promise": "^1.1.0" + }, + "dependencies": { + "@hapi/ammo": { + "version": "4.0.0", + "requires": { + "@hapi/hoek": "8.x.x" + } + }, + "@hapi/joi": { + "version": "15.1.1", + "requires": { + "@hapi/address": "2.x.x", + "@hapi/bourne": "1.x.x", + "@hapi/hoek": "8.x.x", + "@hapi/topo": "3.x.x" + } + }, + "async": { + "version": "2.6.3", + "requires": { + "lodash": "^4.17.14" + } + }, + "concat-stream": { + "version": "2.0.0", + "requires": { + "inherits": "^2.0.3", + "readable-stream": "^3.0.2" + } + }, + "form-data": { + "version": "2.5.1", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + } + }, + "interface-datastore": { + "version": "0.8.0", + "requires": { + "class-is": "^1.1.0", + "err-code": "^2.0.0", + "uuid": "^3.2.2" + } + }, + "ip-regex": { + "version": "2.1.0" + }, + "ipfs-http-client": { + "version": "39.0.2", + "requires": { + "abort-controller": "^3.0.0", + "async": "^2.6.1", + "async-iterator-all": "^1.0.0", + "async-iterator-to-pull-stream": "^1.3.0", + "bignumber.js": "^9.0.0", + "bl": "^4.0.0", + "bs58": "^4.0.1", + "buffer": "^5.4.2", + "callbackify": "^1.1.0", + "cids": "~0.7.1", + "debug": "^4.1.0", + "delay": "^4.3.0", + "detect-node": "^2.0.4", + "end-of-stream": "^1.4.1", + "err-code": "^2.0.0", + "event-iterator": "^1.2.0", + "explain-error": "^1.0.4", + "flatmap": "0.0.3", + "form-data": "^2.5.1", + "fs-extra": "^8.1.0", + "glob": "^7.1.3", + "ipfs-block": "~0.8.1", + "ipfs-utils": "^0.4.0", + "ipld-dag-cbor": "~0.15.0", + "ipld-dag-pb": "^0.18.1", + "ipld-raw": "^4.0.0", + "is-ipfs": "~0.6.1", + "is-pull-stream": "0.0.0", + "is-stream": "^2.0.0", + "iso-stream-http": "~0.1.2", + "iso-url": "~0.4.6", + "it-glob": "0.0.6", + "it-to-stream": "^0.1.1", + "iterable-ndjson": "^1.1.0", + "just-kebab-case": "^1.1.0", + "just-map-keys": "^1.1.0", + "kind-of": "^6.0.2", + "ky": "^0.15.0", + "ky-universal": "^0.3.0", + "lru-cache": "^5.1.1", + "merge-options": "^2.0.0", + "multiaddr": "^6.0.6", + "multibase": "~0.6.0", + "multicodec": "~0.5.1", + "multihashes": "~0.4.14", + "once": "^1.4.0", + "peer-id": "~0.12.3", + "peer-info": "~0.15.1", + "promise-nodeify": "^3.0.1", + "promisify-es6": "^1.0.3", + "pull-defer": "~0.2.3", + "pull-stream": "^3.6.9", + "pull-stream-to-async-iterator": "^1.0.2", + "pull-to-stream": "~0.1.1", + "pump": "^3.0.0", + "qs": "^6.5.2", + "readable-stream": "^3.1.1", + "stream-to-pull-stream": "^1.7.2", + "tar-stream": "^2.0.1", + "through2": "^3.0.1" + } + }, + "ipfs-utils": { + "version": "0.4.2", + "requires": { + "buffer": "^5.2.1", + "err-code": "^2.0.0", + "fs-extra": "^8.1.0", + "is-buffer": "^2.0.3", + "is-electron": "^2.2.0", + "is-pull-stream": "0.0.0", + "is-stream": "^2.0.0", + "it-glob": "0.0.7", + "kind-of": "^6.0.2", + "pull-stream-to-async-iterator": "^1.0.2", + "readable-stream": "^3.4.0" + }, + "dependencies": { + "it-glob": { + "version": "0.0.7", + "requires": { + "fs-extra": "^8.1.0", + "minimatch": "^3.0.4" + } + } + } + }, + "is-ip": { + "version": "2.0.0", + "requires": { + "ip-regex": "^2.0.0" + } + }, + "it-glob": { + "version": "0.0.6", + "requires": { + "fs-extra": "^8.1.0", + "minimatch": "^3.0.4" + } + }, + "lru-cache": { + "version": "5.1.1", + "requires": { + "yallist": "^3.0.2" + } + }, + "multiaddr": { + "version": "6.1.1", + "requires": { + "bs58": "^4.0.1", + "class-is": "^1.1.0", + "hi-base32": "~0.5.0", + "ip": "^1.1.5", + "is-ip": "^2.0.0", + "varint": "^5.0.0" + } + }, + "multicodec": { + "version": "0.5.7", + "requires": { + "varint": "^5.0.0" + } + }, + "readable-stream": { + "version": "3.5.0", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "semver": { + "version": "6.3.0" + }, + "string_decoder": { + "version": "1.3.0", + "requires": { + "safe-buffer": "~5.2.0" + } + }, + "through2": { + "version": "3.0.1", + "requires": { + "readable-stream": "2 || 3" + } + }, + "yargs": { + "version": "14.2.2", + "requires": { + "cliui": "^5.0.0", + "decamelize": "^1.2.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^15.0.0" + } + }, + "yargs-parser": { + "version": "15.0.0", + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } + } + }, + "ipfs-bitswap": { + "version": "0.26.2", + "requires": { + "bignumber.js": "^9.0.0", + "callbackify": "^1.1.0", + "cids": "~0.7.0", + "debug": "^4.1.0", + "ipfs-block": "~0.8.0", + "just-debounce-it": "^1.1.0", + "moving-average": "^1.0.0", + "multicodec": "~0.5.7", + "multihashing-async": "^0.8.0", + "protons": "^1.0.1", + "pull-length-prefixed": "^1.3.1", + "pull-stream": "^3.6.9", + "varint-decoder": "~0.1.1" + }, + "dependencies": { + "multicodec": { + "version": "0.5.7", + "requires": { + "varint": "^5.0.0" + } + } + } + }, + "ipfs-block": { + "version": "0.8.1", + "requires": { + "cids": "~0.7.0", + "class-is": "^1.1.0" + } + }, + "ipfs-block-service": { + "version": "0.16.0", + "requires": { + "streaming-iterables": "^4.1.0" + } + }, + "ipfs-http-client": { + "version": "33.1.1", + "requires": { + "async": "^2.6.1", + "bignumber.js": "^9.0.0", + "bl": "^3.0.0", + "bs58": "^4.0.1", + "buffer": "^5.2.1", + "cids": "~0.7.1", + "debug": "^4.1.0", + "detect-node": "^2.0.4", + "end-of-stream": "^1.4.1", + "err-code": "^1.1.2", + "flatmap": "0.0.3", + "glob": "^7.1.3", + "ipfs-block": "~0.8.1", + "ipfs-utils": "~0.0.3", + "ipld-dag-cbor": "~0.15.0", + "ipld-dag-pb": "~0.17.3", + "ipld-raw": "^4.0.0", + "is-ipfs": "~0.6.1", + "is-pull-stream": "0.0.0", + "is-stream": "^2.0.0", + "iso-stream-http": "~0.1.2", + "iso-url": "~0.4.6", + "just-kebab-case": "^1.1.0", + "just-map-keys": "^1.1.0", + "kind-of": "^6.0.2", + "lru-cache": "^5.1.1", + "multiaddr": "^6.0.6", + "multibase": "~0.6.0", + "multicodec": "~0.5.1", + "multihashes": "~0.4.14", + "once": "^1.4.0", + "peer-id": "~0.12.2", + "peer-info": "~0.15.1", + "promisify-es6": "^1.0.3", + "pull-defer": "~0.2.3", + "pull-stream": "^3.6.9", + "pull-to-stream": "~0.1.1", + "pump": "^3.0.0", + "qs": "^6.5.2", + "readable-stream": "^3.1.1", + "stream-to-pull-stream": "^1.7.2", + "tar-stream": "^2.0.1", + "through2": "^3.0.1" + }, + "dependencies": { + "async": { + "version": "2.6.3", + "requires": { + "lodash": "^4.17.14" + } + }, + "bl": { + "version": "3.0.0", + "requires": { + "readable-stream": "^3.0.1" + } + }, + "concat-stream": { + "version": "2.0.0", + "requires": { + "inherits": "^2.0.3", + "readable-stream": "^3.0.2" + } + }, + "err-code": { + "version": "1.1.2" + }, + "ip-regex": { + "version": "2.1.0" + }, + "ipfs-utils": { + "version": "0.0.4", + "requires": { + "buffer": "^5.2.1", + "is-buffer": "^2.0.3", + "is-electron": "^2.2.0", + "is-pull-stream": "0.0.0", + "is-stream": "^2.0.0", + "kind-of": "^6.0.2", + "readable-stream": "^3.4.0" + } + }, + "ipld-dag-pb": { + "version": "0.17.4", + "requires": { + "cids": "~0.7.0", + "class-is": "^1.1.0", + "multicodec": "~0.5.1", + "multihashing-async": "~0.7.0", + "protons": "^1.0.1", + "stable": "~0.1.8" + } + }, + "is-ip": { + "version": "2.0.0", + "requires": { + "ip-regex": "^2.0.0" + } + }, + "lru-cache": { + "version": "5.1.1", + "requires": { + "yallist": "^3.0.2" + } + }, + "multiaddr": { + "version": "6.1.1", + "requires": { + "bs58": "^4.0.1", + "class-is": "^1.1.0", + "hi-base32": "~0.5.0", + "ip": "^1.1.5", + "is-ip": "^2.0.0", + "varint": "^5.0.0" + } + }, + "multicodec": { + "version": "0.5.7", + "requires": { + "varint": "^5.0.0" + } + }, + "multihashing-async": { + "version": "0.7.0", + "requires": { + "blakejs": "^1.1.0", + "buffer": "^5.2.1", + "err-code": "^1.1.2", + "js-sha3": "~0.8.0", + "multihashes": "~0.4.13", + "murmurhash3js-revisited": "^3.0.0" + } + }, + "readable-stream": { + "version": "3.5.0", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "string_decoder": { + "version": "1.3.0", + "requires": { + "safe-buffer": "~5.2.0" + } + }, + "through2": { + "version": "3.0.1", + "requires": { + "readable-stream": "2 || 3" + } + } + } + }, + "ipfs-http-response": { + "version": "0.4.0", + "requires": { + "cids": "~0.7.1", + "debug": "^4.1.1", + "file-type": "^8.0.0", + "filesize": "^3.6.1", + "get-stream": "^3.0.0", + "ipfs-unixfs": "~0.1.16", + "mime-types": "^2.1.21", + "multihashes": "~0.4.14", + "p-try-each": "^1.0.1", + "stream-to-blob": "^2.0.0" + }, + "dependencies": { + "file-type": { + "version": "8.1.0" + } + } + }, + "ipfs-mfs": { + "version": "0.13.2", + "requires": { + "@hapi/boom": "^7.4.2", + "@hapi/joi": "^15.1.0", + "async-iterator-last": "^1.0.0", + "cids": "~0.7.1", + "debug": "^4.1.0", + "err-code": "^2.0.0", + "hamt-sharding": "~0.0.2", + "interface-datastore": "~0.7.0", + "ipfs-multipart": "~0.2.0", + "ipfs-unixfs": "~0.1.16", + "ipfs-unixfs-exporter": "~0.38.0", + "ipfs-unixfs-importer": "~0.40.0", + "ipld-dag-pb": "~0.18.0", + "joi-browser": "^13.4.0", + "mortice": "^2.0.0", + "multicodec": "~0.5.3", + "multihashes": "~0.4.14", + "once": "^1.4.0", + "pull-stream": "^3.6.9" + }, + "dependencies": { + "@hapi/joi": { + "version": "15.1.1", + "requires": { + "@hapi/address": "2.x.x", + "@hapi/bourne": "1.x.x", + "@hapi/hoek": "8.x.x", + "@hapi/topo": "3.x.x" + } + }, + "multicodec": { + "version": "0.5.7", + "requires": { + "varint": "^5.0.0" + } + } + } + }, + "ipfs-multipart": { + "version": "0.2.0", + "requires": { + "@hapi/content": "^4.1.0", + "it-multipart": "~0.0.2" + } + }, + "ipfs-repo": { + "version": "0.29.3", + "requires": { + "base32.js": "~0.1.0", + "bignumber.js": "^9.0.0", + "bytes": "^3.1.0", + "cids": "~0.7.0", + "datastore-core": "~0.7.0", + "datastore-fs": "~0.9.0", + "datastore-level": "~0.14.0", + "debug": "^4.1.0", + "err-code": "^1.1.2", + "interface-datastore": "~0.7.0", + "ipfs-block": "~0.8.1", + "ipfs-repo-migrations": "~0.1.0", + "just-safe-get": "^1.3.0", + "just-safe-set": "^2.1.0", + "lodash.has": "^4.5.2", + "p-queue": "^6.0.0", + "pretty-bytes": "^5.3.0", + "proper-lockfile": "^4.0.0", + "sort-keys": "^3.0.0" + }, + "dependencies": { + "err-code": { + "version": "1.1.2" + } + } + }, + "ipfs-repo-migrations": { + "version": "0.1.1", + "requires": { + "chalk": "^2.4.2", + "datastore-fs": "~0.9.1", + "datastore-level": "~0.12.1", + "debug": "^4.1.0", + "interface-datastore": "~0.8.0", + "proper-lockfile": "^4.1.1", + "yargs": "^14.2.0", + "yargs-promise": "^1.1.0" + }, + "dependencies": { + "datastore-level": { + "version": "0.12.1", + "requires": { + "datastore-core": "~0.7.0", + "interface-datastore": "~0.7.0", + "level": "^5.0.1" + }, + "dependencies": { + "err-code": { + "version": "1.1.2" + }, + "interface-datastore": { + "version": "0.7.0", + "requires": { + "class-is": "^1.1.0", + "err-code": "^1.1.2", + "uuid": "^3.2.2" + } + } + } + }, + "interface-datastore": { + "version": "0.8.0", + "requires": { + "class-is": "^1.1.0", + "err-code": "^2.0.0", + "uuid": "^3.2.2" + } + }, + "yargs": { + "version": "14.2.2", + "requires": { + "cliui": "^5.0.0", + "decamelize": "^1.2.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^15.0.0" + } + }, + "yargs-parser": { + "version": "15.0.0", + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } + } + }, + "ipfs-unixfs": { + "version": "0.1.16", + "requires": { + "protons": "^1.0.1" + } + }, + "ipfs-unixfs-exporter": { + "version": "0.38.0", + "requires": { + "async-iterator-last": "^1.0.0", + "cids": "~0.7.1", + "err-code": "^2.0.0", + "hamt-sharding": "~0.0.2", + "ipfs-unixfs": "~0.1.16", + "ipfs-unixfs-importer": "~0.40.0" + } + }, + "ipfs-unixfs-importer": { + "version": "0.40.0", + "requires": { + "async-iterator-all": "^1.0.0", + "async-iterator-batch": "~0.0.1", + "async-iterator-first": "^1.0.0", + "bl": "^3.0.0", + "deep-extend": "~0.6.0", + "err-code": "^2.0.0", + "hamt-sharding": "~0.0.2", + "ipfs-unixfs": "~0.1.16", + "ipld-dag-pb": "^0.18.0", + "multicodec": "~0.5.1", + "multihashing-async": "~0.7.0", + "rabin-wasm": "~0.0.8", + "superstruct": "~0.6.1" + }, + "dependencies": { + "bl": { + "version": "3.0.0", + "requires": { + "readable-stream": "^3.0.1" + } + }, + "multicodec": { + "version": "0.5.7", + "requires": { + "varint": "^5.0.0" + } + }, + "multihashing-async": { + "version": "0.7.0", + "requires": { + "blakejs": "^1.1.0", + "buffer": "^5.2.1", + "err-code": "^1.1.2", + "js-sha3": "~0.8.0", + "multihashes": "~0.4.13", + "murmurhash3js-revisited": "^3.0.0" + }, + "dependencies": { + "err-code": { + "version": "1.1.2" + } + } + }, + "readable-stream": { + "version": "3.5.0", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "string_decoder": { + "version": "1.3.0", + "requires": { + "safe-buffer": "~5.2.0" + } + } + } + }, + "ipfs-utils": { + "version": "0.6.0", + "requires": { + "buffer": "^5.2.1", + "err-code": "^2.0.0", + "fs-extra": "^8.1.0", + "is-electron": "^2.2.0", + "it-glob": "0.0.7", + "ky": "^0.16.1", + "ky-universal": "^0.3.0", + "stream-to-it": "^0.2.0" + }, + "dependencies": { + "ky": { + "version": "0.16.2" + } + } + }, + "ipfsd-ctl": { + "version": "1.0.6", + "requires": { + "@hapi/boom": "^8.0.1", + "@hapi/hapi": "^18.3.2", + "@hapi/joi": "^16.1.8", + "debug": "^4.1.1", + "execa": "^4.0.0", + "fs-extra": "^8.1.0", + "go-ipfs-dep": "~0.4.22", + "ipfs": "0.40.0", + "ipfs-http-client": "^41.0.0", + "ipfs-utils": "^0.6.0", + "ky": "^0.16.1", + "ky-universal": "^0.3.0", + "merge-options": "^2.0.0", + "multiaddr": "^6.1.1", + "nanoid": "^2.1.9", + "resolve-cwd": "^3.0.0", + "temp-write": "^4.0.0" + }, + "dependencies": { + "@hapi/boom": { + "version": "8.0.1", + "requires": { + "@hapi/hoek": "8.x.x" + } + }, + "cross-spawn": { + "version": "7.0.1", + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "execa": { + "version": "4.0.0", + "requires": { + "cross-spawn": "^7.0.0", + "get-stream": "^5.0.0", + "human-signals": "^1.1.1", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.0", + "onetime": "^5.1.0", + "signal-exit": "^3.0.2", + "strip-final-newline": "^2.0.0" + } + }, + "get-stream": { + "version": "5.1.0", + "requires": { + "pump": "^3.0.0" + } + }, + "ip-regex": { + "version": "2.1.0" + }, + "ipfs-http-client": { + "version": "41.0.0", + "requires": { + "abort-controller": "^3.0.0", + "async-iterator-to-pull-stream": "^1.3.0", + "bignumber.js": "^9.0.0", + "bl": "^4.0.0", + "bs58": "^4.0.1", + "buffer": "^5.4.2", + "callbackify": "^1.1.0", + "cids": "~0.7.1", + "debug": "^4.1.0", + "err-code": "^2.0.0", + "explain-error": "^1.0.4", + "form-data": "^3.0.0", + "ipfs-block": "~0.8.1", + "ipfs-utils": "^0.4.2", + "ipld-dag-cbor": "~0.15.0", + "ipld-dag-pb": "^0.18.1", + "ipld-raw": "^4.0.0", + "is-ipfs": "~0.6.1", + "it-all": "^1.0.1", + "it-glob": "0.0.7", + "it-tar": "^1.1.1", + "it-to-stream": "^0.1.1", + "iterable-ndjson": "^1.1.0", + "ky": "^0.15.0", + "ky-universal": "^0.3.0", + "merge-options": "^2.0.0", + "multiaddr": "^6.0.6", + "multiaddr-to-uri": "^5.0.0", + "multibase": "~0.6.0", + "multicodec": "^1.0.0", + "multihashes": "~0.4.14", + "parse-duration": "^0.1.1", + "peer-id": "~0.12.3", + "peer-info": "~0.15.1", + "promise-nodeify": "^3.0.1" + }, + "dependencies": { + "ipfs-utils": { + "version": "0.4.2", + "requires": { + "buffer": "^5.2.1", + "err-code": "^2.0.0", + "fs-extra": "^8.1.0", + "is-buffer": "^2.0.3", + "is-electron": "^2.2.0", + "is-pull-stream": "0.0.0", + "is-stream": "^2.0.0", + "it-glob": "0.0.7", + "kind-of": "^6.0.2", + "pull-stream-to-async-iterator": "^1.0.2", + "readable-stream": "^3.4.0" + } + }, + "ky": { + "version": "0.15.0" + } + } + }, + "is-ip": { + "version": "2.0.0", + "requires": { + "ip-regex": "^2.0.0" + } + }, + "ky": { + "version": "0.16.2" + }, + "multiaddr": { + "version": "6.1.1", + "requires": { + "bs58": "^4.0.1", + "class-is": "^1.1.0", + "hi-base32": "~0.5.0", + "ip": "^1.1.5", + "is-ip": "^2.0.0", + "varint": "^5.0.0" + } + }, + "npm-run-path": { + "version": "4.0.1", + "requires": { + "path-key": "^3.0.0" + } + }, + "path-key": { + "version": "3.1.1" + }, + "readable-stream": { + "version": "3.5.0", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "shebang-command": { + "version": "2.0.0", + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0" + }, + "string_decoder": { + "version": "1.3.0", + "requires": { + "safe-buffer": "~5.2.0" + } + }, + "which": { + "version": "2.0.2", + "requires": { + "isexe": "^2.0.0" + } + } + } + }, + "ipld": { + "version": "0.25.3", + "requires": { + "cids": "~0.7.1", + "ipfs-block": "~0.8.1", + "ipld-dag-cbor": "~0.15.0", + "ipld-dag-pb": "~0.18.1", + "ipld-raw": "^4.0.0", + "merge-options": "^2.0.0", + "multicodec": "^1.0.0", + "typical": "^6.0.0" + } + }, + "ipld-bitcoin": { + "version": "0.3.1", + "requires": { + "bitcoinjs-lib": "^5.0.0", + "cids": "~0.7.0", + "multicodec": "^1.0.0", + "multihashes": "~0.4.14", + "multihashing-async": "~0.8.0" + } + }, + "ipld-dag-cbor": { + "version": "0.15.1", + "requires": { + "borc": "^2.1.0", + "cids": "~0.7.0", + "is-circular": "^1.0.2", + "multicodec": "^1.0.0", + "multihashing-async": "~0.8.0" + } + }, + "ipld-dag-pb": { + "version": "0.18.2", + "requires": { + "cids": "~0.7.1", + "class-is": "^1.1.0", + "multicodec": "^1.0.0", + "multihashing-async": "~0.8.0", + "protons": "^1.0.1", + "stable": "~0.1.8" + } + }, + "ipld-ethereum": { + "version": "4.0.1", + "requires": { + "cids": "~0.7.0", + "ethereumjs-account": "^3.0.0", + "ethereumjs-block": "^2.2.1", + "ethereumjs-tx": "^2.1.1", + "merkle-patricia-tree": "^3.0.0", + "multicodec": "^1.0.0", + "multihashes": "~0.4.15", + "multihashing-async": "~0.8.0", + "rlp": "^2.2.4" + } + }, + "ipld-git": { + "version": "0.5.1", + "requires": { + "cids": "~0.7.0", + "multicodec": "^1.0.0", + "multihashes": "~0.4.14", + "multihashing-async": "~0.8.0", + "smart-buffer": "^4.0.2", + "strftime": "~0.10.0" + } + }, + "ipld-raw": { + "version": "4.0.1", + "requires": { + "cids": "~0.7.0", + "multicodec": "^1.0.0", + "multihashing-async": "~0.8.0" + } + }, + "ipld-zcash": { + "version": "0.4.1", + "requires": { + "cids": "~0.7.1", + "multicodec": "^1.0.0", + "multihashes": "~0.4.15", + "multihashing-async": "~0.8.0", + "zcash-block": "^2.0.0" + } + }, + "ipns": { + "version": "0.6.1", + "requires": { + "base32-encode": "^1.1.0", + "debug": "^4.1.1", + "err-code": "^2.0.0", + "interface-datastore": "~0.7.0", + "left-pad": "^1.3.0", + "libp2p-crypto": "^0.16.2", + "multihashes": "~0.4.14", + "peer-id": "^0.12.2", + "promisify-es6": "^1.0.3", + "protons": "^1.0.1", + "timestamp-nano": "^1.0.0" + } + }, + "irregular-plurals": { + "version": "2.0.0" + }, + "is-absolute": { + "version": "1.0.0", + "requires": { + "is-relative": "^1.0.0", + "is-windows": "^1.0.1" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-alphabetical": { + "version": "1.0.3" + }, + "is-alphanumeric": { + "version": "1.0.0" + }, + "is-alphanumerical": { + "version": "1.0.3", + "requires": { + "is-alphabetical": "^1.0.0", + "is-decimal": "^1.0.0" + } + }, + "is-arrayish": { + "version": "0.2.1" + }, + "is-binary-path": { + "version": "2.1.0", + "requires": { + "binary-extensions": "^2.0.0" + } + }, + "is-buffer": { + "version": "2.0.4" + }, + "is-callable": { + "version": "1.1.5" + }, + "is-ci": { + "version": "2.0.0", + "requires": { + "ci-info": "^2.0.0" + } + }, + "is-circular": { + "version": "1.0.2" + }, + "is-data-descriptor": { + "version": "1.0.0", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-date-object": { + "version": "1.0.2" + }, + "is-decimal": { + "version": "1.0.3" + }, + "is-deflate": { + "version": "1.0.0" + }, + "is-descriptor": { + "version": "1.0.2", + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "is-directory": { + "version": "0.3.1" + }, + "is-domain-name": { + "version": "1.0.1" + }, + "is-electron": { + "version": "2.2.0" + }, + "is-electron-renderer": { + "version": "2.0.1" + }, + "is-extendable": { + "version": "0.1.1" + }, + "is-extglob": { + "version": "2.1.1" + }, + "is-finite": { + "version": "1.0.2", + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "is-fn": { + "version": "1.0.0" + }, + "is-fullwidth-code-point": { + "version": "2.0.0" + }, + "is-glob": { + "version": "4.0.1", + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-gzip": { + "version": "1.0.0" + }, + "is-hex-prefixed": { + "version": "1.0.0" + }, + "is-hexadecimal": { + "version": "1.0.3" + }, + "is-installed-globally": { + "version": "0.1.0", + "requires": { + "global-dirs": "^0.1.0", + "is-path-inside": "^1.0.0" + }, + "dependencies": { + "is-path-inside": { + "version": "1.0.1", + "requires": { + "path-is-inside": "^1.0.1" + } + } + } + }, + "is-ip": { + "version": "3.1.0", + "requires": { + "ip-regex": "^4.0.0" + } + }, + "is-ipfs": { + "version": "0.6.3", + "requires": { + "bs58": "^4.0.1", + "cids": "~0.7.0", + "mafmt": "^7.0.0", + "multiaddr": "^7.2.1", + "multibase": "~0.6.0", + "multihashes": "~0.4.13" + }, + "dependencies": { + "mafmt": { + "version": "7.0.0", + "requires": { + "multiaddr": "^7.0.0" + } + } + } + }, + "is-negated-glob": { + "version": "1.0.0" + }, + "is-npm": { + "version": "3.0.0" + }, + "is-number": { + "version": "3.0.0", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "is-buffer": { + "version": "1.1.6" + }, + "kind-of": { + "version": "3.2.2", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-obj": { + "version": "1.0.1" + }, + "is-object": { + "version": "1.0.1" + }, + "is-observable": { + "version": "1.1.0", + "requires": { + "symbol-observable": "^1.1.0" + } + }, + "is-path-cwd": { + "version": "2.2.0" + }, + "is-path-inside": { + "version": "3.0.2" + }, + "is-plain-obj": { + "version": "1.1.0" + }, + "is-plain-object": { + "version": "2.0.4", + "requires": { + "isobject": "^3.0.1" + } + }, + "is-promise": { + "version": "1.0.1" + }, + "is-pull-stream": { + "version": "0.0.0" + }, + "is-regex": { + "version": "1.0.5", + "requires": { + "has": "^1.0.3" + } + }, + "is-relative": { + "version": "1.0.0", + "requires": { + "is-unc-path": "^1.0.0" + } + }, + "is-retry-allowed": { + "version": "1.2.0" + }, + "is-ssh": { + "version": "1.3.1", + "requires": { + "protocols": "^1.1.0" + } + }, + "is-stream": { + "version": "2.0.0" + }, + "is-string": { + "version": "1.0.5" + }, + "is-symbol": { + "version": "1.0.3", + "requires": { + "has-symbols": "^1.0.1" + } + }, + "is-text-path": { + "version": "1.0.1", + "requires": { + "text-extensions": "^1.0.0" + } + }, + "is-typedarray": { + "version": "1.0.0" + }, + "is-unc-path": { + "version": "1.0.0", + "requires": { + "unc-path-regex": "^0.1.2" + } + }, + "is-utf8": { + "version": "0.2.1" + }, + "is-valid-glob": { + "version": "1.0.0" + }, + "is-whitespace-character": { + "version": "1.0.3" + }, + "is-windows": { + "version": "1.0.2" + }, + "is-word-character": { + "version": "1.0.3" + }, + "is-wsl": { + "version": "2.1.1" + }, + "is-yarn-global": { + "version": "0.3.0" + }, + "isarray": { + "version": "1.0.0" + }, + "isbinaryfile": { + "version": "3.0.3", + "requires": { + "buffer-alloc": "^1.2.0" + } + }, + "isexe": { + "version": "2.0.0" + }, + "iso-random-stream": { + "version": "1.1.1", + "requires": { + "buffer": "^5.4.3", + "readable-stream": "^3.4.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.5.0", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "string_decoder": { + "version": "1.3.0", + "requires": { + "safe-buffer": "~5.2.0" + } + } + } + }, + "iso-stream-http": { + "version": "0.1.2", + "requires": { + "builtin-status-codes": "^3.0.0", + "inherits": "^2.0.1", + "readable-stream": "^3.1.1" + }, + "dependencies": { + "readable-stream": { + "version": "3.5.0", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "string_decoder": { + "version": "1.3.0", + "requires": { + "safe-buffer": "~5.2.0" + } + } + } + }, + "iso-url": { + "version": "0.4.6" + }, + "isobject": { + "version": "3.0.1" + }, + "isstream": { + "version": "0.1.2" + }, + "istanbul-lib-coverage": { + "version": "2.0.5" + }, + "istanbul-lib-hook": { + "version": "2.0.7", + "requires": { + "append-transform": "^1.0.0" + } + }, + "istanbul-lib-instrument": { + "version": "3.3.0", + "requires": { + "@babel/generator": "^7.4.0", + "@babel/parser": "^7.4.3", + "@babel/template": "^7.4.0", + "@babel/traverse": "^7.4.3", + "@babel/types": "^7.4.0", + "istanbul-lib-coverage": "^2.0.5", + "semver": "^6.0.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0" + } + } + }, + "istanbul-lib-report": { + "version": "2.0.8", + "requires": { + "istanbul-lib-coverage": "^2.0.5", + "make-dir": "^2.1.0", + "supports-color": "^6.1.0" + } + }, + "istanbul-lib-source-maps": { + "version": "3.0.6", + "requires": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^2.0.5", + "make-dir": "^2.1.0", + "rimraf": "^2.6.3", + "source-map": "^0.6.1" + } + }, + "istanbul-reports": { + "version": "2.2.7", + "requires": { + "html-escaper": "^2.0.0" + } + }, + "isurl": { + "version": "1.0.0", + "requires": { + "has-to-string-tag-x": "^1.2.0", + "is-object": "^1.0.1" + } + }, + "it-all": { + "version": "1.0.1" + }, + "it-concat": { + "version": "1.0.0", + "requires": { + "bl": "^4.0.0" + } + }, + "it-glob": { + "version": "0.0.7", + "requires": { + "fs-extra": "^8.1.0", + "minimatch": "^3.0.4" + } + }, + "it-last": { + "version": "1.0.1" + }, + "it-multipart": { + "version": "0.0.2", + "requires": { + "buffer-indexof": "^1.1.1", + "parse-headers": "^2.0.2" + } + }, + "it-pipe": { + "version": "1.1.0" + }, + "it-pushable": { + "version": "1.4.0", + "requires": { + "fast-fifo": "^1.0.0" + } + }, + "it-reader": { + "version": "2.1.0", + "requires": { + "bl": "^4.0.0" + } + }, + "it-tar": { + "version": "1.1.1", + "requires": { + "bl": "^4.0.0", + "buffer": "^5.4.3", + "it-reader": "^2.0.0", + "p-defer": "^3.0.0" + } + }, + "it-to-stream": { + "version": "0.1.1", + "requires": { + "buffer": "^5.2.1", + "fast-fifo": "^1.0.0", + "get-iterator": "^1.0.2", + "p-defer": "^3.0.0", + "p-fifo": "^1.0.0", + "readable-stream": "^3.4.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.5.0", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "string_decoder": { + "version": "1.3.0", + "requires": { + "safe-buffer": "~5.2.0" + } + } + } + }, + "iterable-ndjson": { + "version": "1.1.0", + "requires": { + "string_decoder": "^1.2.0" + }, + "dependencies": { + "string_decoder": { + "version": "1.3.0", + "requires": { + "safe-buffer": "~5.2.0" + } + } + } + }, + "jest-worker": { + "version": "24.9.0", + "requires": { + "merge-stream": "^2.0.0", + "supports-color": "^6.1.0" + } + }, + "jmespath": { + "version": "0.15.0" + }, + "joi-browser": { + "version": "13.4.0" + }, + "joycon": { + "version": "2.2.5" + }, + "js-sha3": { + "version": "0.8.0" + }, + "js-tokens": { + "version": "4.0.0" + }, + "js-yaml": { + "version": "3.13.1", + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "jsbn": { + "version": "0.1.1" + }, + "jsesc": { + "version": "2.5.2" + }, + "json-buffer": { + "version": "3.0.0" + }, + "json-loader": { + "version": "0.5.7" + }, + "json-parse-better-errors": { + "version": "1.0.2" + }, + "json-schema": { + "version": "0.2.3" + }, + "json-schema-traverse": { + "version": "0.4.1" + }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1" + }, + "json-stringify-safe": { + "version": "5.0.1" + }, + "json-text-sequence": { + "version": "0.1.1", + "requires": { + "delimit-stream": "0.1.0" + } + }, + "json5": { + "version": "2.1.1", + "requires": { + "minimist": "^1.2.0" + } + }, + "jsonbird": { + "version": "2.2.2", + "requires": { + "jsonparse": "^1.2.0", + "readable-stream": "^2.1.4", + "shortid": "^2.2.6" + } + }, + "jsonc-parser": { + "version": "2.2.0" + }, + "jsondiffpatch": { + "version": "0.3.11", + "requires": { + "chalk": "^2.3.0", + "diff-match-patch": "^1.0.0" + } + }, + "jsonfile": { + "version": "4.0.0", + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "jsonparse": { + "version": "1.3.1" + }, + "jsprim": { + "version": "1.4.1", + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "just-debounce-it": { + "version": "1.1.0" + }, + "just-extend": { + "version": "4.0.2" + }, + "just-kebab-case": { + "version": "1.1.0" + }, + "just-map-keys": { + "version": "1.1.0" + }, + "just-safe-get": { + "version": "1.3.3" + }, + "just-safe-set": { + "version": "2.1.0" + }, + "k-bucket": { + "version": "5.0.0", + "requires": { + "randombytes": "^2.0.3" + } + }, + "karma": { + "version": "4.4.1", + "requires": { + "bluebird": "^3.3.0", + "body-parser": "^1.16.1", + "braces": "^3.0.2", + "chokidar": "^3.0.0", + "colors": "^1.1.0", + "connect": "^3.6.0", + "di": "^0.0.1", + "dom-serialize": "^2.2.0", + "flatted": "^2.0.0", + "glob": "^7.1.1", + "graceful-fs": "^4.1.2", + "http-proxy": "^1.13.0", + "isbinaryfile": "^3.0.0", + "lodash": "^4.17.14", + "log4js": "^4.0.0", + "mime": "^2.3.1", + "minimatch": "^3.0.2", + "optimist": "^0.6.1", + "qjobs": "^1.1.4", + "range-parser": "^1.2.0", + "rimraf": "^2.6.0", + "safe-buffer": "^5.0.1", + "socket.io": "2.1.1", + "source-map": "^0.6.1", + "tmp": "0.0.33", + "useragent": "2.3.0" + }, + "dependencies": { + "chokidar": { + "version": "3.3.1", + "requires": { + "anymatch": "~3.1.1", + "braces": "~3.0.2", + "fsevents": "~2.1.2", + "glob-parent": "~5.1.0", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.3.0" + } + }, + "readdirp": { + "version": "3.3.0", + "requires": { + "picomatch": "^2.0.7" + } + } + } + }, + "karma-chrome-launcher": { + "version": "3.1.0", + "requires": { + "which": "^1.2.1" + } + }, + "karma-cli": { + "version": "2.0.0", + "requires": { + "resolve": "^1.3.3" + } + }, + "karma-edge-launcher": { + "version": "0.4.2", + "requires": { + "edge-launcher": "1.2.2" + } + }, + "karma-firefox-launcher": { + "version": "1.3.0", + "requires": { + "is-wsl": "^2.1.0" + } + }, + "karma-junit-reporter": { + "version": "2.0.1", + "requires": { + "path-is-absolute": "^1.0.0", + "xmlbuilder": "12.0.0" + } + }, + "karma-mocha": { + "version": "1.3.0", + "requires": { + "minimist": "1.2.0" + } + }, + "karma-mocha-reporter": { + "version": "2.2.5", + "requires": { + "chalk": "^2.1.0", + "log-symbols": "^2.1.0", + "strip-ansi": "^4.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0" + }, + "strip-ansi": { + "version": "4.0.0", + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "karma-mocha-webworker": { + "version": "1.3.0", + "requires": { + "jsonbird": "^2.0.0", + "minimatch": "^3.0.3" + } + }, + "karma-sourcemap-loader": { + "version": "0.3.7", + "requires": { + "graceful-fs": "^4.1.2" + } + }, + "karma-webpack": { + "version": "4.0.2", + "requires": { + "clone-deep": "^4.0.1", + "loader-utils": "^1.1.0", + "neo-async": "^2.6.1", + "schema-utils": "^1.0.0", + "source-map": "^0.7.3", + "webpack-dev-middleware": "^3.7.0" + }, + "dependencies": { + "source-map": { + "version": "0.7.3" + } + } + }, + "keccak": { + "version": "1.4.0", + "requires": { + "bindings": "^1.2.1", + "inherits": "^2.0.3", + "nan": "^2.2.1", + "safe-buffer": "^5.1.0" + } + }, + "keypair": { + "version": "1.0.1" + }, + "keypress": { + "version": "0.2.1" + }, + "keyv": { + "version": "3.0.0", + "requires": { + "json-buffer": "3.0.0" + } + }, + "kind-of": { + "version": "6.0.3" + }, + "ky": { + "version": "0.15.0" + }, + "ky-universal": { + "version": "0.3.0", + "requires": { + "abort-controller": "^3.0.0", + "node-fetch": "^2.6.0" + } + }, + "latency-monitor": { + "version": "0.2.1", + "requires": { + "debug": "^2.6.0", + "lodash": "^4.17.4" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0" + } + } + }, + "latest-version": { + "version": "5.1.0", + "requires": { + "package-json": "^6.3.0" + } + }, + "lazystream": { + "version": "1.0.0", + "requires": { + "readable-stream": "^2.0.5" + } + }, + "lcid": { + "version": "2.0.0", + "requires": { + "invert-kv": "^2.0.0" + } + }, + "lead": { + "version": "1.0.0", + "requires": { + "flush-write-stream": "^1.0.2" + } + }, + "left-pad": { + "version": "1.3.0" + }, + "length-prefixed-stream": { + "version": "2.0.0", + "requires": { + "inherits": "^2.0.3", + "readable-stream": "^3.1.1", + "varint": "^5.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.5.0", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "string_decoder": { + "version": "1.3.0", + "requires": { + "safe-buffer": "~5.2.0" + } + } + } + }, + "level": { + "version": "5.0.1", + "requires": { + "level-js": "^4.0.0", + "level-packager": "^5.0.0", + "leveldown": "^5.0.0", + "opencollective-postinstall": "^2.0.0" + } + }, + "level-codec": { + "version": "9.0.1" + }, + "level-concat-iterator": { + "version": "2.0.1" + }, + "level-errors": { + "version": "2.0.1", + "requires": { + "errno": "~0.1.1" + } + }, + "level-iterator-stream": { + "version": "1.3.1", + "requires": { + "inherits": "^2.0.1", + "level-errors": "^1.0.3", + "readable-stream": "^1.0.33", + "xtend": "^4.0.0" + }, + "dependencies": { + "isarray": { + "version": "0.0.1" + }, + "level-errors": { + "version": "1.1.2", + "requires": { + "errno": "~0.1.1" + } + }, + "readable-stream": { + "version": "1.1.14", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + } + } + }, + "level-js": { + "version": "4.0.2", + "requires": { + "abstract-leveldown": "~6.0.1", + "immediate": "~3.2.3", + "inherits": "^2.0.3", + "ltgt": "^2.1.2", + "typedarray-to-buffer": "~3.1.5" + }, + "dependencies": { + "abstract-leveldown": { + "version": "6.0.3", + "requires": { + "level-concat-iterator": "~2.0.0", + "xtend": "~4.0.0" + } + } + } + }, + "level-mem": { + "version": "3.0.1", + "requires": { + "level-packager": "~4.0.0", + "memdown": "~3.0.0" + }, + "dependencies": { + "deferred-leveldown": { + "version": "4.0.2", + "requires": { + "abstract-leveldown": "~5.0.0", + "inherits": "^2.0.3" + } + }, + "encoding-down": { + "version": "5.0.4", + "requires": { + "abstract-leveldown": "^5.0.0", + "inherits": "^2.0.3", + "level-codec": "^9.0.0", + "level-errors": "^2.0.0", + "xtend": "^4.0.1" + } + }, + "level-iterator-stream": { + "version": "3.0.1", + "requires": { + "inherits": "^2.0.1", + "readable-stream": "^2.3.6", + "xtend": "^4.0.0" + } + }, + "level-packager": { + "version": "4.0.1", + "requires": { + "encoding-down": "~5.0.0", + "levelup": "^3.0.0" + } + }, + "levelup": { + "version": "3.1.1", + "requires": { + "deferred-leveldown": "~4.0.0", + "level-errors": "~2.0.0", + "level-iterator-stream": "~3.0.0", + "xtend": "~4.0.0" + } + }, + "memdown": { + "version": "3.0.0", + "requires": { + "abstract-leveldown": "~5.0.0", + "functional-red-black-tree": "~1.0.1", + "immediate": "~3.2.3", + "inherits": "~2.0.1", + "ltgt": "~2.2.0", + "safe-buffer": "~5.1.1" + } + }, + "safe-buffer": { + "version": "5.1.2" + } + } + }, + "level-packager": { + "version": "5.1.1", + "requires": { + "encoding-down": "^6.3.0", + "levelup": "^4.3.2" + }, + "dependencies": { + "abstract-leveldown": { + "version": "6.2.2", + "requires": { + "level-concat-iterator": "~2.0.0", + "level-supports": "~1.0.0", + "xtend": "~4.0.0" + } + }, + "deferred-leveldown": { + "version": "5.3.0", + "requires": { + "abstract-leveldown": "~6.2.1", + "inherits": "^2.0.3" + } + }, + "level-iterator-stream": { + "version": "4.0.2", + "requires": { + "inherits": "^2.0.4", + "readable-stream": "^3.4.0", + "xtend": "^4.0.2" + } + }, + "levelup": { + "version": "4.3.2", + "requires": { + "deferred-leveldown": "~5.3.0", + "level-errors": "~2.0.0", + "level-iterator-stream": "~4.0.0", + "level-supports": "~1.0.0", + "xtend": "~4.0.0" + } + }, + "readable-stream": { + "version": "3.5.0", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "string_decoder": { + "version": "1.3.0", + "requires": { + "safe-buffer": "~5.2.0" + } + } + } + }, + "level-supports": { + "version": "1.0.1", + "requires": { + "xtend": "^4.0.2" + } + }, + "level-ws": { + "version": "1.0.0", + "requires": { + "inherits": "^2.0.3", + "readable-stream": "^2.2.8", + "xtend": "^4.0.1" + } + }, + "leveldown": { + "version": "5.4.1", + "requires": { + "abstract-leveldown": "~6.2.1", + "napi-macros": "~2.0.0", + "node-gyp-build": "~4.1.0" + }, + "dependencies": { + "abstract-leveldown": { + "version": "6.2.2", + "requires": { + "level-concat-iterator": "~2.0.0", + "level-supports": "~1.0.0", + "xtend": "~4.0.0" + } + } + } + }, + "levelup": { + "version": "1.3.9", + "requires": { + "deferred-leveldown": "~1.2.1", + "level-codec": "~7.0.0", + "level-errors": "~1.0.3", + "level-iterator-stream": "~1.3.0", + "prr": "~1.0.1", + "semver": "~5.4.1", + "xtend": "~4.0.0" + }, + "dependencies": { + "level-codec": { + "version": "7.0.1" + }, + "level-errors": { + "version": "1.0.5", + "requires": { + "errno": "~0.1.1" + } + }, + "semver": { + "version": "5.4.1" + } + } + }, + "leven": { + "version": "3.1.0" + }, + "levenary": { + "version": "1.1.0", + "requires": { + "leven": "^3.1.0" + } + }, + "levn": { + "version": "0.3.0", + "requires": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + } + }, + "libp2p": { + "version": "0.26.2", + "requires": { + "async": "^2.6.2", + "bignumber.js": "^9.0.0", + "class-is": "^1.1.0", + "debug": "^4.1.1", + "err-code": "^1.1.2", + "fsm-event": "^2.1.0", + "hashlru": "^2.3.0", + "interface-connection": "~0.3.3", + "latency-monitor": "~0.2.1", + "libp2p-crypto": "~0.16.1", + "libp2p-websockets": "^0.12.2", + "mafmt": "^6.0.7", + "merge-options": "^1.0.1", + "moving-average": "^1.0.0", + "multiaddr": "^6.1.0", + "multistream-select": "~0.14.6", + "once": "^1.4.0", + "peer-book": "^0.9.1", + "peer-id": "^0.12.2", + "peer-info": "~0.15.1", + "promisify-es6": "^1.0.3", + "protons": "^1.0.1", + "pull-cat": "^1.1.11", + "pull-defer": "~0.2.3", + "pull-handshake": "^1.1.4", + "pull-reader": "^1.3.1", + "pull-stream": "^3.6.9", + "retimer": "^2.0.0", + "superstruct": "^0.6.0", + "xsalsa20": "^1.0.2" + }, + "dependencies": { + "async": { + "version": "2.6.3", + "requires": { + "lodash": "^4.17.14" + } + }, + "err-code": { + "version": "1.1.2" + }, + "ip-regex": { + "version": "2.1.0" + }, + "is-ip": { + "version": "2.0.0", + "requires": { + "ip-regex": "^2.0.0" + } + }, + "merge-options": { + "version": "1.0.1", + "requires": { + "is-plain-obj": "^1.1" + } + }, + "multiaddr": { + "version": "6.1.1", + "requires": { + "bs58": "^4.0.1", + "class-is": "^1.1.0", + "hi-base32": "~0.5.0", + "ip": "^1.1.5", + "is-ip": "^2.0.0", + "varint": "^5.0.0" + } + } + } + }, + "libp2p-bootstrap": { + "version": "0.9.7", + "requires": { + "async": "^2.6.1", + "debug": "^4.1.1", + "mafmt": "^6.0.4", + "multiaddr": "^6.0.3", + "peer-id": "~0.12.2", + "peer-info": "~0.15.1" + }, + "dependencies": { + "async": { + "version": "2.6.3", + "requires": { + "lodash": "^4.17.14" + } + }, + "ip-regex": { + "version": "2.1.0" + }, + "is-ip": { + "version": "2.0.0", + "requires": { + "ip-regex": "^2.0.0" + } + }, + "multiaddr": { + "version": "6.1.1", + "requires": { + "bs58": "^4.0.1", + "class-is": "^1.1.0", + "hi-base32": "~0.5.0", + "ip": "^1.1.5", + "is-ip": "^2.0.0", + "varint": "^5.0.0" + } + } + } + }, + "libp2p-crypto": { + "version": "0.16.3", + "requires": { + "asmcrypto.js": "^2.3.2", + "asn1.js": "^5.0.1", + "async": "^2.6.1", + "bn.js": "^4.11.8", + "browserify-aes": "^1.2.0", + "bs58": "^4.0.1", + "iso-random-stream": "^1.1.0", + "keypair": "^1.0.1", + "libp2p-crypto-secp256k1": "~0.3.0", + "multihashing-async": "~0.5.1", + "node-forge": "~0.9.1", + "pem-jwk": "^2.0.0", + "protons": "^1.0.1", + "rsa-pem-to-jwk": "^1.1.3", + "tweetnacl": "^1.0.0", + "ursa-optional": "~0.10.0" + }, + "dependencies": { + "async": { + "version": "2.6.3", + "requires": { + "lodash": "^4.17.14" + } + }, + "multihashing-async": { + "version": "0.5.2", + "requires": { + "blakejs": "^1.1.0", + "js-sha3": "~0.8.0", + "multihashes": "~0.4.13", + "murmurhash3js": "^3.0.1", + "nodeify": "^1.0.1" + } + }, + "tweetnacl": { + "version": "1.0.2" + } + } + }, + "libp2p-crypto-secp256k1": { + "version": "0.3.1", + "requires": { + "async": "^2.6.2", + "bs58": "^4.0.1", + "multihashing-async": "~0.6.0", + "nodeify": "^1.0.1", + "safe-buffer": "^5.1.2", + "secp256k1": "^3.6.2" + }, + "dependencies": { + "async": { + "version": "2.6.3", + "requires": { + "lodash": "^4.17.14" + } + }, + "multihashing-async": { + "version": "0.6.0", + "requires": { + "blakejs": "^1.1.0", + "js-sha3": "~0.8.0", + "multihashes": "~0.4.13", + "murmurhash3js": "^3.0.1", + "nodeify": "^1.0.1" + } + } + } + }, + "libp2p-delegated-content-routing": { + "version": "0.3.1", + "requires": { + "debug": "^4.1.1", + "multiaddr": "^6.1.0", + "p-queue": "^6.1.0" + }, + "dependencies": { + "ip-regex": { + "version": "2.1.0" + }, + "is-ip": { + "version": "2.0.0", + "requires": { + "ip-regex": "^2.0.0" + } + }, + "multiaddr": { + "version": "6.1.1", + "requires": { + "bs58": "^4.0.1", + "class-is": "^1.1.0", + "hi-base32": "~0.5.0", + "ip": "^1.1.5", + "is-ip": "^2.0.0", + "varint": "^5.0.0" + } + } + } + }, + "libp2p-delegated-peer-routing": { + "version": "0.3.1", + "requires": { + "debug": "^4.1.1", + "p-queue": "^6.1.0", + "peer-id": "~0.12.2" + } + }, + "libp2p-floodsub": { + "version": "0.18.0", + "requires": { + "async": "^2.6.2", + "bs58": "^4.0.1", + "debug": "^4.1.1", + "length-prefixed-stream": "^2.0.0", + "libp2p-crypto": "~0.16.1", + "libp2p-pubsub": "~0.2.0", + "protons": "^1.0.1", + "pull-length-prefixed": "^1.3.2", + "pull-pushable": "^2.2.0", + "pull-stream": "^3.6.9" + }, + "dependencies": { + "async": { + "version": "2.6.3", + "requires": { + "lodash": "^4.17.14" + } + } + } + }, + "libp2p-gossipsub": { + "version": "0.0.5", + "requires": { + "async": "^2.6.2", + "err-code": "^1.1.2", + "libp2p-floodsub": "~0.17.1", + "libp2p-pubsub": "~0.2.0", + "multistream-select": "~0.14.6", + "peer-id": "~0.12.2", + "peer-info": "~0.15.1", + "protons": "^1.0.1", + "pull-length-prefixed": "^1.3.3", + "pull-stream": "^3.6.13" + }, + "dependencies": { + "async": { + "version": "2.6.3", + "requires": { + "lodash": "^4.17.14" + } + }, + "err-code": { + "version": "1.1.2" + }, + "libp2p-floodsub": { + "version": "0.17.2", + "requires": { + "async": "^2.6.2", + "bs58": "^4.0.1", + "debug": "^4.1.1", + "length-prefixed-stream": "^2.0.0", + "libp2p-crypto": "~0.16.1", + "libp2p-pubsub": "~0.2.0", + "protons": "^1.0.1", + "pull-length-prefixed": "^1.3.2", + "pull-pushable": "^2.2.0", + "pull-stream": "^3.6.9" + } + } + } + }, + "libp2p-kad-dht": { + "version": "0.16.1", + "requires": { + "abort-controller": "^3.0.0", + "async": "^2.6.2", + "base32.js": "~0.1.0", + "chai-checkmark": "^1.0.1", + "cids": "~0.7.0", + "debug": "^4.1.1", + "err-code": "^1.1.2", + "hashlru": "^2.3.0", + "heap": "~0.2.6", + "interface-datastore": "~0.7.0", + "k-bucket": "^5.0.0", + "libp2p-crypto": "~0.16.1", + "libp2p-record": "~0.6.2", + "multihashes": "~0.4.14", + "multihashing-async": "~0.5.2", + "p-queue": "^6.0.0", + "p-times": "^2.1.0", + "peer-id": "~0.12.2", + "peer-info": "~0.15.1", + "promise-to-callback": "^1.0.0", + "promisify-es6": "^1.0.3", + "protons": "^1.0.1", + "pull-length-prefixed": "^1.3.2", + "pull-stream": "^3.6.9", + "varint": "^5.0.0", + "xor-distance": "^2.0.0" + }, + "dependencies": { + "async": { + "version": "2.6.3", + "requires": { + "lodash": "^4.17.14" + } + }, + "err-code": { + "version": "1.1.2" + }, + "libp2p-record": { + "version": "0.6.3", + "requires": { + "async": "^2.6.2", + "buffer-split": "^1.0.0", + "err-code": "^1.1.2", + "multihashes": "~0.4.14", + "multihashing-async": "~0.6.0", + "protons": "^1.0.1" + }, + "dependencies": { + "multihashing-async": { + "version": "0.6.0", + "requires": { + "blakejs": "^1.1.0", + "js-sha3": "~0.8.0", + "multihashes": "~0.4.13", + "murmurhash3js": "^3.0.1", + "nodeify": "^1.0.1" + } + } + } + }, + "multihashing-async": { + "version": "0.5.2", + "requires": { + "blakejs": "^1.1.0", + "js-sha3": "~0.8.0", + "multihashes": "~0.4.13", + "murmurhash3js": "^3.0.1", + "nodeify": "^1.0.1" + } + } + } + }, + "libp2p-keychain": { + "version": "0.5.5", + "requires": { + "err-code": "^2.0.0", + "interface-datastore": "^0.7.0", + "libp2p-crypto": "^0.16.2", + "merge-options": "^1.0.1", + "node-forge": "^0.9.1", + "promisify-es6": "^1.0.3", + "sanitize-filename": "^1.6.1" + }, + "dependencies": { + "merge-options": { + "version": "1.0.1", + "requires": { + "is-plain-obj": "^1.1" + } + } + } + }, + "libp2p-mdns": { + "version": "0.12.3", + "requires": { + "async": "^2.6.2", + "debug": "^4.1.1", + "libp2p-tcp": "~0.13.0", + "multiaddr": "^6.0.6", + "multicast-dns": "^7.2.0", + "peer-id": "~0.12.2", + "peer-info": "~0.15.1" + }, + "dependencies": { + "async": { + "version": "2.6.3", + "requires": { + "lodash": "^4.17.14" + } + }, + "ip-regex": { + "version": "2.1.0" + }, + "is-ip": { + "version": "2.0.0", + "requires": { + "ip-regex": "^2.0.0" + } + }, + "multiaddr": { + "version": "6.1.1", + "requires": { + "bs58": "^4.0.1", + "class-is": "^1.1.0", + "hi-base32": "~0.5.0", + "ip": "^1.1.5", + "is-ip": "^2.0.0", + "varint": "^5.0.0" + } + } + } + }, + "libp2p-pubsub": { + "version": "0.2.1", + "requires": { + "async": "^2.6.2", + "bs58": "^4.0.1", + "debug": "^4.1.1", + "err-code": "^1.1.2", + "length-prefixed-stream": "^2.0.0", + "libp2p-crypto": "~0.16.1", + "protons": "^1.0.1", + "pull-length-prefixed": "^1.3.1", + "pull-pushable": "^2.2.0", + "pull-stream": "^3.6.9", + "sinon": "^7.3.2", + "time-cache": "~0.3.0" + }, + "dependencies": { + "async": { + "version": "2.6.3", + "requires": { + "lodash": "^4.17.14" + } + }, + "err-code": { + "version": "1.1.2" + } + } + }, + "libp2p-record": { + "version": "0.7.1", + "requires": { + "buffer-split": "^1.0.0", + "err-code": "^2.0.0", + "multihashes": "~0.4.15", + "multihashing-async": "^0.8.0", + "protons": "^1.0.1" + } + }, + "libp2p-secio": { + "version": "0.11.1", + "requires": { + "async": "^2.6.1", + "debug": "^4.1.1", + "interface-connection": "~0.3.2", + "libp2p-crypto": "~0.16.0", + "multihashing-async": "~0.5.2", + "peer-id": "~0.12.2", + "peer-info": "~0.15.1", + "protons": "^1.0.1", + "pull-defer": "~0.2.3", + "pull-handshake": "^1.1.4", + "pull-length-prefixed": "^1.3.1", + "pull-stream": "^3.6.9" + }, + "dependencies": { + "async": { + "version": "2.6.3", + "requires": { + "lodash": "^4.17.14" + } + }, + "multihashing-async": { + "version": "0.5.2", + "requires": { + "blakejs": "^1.1.0", + "js-sha3": "~0.8.0", + "multihashes": "~0.4.13", + "murmurhash3js": "^3.0.1", + "nodeify": "^1.0.1" + } + } + } + }, + "libp2p-tcp": { + "version": "0.13.2", + "requires": { + "class-is": "^1.1.0", + "debug": "^4.1.1", + "interface-connection": "~0.3.3", + "ip-address": "^6.1.0", + "lodash.includes": "^4.3.0", + "lodash.isfunction": "^3.0.9", + "mafmt": "^6.0.7", + "multiaddr": "^6.1.0", + "once": "^1.4.0", + "stream-to-pull-stream": "^1.7.3" + }, + "dependencies": { + "ip-regex": { + "version": "2.1.0" + }, + "is-ip": { + "version": "2.0.0", + "requires": { + "ip-regex": "^2.0.0" + } + }, + "multiaddr": { + "version": "6.1.1", + "requires": { + "bs58": "^4.0.1", + "class-is": "^1.1.0", + "hi-base32": "~0.5.0", + "ip": "^1.1.5", + "is-ip": "^2.0.0", + "varint": "^5.0.0" + } + } + } + }, + "libp2p-webrtc-star": { + "version": "0.16.1", + "requires": { + "@hapi/hapi": "^18.3.1", + "@hapi/inert": "^5.2.0", + "async": "^2.6.2", + "class-is": "^1.1.0", + "debug": "^4.1.1", + "epimetheus": "^1.0.92", + "interface-connection": "~0.3.3", + "mafmt": "^6.0.7", + "minimist": "^1.2.0", + "multiaddr": "^6.0.6", + "once": "^1.4.0", + "peer-id": "~0.12.2", + "peer-info": "~0.15.1", + "pull-stream": "^3.6.9", + "simple-peer": "^9.3.0", + "socket.io": "^2.1.1", + "socket.io-client": "^2.1.1", + "stream-to-pull-stream": "^1.7.3" + }, + "dependencies": { + "async": { + "version": "2.6.3", + "requires": { + "lodash": "^4.17.14" + } + }, + "base64id": { + "version": "2.0.0" + }, + "engine.io": { + "version": "3.4.0", + "requires": { + "accepts": "~1.3.4", + "base64id": "2.0.0", + "cookie": "0.3.1", + "debug": "~4.1.0", + "engine.io-parser": "~2.2.0", + "ws": "^7.1.2" + } + }, + "engine.io-parser": { + "version": "2.2.0", + "requires": { + "after": "0.8.2", + "arraybuffer.slice": "~0.0.7", + "base64-arraybuffer": "0.1.5", + "blob": "0.0.5", + "has-binary2": "~1.0.2" + } + }, + "ip-regex": { + "version": "2.1.0" + }, + "is-ip": { + "version": "2.0.0", + "requires": { + "ip-regex": "^2.0.0" + } + }, + "isarray": { + "version": "2.0.1" + }, + "multiaddr": { + "version": "6.1.1", + "requires": { + "bs58": "^4.0.1", + "class-is": "^1.1.0", + "hi-base32": "~0.5.0", + "ip": "^1.1.5", + "is-ip": "^2.0.0", + "varint": "^5.0.0" + } + }, + "socket.io": { + "version": "2.3.0", + "requires": { + "debug": "~4.1.0", + "engine.io": "~3.4.0", + "has-binary2": "~1.0.2", + "socket.io-adapter": "~1.1.0", + "socket.io-client": "2.3.0", + "socket.io-parser": "~3.4.0" + } + }, + "socket.io-parser": { + "version": "3.4.0", + "requires": { + "component-emitter": "1.2.1", + "debug": "~4.1.0", + "isarray": "2.0.1" + } + }, + "ws": { + "version": "7.2.1" + } + } + }, + "libp2p-websocket-star": { + "version": "0.10.2", + "requires": { + "async": "^2.6.1", + "class-is": "^1.1.0", + "debug": "^4.1.1", + "interface-connection": "~0.3.2", + "libp2p-crypto": "~0.16.0", + "mafmt": "^6.0.4", + "multiaddr": "^6.0.3", + "nanoid": "^2.0.0", + "once": "^1.4.0", + "peer-id": "~0.12.2", + "peer-info": "~0.15.1", + "pull-stream": "^3.6.9", + "socket.io-client": "^2.1.1", + "socket.io-pull-stream": "~0.1.5" + }, + "dependencies": { + "async": { + "version": "2.6.3", + "requires": { + "lodash": "^4.17.14" + } + }, + "ip-regex": { + "version": "2.1.0" + }, + "is-ip": { + "version": "2.0.0", + "requires": { + "ip-regex": "^2.0.0" + } + }, + "multiaddr": { + "version": "6.1.1", + "requires": { + "bs58": "^4.0.1", + "class-is": "^1.1.0", + "hi-base32": "~0.5.0", + "ip": "^1.1.5", + "is-ip": "^2.0.0", + "varint": "^5.0.0" + } + } + } + }, + "libp2p-websocket-star-multi": { + "version": "0.4.4", + "requires": { + "async": "^2.6.2", + "debug": "^4.1.1", + "libp2p-websocket-star": "~0.10.2", + "mafmt": "^6.0.7", + "multiaddr": "^6.0.6", + "once": "^1.4.0" + }, + "dependencies": { + "async": { + "version": "2.6.3", + "requires": { + "lodash": "^4.17.14" + } + }, + "ip-regex": { + "version": "2.1.0" + }, + "is-ip": { + "version": "2.0.0", + "requires": { + "ip-regex": "^2.0.0" + } + }, + "multiaddr": { + "version": "6.1.1", + "requires": { + "bs58": "^4.0.1", + "class-is": "^1.1.0", + "hi-base32": "~0.5.0", + "ip": "^1.1.5", + "is-ip": "^2.0.0", + "varint": "^5.0.0" + } + } + } + }, + "libp2p-websockets": { + "version": "0.12.4", + "requires": { + "class-is": "^1.1.0", + "debug": "^4.1.1", + "interface-connection": "~0.3.3", + "mafmt": "^6.0.7", + "multiaddr-to-uri": "^5.0.0" + } + }, + "lines-and-columns": { + "version": "1.1.6" + }, + "listr": { + "version": "0.14.3", + "requires": { + "@samverschueren/stream-to-observable": "^0.3.0", + "is-observable": "^1.1.0", + "is-promise": "^2.1.0", + "is-stream": "^1.1.0", + "listr-silent-renderer": "^1.1.1", + "listr-update-renderer": "^0.5.0", + "listr-verbose-renderer": "^0.5.0", + "p-map": "^2.0.0", + "rxjs": "^6.3.3" + }, + "dependencies": { + "date-fns": { + "version": "1.30.1" + }, + "is-promise": { + "version": "2.1.0" + }, + "is-stream": { + "version": "1.1.0" + }, + "listr-verbose-renderer": { + "version": "0.5.0", + "requires": { + "chalk": "^2.4.1", + "cli-cursor": "^2.1.0", + "date-fns": "^1.27.2", + "figures": "^2.0.0" + } + }, + "p-map": { + "version": "2.1.0" + } + } + }, + "listr-silent-renderer": { + "version": "1.1.1" + }, + "listr-update-renderer": { + "version": "0.5.0", + "requires": { + "chalk": "^1.1.3", + "cli-truncate": "^0.2.1", + "elegant-spinner": "^1.0.1", + "figures": "^1.7.0", + "indent-string": "^3.0.0", + "log-symbols": "^1.0.2", + "log-update": "^2.3.0", + "strip-ansi": "^3.0.1" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1" + }, + "chalk": { + "version": "1.1.3", + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "figures": { + "version": "1.7.0", + "requires": { + "escape-string-regexp": "^1.0.5", + "object-assign": "^4.1.0" + } + }, + "log-symbols": { + "version": "1.0.2", + "requires": { + "chalk": "^1.0.0" + } + }, + "supports-color": { + "version": "2.0.0" + } + } + }, + "listr-verbose-renderer": { + "version": "0.6.0", + "requires": { + "chalk": "^2.4.1", + "cli-cursor": "^2.1.0", + "date-fns": "^2.0.1", + "figures": "^2.0.0" + } + }, + "livereload-js": { + "version": "2.4.0" + }, + "load-json-file": { + "version": "4.0.0", + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" + }, + "dependencies": { + "pify": { + "version": "3.0.0" + } + } + }, + "loader-runner": { + "version": "2.4.0" + }, + "loader-utils": { + "version": "1.2.3", + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^2.0.0", + "json5": "^1.0.1" + }, + "dependencies": { + "json5": { + "version": "1.0.1", + "requires": { + "minimist": "^1.2.0" + } + } + } + }, + "locate-path": { + "version": "3.0.0", + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "lodash": { + "version": "4.17.15" + }, + "lodash._reinterpolate": { + "version": "3.0.0" + }, + "lodash.find": { + "version": "4.6.0" + }, + "lodash.flatten": { + "version": "4.4.0" + }, + "lodash.flattendeep": { + "version": "4.4.0" + }, + "lodash.has": { + "version": "4.5.2" + }, + "lodash.includes": { + "version": "4.3.0" + }, + "lodash.isfunction": { + "version": "3.0.9" + }, + "lodash.ismatch": { + "version": "4.4.0" + }, + "lodash.max": { + "version": "4.0.1" + }, + "lodash.merge": { + "version": "4.6.2" + }, + "lodash.padstart": { + "version": "4.6.1" + }, + "lodash.repeat": { + "version": "4.1.0" + }, + "lodash.template": { + "version": "4.5.0", + "requires": { + "lodash._reinterpolate": "^3.0.0", + "lodash.templatesettings": "^4.0.0" + } + }, + "lodash.templatesettings": { + "version": "4.2.0", + "requires": { + "lodash._reinterpolate": "^3.0.0" + } + }, + "lodash.throttle": { + "version": "4.1.1" + }, + "log-symbols": { + "version": "2.2.0", + "requires": { + "chalk": "^2.0.1" + } + }, + "log-update": { + "version": "2.3.0", + "requires": { + "ansi-escapes": "^3.0.0", + "cli-cursor": "^2.0.0", + "wrap-ansi": "^3.0.1" + }, + "dependencies": { + "ansi-escapes": { + "version": "3.2.0" + }, + "ansi-regex": { + "version": "3.0.0" + }, + "string-width": { + "version": "2.1.1", + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "requires": { + "ansi-regex": "^3.0.0" + } + }, + "wrap-ansi": { + "version": "3.0.1", + "requires": { + "string-width": "^2.1.1", + "strip-ansi": "^4.0.0" + } + } + } + }, + "log4js": { + "version": "4.5.1", + "requires": { + "date-format": "^2.0.0", + "debug": "^4.1.1", + "flatted": "^2.0.0", + "rfdc": "^1.1.4", + "streamroller": "^1.0.6" + } + }, + "lolex": { + "version": "4.2.0" + }, + "long": { + "version": "4.0.0" + }, + "longest-streak": { + "version": "2.0.3" + }, + "looper": { + "version": "3.0.0" + }, + "loose-envify": { + "version": "1.4.0", + "requires": { + "js-tokens": "^3.0.0 || ^4.0.0" + } + }, + "loud-rejection": { + "version": "1.6.0", + "requires": { + "currently-unhandled": "^0.4.1", + "signal-exit": "^3.0.0" + } + }, + "lowercase-keys": { + "version": "1.0.1" + }, + "lru-cache": { + "version": "4.1.5", + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + }, + "dependencies": { + "yallist": { + "version": "2.1.2" + } + } + }, + "ltgt": { + "version": "2.2.1" + }, + "mafmt": { + "version": "6.0.10", + "requires": { + "multiaddr": "^6.1.0" + }, + "dependencies": { + "ip-regex": { + "version": "2.1.0" + }, + "is-ip": { + "version": "2.0.0", + "requires": { + "ip-regex": "^2.0.0" + } + }, + "multiaddr": { + "version": "6.1.1", + "requires": { + "bs58": "^4.0.1", + "class-is": "^1.1.0", + "hi-base32": "~0.5.0", + "ip": "^1.1.5", + "is-ip": "^2.0.0", + "varint": "^5.0.0" + } + } + } + }, + "make-dir": { + "version": "2.1.0", + "requires": { + "pify": "^4.0.1", + "semver": "^5.6.0" + } + }, + "mamacro": { + "version": "0.0.3" + }, + "map-age-cleaner": { + "version": "0.1.3", + "requires": { + "p-defer": "^1.0.0" + }, + "dependencies": { + "p-defer": { + "version": "1.0.0" + } + } + }, + "map-cache": { + "version": "0.2.2" + }, + "map-obj": { + "version": "1.0.1" + }, + "map-visit": { + "version": "1.0.0", + "requires": { + "object-visit": "^1.0.0" + } + }, + "markdown-escapes": { + "version": "1.0.3" + }, + "markdown-table": { + "version": "1.1.3" + }, + "md5.js": { + "version": "1.3.5", + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "mdast-util-compact": { + "version": "1.0.4", + "requires": { + "unist-util-visit": "^1.1.0" + } + }, + "mdast-util-definitions": { + "version": "1.2.5", + "requires": { + "unist-util-visit": "^1.0.0" + } + }, + "mdast-util-inject": { + "version": "1.1.0", + "requires": { + "mdast-util-to-string": "^1.0.0" + } + }, + "mdast-util-to-hast": { + "version": "3.0.4", + "requires": { + "collapse-white-space": "^1.0.0", + "detab": "^2.0.0", + "mdast-util-definitions": "^1.2.0", + "mdurl": "^1.0.1", + "trim": "0.0.1", + "trim-lines": "^1.0.0", + "unist-builder": "^1.0.1", + "unist-util-generated": "^1.1.0", + "unist-util-position": "^3.0.0", + "unist-util-visit": "^1.1.0", + "xtend": "^4.0.1" + } + }, + "mdast-util-to-string": { + "version": "1.0.7" + }, + "mdast-util-toc": { + "version": "3.1.0", + "requires": { + "github-slugger": "^1.2.1", + "mdast-util-to-string": "^1.0.5", + "unist-util-is": "^2.1.2", + "unist-util-visit": "^1.1.0" + } + }, + "mdurl": { + "version": "1.0.1" + }, + "media-typer": { + "version": "0.3.0" + }, + "mem": { + "version": "4.3.0", + "requires": { + "map-age-cleaner": "^0.1.1", + "mimic-fn": "^2.0.0", + "p-is-promise": "^2.0.0" + }, + "dependencies": { + "p-is-promise": { + "version": "2.1.0" + } + } + }, + "memdown": { + "version": "1.4.1", + "requires": { + "abstract-leveldown": "~2.7.1", + "functional-red-black-tree": "^1.0.1", + "immediate": "^3.2.3", + "inherits": "~2.0.1", + "ltgt": "~2.2.0", + "safe-buffer": "~5.1.1" + }, + "dependencies": { + "abstract-leveldown": { + "version": "2.7.2", + "requires": { + "xtend": "~4.0.0" + } + }, + "safe-buffer": { + "version": "5.1.2" + } + } + }, + "memory-fs": { + "version": "0.4.1", + "requires": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + } + }, + "meow": { + "version": "5.0.0", + "requires": { + "camelcase-keys": "^4.0.0", + "decamelize-keys": "^1.0.0", + "loud-rejection": "^1.0.0", + "minimist-options": "^3.0.1", + "normalize-package-data": "^2.3.4", + "read-pkg-up": "^3.0.0", + "redent": "^2.0.0", + "trim-newlines": "^2.0.0", + "yargs-parser": "^10.0.0" + }, + "dependencies": { + "camelcase": { + "version": "4.1.0" + }, + "yargs-parser": { + "version": "10.1.0", + "requires": { + "camelcase": "^4.1.0" + } + } + } + }, + "merge-descriptors": { + "version": "1.0.1" + }, + "merge-options": { + "version": "2.0.0", + "requires": { + "is-plain-obj": "^2.0.0" + }, + "dependencies": { + "is-plain-obj": { + "version": "2.1.0" + } + } + }, + "merge-source-map": { + "version": "1.1.0", + "requires": { + "source-map": "^0.6.1" + } + }, + "merge-stream": { + "version": "2.0.0" + }, + "merge2": { + "version": "1.3.0" + }, + "merkle-lib": { + "version": "2.0.10" + }, + "merkle-patricia-tree": { + "version": "3.0.0", + "requires": { + "async": "^2.6.1", + "ethereumjs-util": "^5.2.0", + "level-mem": "^3.0.1", + "level-ws": "^1.0.0", + "readable-stream": "^3.0.6", + "rlp": "^2.0.0", + "semaphore": ">=1.0.1" + }, + "dependencies": { + "async": { + "version": "2.6.3", + "requires": { + "lodash": "^4.17.14" + } + }, + "readable-stream": { + "version": "3.5.0", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "string_decoder": { + "version": "1.3.0", + "requires": { + "safe-buffer": "~5.2.0" + } + } + } + }, + "methods": { + "version": "1.1.2" + }, + "micromatch": { + "version": "3.1.10", + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "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.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + }, + "dependencies": { + "braces": { + "version": "2.3.2", + "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.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-extendable": { + "version": "0.1.1" + } + } + }, + "define-property": { + "version": "2.0.2", + "requires": { + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" + } + }, + "extend-shallow": { + "version": "3.0.2", + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + } + }, + "fill-range": { + "version": "4.0.0", + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-extendable": { + "version": "0.1.1" + } + } + }, + "is-extendable": { + "version": "1.0.1", + "requires": { + "is-plain-object": "^2.0.4" + } + }, + "to-regex-range": { + "version": "2.1.1", + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } + } + } + }, + "miller-rabin": { + "version": "4.0.1", + "requires": { + "bn.js": "^4.0.0", + "brorand": "^1.0.1" + } + }, + "mime": { + "version": "2.4.4" + }, + "mime-db": { + "version": "1.43.0" + }, + "mime-types": { + "version": "2.1.26", + "requires": { + "mime-db": "1.43.0" + } + }, + "mimic-fn": { + "version": "2.1.0" + }, + "mimic-response": { + "version": "1.0.1" + }, + "min-indent": { + "version": "1.0.0" + }, + "minimalistic-assert": { + "version": "1.0.1" + }, + "minimalistic-crypto-utils": { + "version": "1.0.1" + }, + "minimatch": { + "version": "3.0.4", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.0" + }, + "minimist-options": { + "version": "3.0.2", + "requires": { + "arrify": "^1.0.1", + "is-plain-obj": "^1.1.0" + } + }, + "minipass": { + "version": "3.1.1", + "requires": { + "yallist": "^4.0.0" + }, + "dependencies": { + "yallist": { + "version": "4.0.0" + } + } + }, + "minipass-collect": { + "version": "1.0.2", + "requires": { + "minipass": "^3.0.0" + } + }, + "minipass-flush": { + "version": "1.0.5", + "requires": { + "minipass": "^3.0.0" + } + }, + "minipass-pipeline": { + "version": "1.2.2", + "requires": { + "minipass": "^3.0.0" + } + }, + "minizlib": { + "version": "1.3.3", + "requires": { + "minipass": "^2.9.0" + }, + "dependencies": { + "minipass": { + "version": "2.9.0", + "requires": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + } + } + } + }, + "mississippi": { + "version": "3.0.0", + "requires": { + "concat-stream": "^1.5.0", + "duplexify": "^3.4.2", + "end-of-stream": "^1.1.0", + "flush-write-stream": "^1.0.0", + "from2": "^2.1.0", + "parallel-transform": "^1.1.0", + "pump": "^3.0.0", + "pumpify": "^1.3.3", + "stream-each": "^1.1.0", + "through2": "^2.0.0" + } + }, + "mixin-deep": { + "version": "1.3.2", + "requires": { + "for-in": "^1.0.2", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "mixin-object": { + "version": "2.0.1", + "requires": { + "for-in": "^0.1.3", + "is-extendable": "^0.1.1" + }, + "dependencies": { + "for-in": { + "version": "0.1.8" + } + } + }, + "mkdirp": { + "version": "0.5.1", + "requires": { + "minimist": "0.0.8" + }, + "dependencies": { + "minimist": { + "version": "0.0.8" + } + } + }, + "mocha": { + "version": "6.2.2", + "requires": { + "ansi-colors": "3.2.3", + "browser-stdout": "1.3.1", + "debug": "3.2.6", + "diff": "3.5.0", + "escape-string-regexp": "1.0.5", + "find-up": "3.0.0", + "glob": "7.1.3", + "growl": "1.10.5", + "he": "1.2.0", + "js-yaml": "3.13.1", + "log-symbols": "2.2.0", + "minimatch": "3.0.4", + "mkdirp": "0.5.1", + "ms": "2.1.1", + "node-environment-flags": "1.0.5", + "object.assign": "4.1.0", + "strip-json-comments": "2.0.1", + "supports-color": "6.0.0", + "which": "1.3.1", + "wide-align": "1.1.3", + "yargs": "13.3.0", + "yargs-parser": "13.1.1", + "yargs-unparser": "1.6.0" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "requires": { + "ms": "^2.1.1" + }, + "dependencies": { + "ms": { + "version": "2.1.2" + } + } + }, + "glob": { + "version": "7.1.3", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "supports-color": { + "version": "6.0.0", + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "modify-values": { + "version": "1.0.1" + }, + "module-deps-sortable": { + "version": "5.0.0", + "requires": { + "JSONStream": "^1.0.3", + "browser-resolve": "^1.7.0", + "cached-path-relative": "^1.0.0", + "concat-stream": "~1.5.0", + "defined": "^1.0.0", + "detective": "^4.0.0", + "duplexer2": "^0.1.2", + "inherits": "^2.0.1", + "readable-stream": "^2.0.2", + "resolve": "^1.1.3", + "stream-combiner2": "^1.1.1", + "subarg": "^1.0.0", + "through2": "^2.0.0", + "xtend": "^4.0.0" + }, + "dependencies": { + "acorn": { + "version": "5.7.3" + }, + "concat-stream": { + "version": "1.5.2", + "requires": { + "inherits": "~2.0.1", + "readable-stream": "~2.0.0", + "typedarray": "~0.0.5" + }, + "dependencies": { + "readable-stream": { + "version": "2.0.6", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "~1.0.0", + "process-nextick-args": "~1.0.6", + "string_decoder": "~0.10.x", + "util-deprecate": "~1.0.1" + } + } + } + }, + "detective": { + "version": "4.7.1", + "requires": { + "acorn": "^5.2.1", + "defined": "^1.0.0" + } + } + } + }, + "mortice": { + "version": "2.0.0", + "requires": { + "globalthis": "^1.0.0", + "observable-webworkers": "^1.0.0", + "p-queue": "^6.0.0", + "promise-timeout": "^1.3.0", + "shortid": "^2.2.8" + } + }, + "move-concurrently": { + "version": "1.0.1", + "requires": { + "aproba": "^1.1.1", + "copy-concurrently": "^1.0.0", + "fs-write-stream-atomic": "^1.0.8", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.3" + } + }, + "moving-average": { + "version": "1.0.0" + }, + "mri": { + "version": "1.1.4" + }, + "ms": { + "version": "2.1.1" + }, + "multiaddr": { + "version": "7.2.1", + "requires": { + "bs58": "^4.0.1", + "cids": "~0.7.1", + "class-is": "^1.1.0", + "hi-base32": "~0.5.0", + "ip": "^1.1.5", + "is-ip": "^3.1.0", + "varint": "^5.0.0" + } + }, + "multiaddr-to-uri": { + "version": "5.1.0", + "requires": { + "multiaddr": "^7.2.1" + } + }, + "multibase": { + "version": "0.6.0", + "requires": { + "base-x": "3.0.4" + } + }, + "multicast-dns": { + "version": "7.2.0", + "requires": { + "dns-packet": "^4.0.0", + "thunky": "^1.0.2" + } + }, + "multicodec": { + "version": "1.0.0", + "requires": { + "varint": "^5.0.0" + } + }, + "multihashes": { + "version": "0.4.15", + "requires": { + "bs58": "^4.0.1", + "varint": "^5.0.0" + } + }, + "multihashing": { + "version": "0.3.3", + "requires": { + "blakejs": "^1.1.0", + "js-sha3": "~0.8.0", + "multihashes": "~0.4.14", + "webcrypto": "~0.1.1" + } + }, + "multihashing-async": { + "version": "0.8.0", + "requires": { + "blakejs": "^1.1.0", + "buffer": "^5.4.3", + "err-code": "^2.0.0", + "js-sha3": "~0.8.0", + "multihashes": "~0.4.15", + "murmurhash3js-revisited": "^3.0.0" + } + }, + "multistream-select": { + "version": "0.14.6", + "requires": { + "async": "^2.6.3", + "debug": "^4.1.1", + "err-code": "^1.1.2", + "interface-connection": "~0.3.3", + "once": "^1.4.0", + "pull-handshake": "^1.1.4", + "pull-length-prefixed": "^1.3.3", + "pull-stream": "^3.6.13", + "semver": "^6.2.0", + "varint": "^5.0.0" + }, + "dependencies": { + "async": { + "version": "2.6.3", + "requires": { + "lodash": "^4.17.14" + } + }, + "err-code": { + "version": "1.1.2" + }, + "semver": { + "version": "6.3.0" + } + } + }, + "murmurhash3js": { + "version": "3.0.1" + }, + "murmurhash3js-revisited": { + "version": "3.0.0" + }, + "mute-stream": { + "version": "0.0.8" + }, + "nan": { + "version": "2.14.0" + }, + "nanoid": { + "version": "2.1.9" + }, + "nanomatch": { + "version": "1.2.13", + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "fragment-cache": "^0.2.1", + "is-windows": "^1.0.2", + "kind-of": "^6.0.2", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "2.0.2", + "requires": { + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" + } + }, + "extend-shallow": { + "version": "3.0.2", + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + } + }, + "is-extendable": { + "version": "1.0.1", + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "napi-build-utils": { + "version": "1.0.1" + }, + "napi-macros": { + "version": "2.0.0" + }, + "native-or-another": { + "version": "2.0.0", + "requires": { + "native-or-bluebird": "^1.1.2" + } + }, + "native-or-bluebird": { + "version": "1.2.0" + }, + "natural-compare": { + "version": "1.4.0" + }, + "ndjson": { + "version": "1.5.0", + "requires": { + "json-stringify-safe": "^5.0.1", + "minimist": "^1.2.0", + "split2": "^3.1.0", + "through2": "^3.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.5.0", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "split2": { + "version": "3.1.1", + "requires": { + "readable-stream": "^3.0.0" + } + }, + "string_decoder": { + "version": "1.3.0", + "requires": { + "safe-buffer": "~5.2.0" + } + }, + "through2": { + "version": "3.0.1", + "requires": { + "readable-stream": "2 || 3" + } + } + } + }, + "needle": { + "version": "2.4.0", + "requires": { + "debug": "^3.2.6", + "iconv-lite": "^0.4.4", + "sax": "^1.2.4" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.2" + } + } + }, + "negotiator": { + "version": "0.6.2" + }, + "neo-async": { + "version": "2.6.1" + }, + "nested-error-stacks": { + "version": "2.1.0" + }, + "nice-try": { + "version": "1.0.5" + }, + "nise": { + "version": "1.5.3", + "requires": { + "@sinonjs/formatio": "^3.2.1", + "@sinonjs/text-encoding": "^0.7.1", + "just-extend": "^4.0.2", + "lolex": "^5.0.1", + "path-to-regexp": "^1.7.0" + }, + "dependencies": { + "isarray": { + "version": "0.0.1" + }, + "lolex": { + "version": "5.1.2", + "requires": { + "@sinonjs/commons": "^1.7.0" + } + }, + "path-to-regexp": { + "version": "1.8.0", + "requires": { + "isarray": "0.0.1" + } + } + } + }, + "nock": { + "version": "11.7.2", + "requires": { + "debug": "^4.1.0", + "json-stringify-safe": "^5.0.1", + "lodash": "^4.17.13", + "mkdirp": "^0.5.0", + "propagate": "^2.0.0" + } + }, + "node-abi": { + "version": "2.13.0", + "requires": { + "semver": "^5.4.1" + } + }, + "node-environment-flags": { + "version": "1.0.5", + "requires": { + "object.getownpropertydescriptors": "^2.0.3", + "semver": "^5.7.0" + } + }, + "node-fetch": { + "version": "2.6.0" + }, + "node-forge": { + "version": "0.9.1" + }, + "node-gyp-build": { + "version": "4.1.1" + }, + "node-libs-browser": { + "version": "2.2.1", + "requires": { + "assert": "^1.1.1", + "browserify-zlib": "^0.2.0", + "buffer": "^4.3.0", + "console-browserify": "^1.1.0", + "constants-browserify": "^1.0.0", + "crypto-browserify": "^3.11.0", + "domain-browser": "^1.1.1", + "events": "^3.0.0", + "https-browserify": "^1.0.0", + "os-browserify": "^0.3.0", + "path-browserify": "0.0.1", + "process": "^0.11.10", + "punycode": "^1.2.4", + "querystring-es3": "^0.2.0", + "readable-stream": "^2.3.3", + "stream-browserify": "^2.0.1", + "stream-http": "^2.7.2", + "string_decoder": "^1.0.0", + "timers-browserify": "^2.0.4", + "tty-browserify": "0.0.0", + "url": "^0.11.0", + "util": "^0.11.0", + "vm-browserify": "^1.0.1" + }, + "dependencies": { + "buffer": { + "version": "4.9.2", + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4", + "isarray": "^1.0.0" + } + }, + "stream-http": { + "version": "2.8.3", + "requires": { + "builtin-status-codes": "^3.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.3.6", + "to-arraybuffer": "^1.0.0", + "xtend": "^4.0.0" + } + }, + "string_decoder": { + "version": "1.3.0", + "requires": { + "safe-buffer": "~5.2.0" + } + } + } + }, + "node-modules-regexp": { + "version": "1.0.0" + }, + "node-pre-gyp": { + "version": "0.14.0", + "requires": { + "detect-libc": "^1.0.2", + "mkdirp": "^0.5.1", + "needle": "^2.2.1", + "nopt": "^4.0.1", + "npm-packlist": "^1.1.6", + "npmlog": "^4.0.2", + "rc": "^1.2.7", + "rimraf": "^2.6.1", + "semver": "^5.3.0", + "tar": "^4.4.2" + } + }, + "node-releases": { + "version": "1.1.46", + "requires": { + "semver": "^6.3.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0" + } + } + }, + "nodeify": { + "version": "1.0.1", + "requires": { + "is-promise": "~1.0.0", + "promise": "~1.3.0" + } + }, + "noop-logger": { + "version": "0.1.1" + }, + "nopt": { + "version": "4.0.1", + "requires": { + "abbrev": "1", + "osenv": "^0.1.4" + } + }, + "normalize-package-data": { + "version": "2.5.0", + "requires": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "normalize-path": { + "version": "3.0.0" + }, + "normalize-url": { + "version": "1.9.1", + "requires": { + "object-assign": "^4.0.1", + "prepend-http": "^1.0.0", + "query-string": "^4.1.0", + "sort-keys": "^1.0.0" + }, + "dependencies": { + "prepend-http": { + "version": "1.0.4" + }, + "sort-keys": { + "version": "1.1.2", + "requires": { + "is-plain-obj": "^1.0.0" + } + } + } + }, + "now-and-later": { + "version": "2.0.1", + "requires": { + "once": "^1.3.2" + } + }, + "npm-bundled": { + "version": "1.1.1", + "requires": { + "npm-normalize-package-bin": "^1.0.1" + } + }, + "npm-normalize-package-bin": { + "version": "1.0.1" + }, + "npm-package-json-lint": { + "version": "4.5.0", + "requires": { + "ajv": "^6.10.2", + "ajv-errors": "^1.0.1", + "chalk": "^3.0.0", + "cosmiconfig": "^5.2.1", + "debug": "^4.1.1", + "globby": "^10.0.1", + "ignore": "^5.1.4", + "is-plain-obj": "^2.0.0", + "jsonc-parser": "^2.2.0", + "log-symbols": "^3.0.0", + "meow": "^6.0.0", + "plur": "^3.1.1", + "semver": "^7.0.0", + "strip-json-comments": "^3.0.1" + }, + "dependencies": { + "ansi-styles": { + "version": "4.2.1", + "requires": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + } + }, + "camelcase-keys": { + "version": "6.1.1", + "requires": { + "camelcase": "^5.3.1", + "map-obj": "^4.0.0", + "quick-lru": "^4.0.1" + } + }, + "chalk": { + "version": "3.0.0", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4" + }, + "find-up": { + "version": "4.1.0", + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "has-flag": { + "version": "4.0.0" + }, + "indent-string": { + "version": "4.0.0" + }, + "is-plain-obj": { + "version": "2.1.0" + }, + "locate-path": { + "version": "5.0.0", + "requires": { + "p-locate": "^4.1.0" + } + }, + "log-symbols": { + "version": "3.0.0", + "requires": { + "chalk": "^2.4.2" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3" + }, + "has-flag": { + "version": "3.0.0" + }, + "supports-color": { + "version": "5.5.0", + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "map-obj": { + "version": "4.1.0" + }, + "meow": { + "version": "6.0.0", + "requires": { + "@types/minimist": "^1.2.0", + "camelcase-keys": "^6.1.1", + "decamelize-keys": "^1.1.0", + "hard-rejection": "^2.0.0", + "minimist-options": "^4.0.1", + "normalize-package-data": "^2.5.0", + "read-pkg-up": "^7.0.0", + "redent": "^3.0.0", + "trim-newlines": "^3.0.0", + "type-fest": "^0.8.1", + "yargs-parser": "^16.1.0" + } + }, + "minimist-options": { + "version": "4.0.2", + "requires": { + "arrify": "^1.0.1", + "is-plain-obj": "^1.1.0" + }, + "dependencies": { + "is-plain-obj": { + "version": "1.1.0" + } + } + }, + "p-locate": { + "version": "4.1.0", + "requires": { + "p-limit": "^2.2.0" + } + }, + "parse-json": { + "version": "5.0.0", + "requires": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1", + "lines-and-columns": "^1.1.6" + } + }, + "path-exists": { + "version": "4.0.0" + }, + "quick-lru": { + "version": "4.0.1" + }, + "read-pkg": { + "version": "5.2.0", + "requires": { + "@types/normalize-package-data": "^2.4.0", + "normalize-package-data": "^2.5.0", + "parse-json": "^5.0.0", + "type-fest": "^0.6.0" + }, + "dependencies": { + "type-fest": { + "version": "0.6.0" + } + } + }, + "read-pkg-up": { + "version": "7.0.1", + "requires": { + "find-up": "^4.1.0", + "read-pkg": "^5.2.0", + "type-fest": "^0.8.1" + } + }, + "redent": { + "version": "3.0.0", + "requires": { + "indent-string": "^4.0.0", + "strip-indent": "^3.0.0" + } + }, + "semver": { + "version": "7.1.1" + }, + "strip-indent": { + "version": "3.0.0", + "requires": { + "min-indent": "^1.0.0" + } + }, + "strip-json-comments": { + "version": "3.0.1" + }, + "supports-color": { + "version": "7.1.0", + "requires": { + "has-flag": "^4.0.0" + } + }, + "trim-newlines": { + "version": "3.0.0" + }, + "yargs-parser": { + "version": "16.1.0", + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } + } + }, + "npm-packlist": { + "version": "1.4.7", + "requires": { + "ignore-walk": "^3.0.1", + "npm-bundled": "^1.0.1" + } + }, + "npm-path": { + "version": "2.0.4", + "requires": { + "which": "^1.2.10" + } + }, + "npm-run-path": { + "version": "2.0.2", + "requires": { + "path-key": "^2.0.0" + } + }, + "npm-which": { + "version": "3.0.1", + "requires": { + "commander": "^2.9.0", + "npm-path": "^2.0.2", + "which": "^1.2.10" + } + }, + "npmlog": { + "version": "4.1.2", + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "nugget": { + "version": "2.0.1", + "requires": { + "debug": "^2.1.3", + "minimist": "^1.1.0", + "pretty-bytes": "^1.0.2", + "progress-stream": "^1.1.0", + "request": "^2.45.0", + "single-line-log": "^1.1.2", + "throttleit": "0.0.2" + }, + "dependencies": { + "camelcase": { + "version": "2.1.1" + }, + "camelcase-keys": { + "version": "2.1.0", + "requires": { + "camelcase": "^2.0.0", + "map-obj": "^1.0.0" + } + }, + "debug": { + "version": "2.6.9", + "requires": { + "ms": "2.0.0" + } + }, + "find-up": { + "version": "1.1.2", + "requires": { + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "indent-string": { + "version": "2.1.0", + "requires": { + "repeating": "^2.0.0" + } + }, + "load-json-file": { + "version": "1.1.0", + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "strip-bom": "^2.0.0" + } + }, + "meow": { + "version": "3.7.0", + "requires": { + "camelcase-keys": "^2.0.0", + "decamelize": "^1.1.2", + "loud-rejection": "^1.0.0", + "map-obj": "^1.0.1", + "minimist": "^1.1.3", + "normalize-package-data": "^2.3.4", + "object-assign": "^4.0.1", + "read-pkg-up": "^1.0.1", + "redent": "^1.0.0", + "trim-newlines": "^1.0.0" + } + }, + "ms": { + "version": "2.0.0" + }, + "parse-json": { + "version": "2.2.0", + "requires": { + "error-ex": "^1.2.0" + } + }, + "path-exists": { + "version": "2.1.0", + "requires": { + "pinkie-promise": "^2.0.0" + } + }, + "path-type": { + "version": "1.1.0", + "requires": { + "graceful-fs": "^4.1.2", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "pify": { + "version": "2.3.0" + }, + "pretty-bytes": { + "version": "1.0.4", + "requires": { + "get-stdin": "^4.0.1", + "meow": "^3.1.0" + } + }, + "read-pkg": { + "version": "1.1.0", + "requires": { + "load-json-file": "^1.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^1.0.0" + } + }, + "read-pkg-up": { + "version": "1.0.1", + "requires": { + "find-up": "^1.0.0", + "read-pkg": "^1.0.0" + } + }, + "redent": { + "version": "1.0.0", + "requires": { + "indent-string": "^2.1.0", + "strip-indent": "^1.0.1" + } + }, + "strip-bom": { + "version": "2.0.0", + "requires": { + "is-utf8": "^0.2.0" + } + }, + "strip-indent": { + "version": "1.0.1", + "requires": { + "get-stdin": "^4.0.1" + } + }, + "trim-newlines": { + "version": "1.0.0" + } + } + }, + "number-is-nan": { + "version": "1.0.1" + }, + "nyc": { + "version": "14.1.1", + "requires": { + "archy": "^1.0.0", + "caching-transform": "^3.0.2", + "convert-source-map": "^1.6.0", + "cp-file": "^6.2.0", + "find-cache-dir": "^2.1.0", + "find-up": "^3.0.0", + "foreground-child": "^1.5.6", + "glob": "^7.1.3", + "istanbul-lib-coverage": "^2.0.5", + "istanbul-lib-hook": "^2.0.7", + "istanbul-lib-instrument": "^3.3.0", + "istanbul-lib-report": "^2.0.8", + "istanbul-lib-source-maps": "^3.0.6", + "istanbul-reports": "^2.2.4", + "js-yaml": "^3.13.1", + "make-dir": "^2.1.0", + "merge-source-map": "^1.1.0", + "resolve-from": "^4.0.0", + "rimraf": "^2.6.3", + "signal-exit": "^3.0.2", + "spawn-wrap": "^1.4.2", + "test-exclude": "^5.2.3", + "uuid": "^3.3.2", + "yargs": "^13.2.2", + "yargs-parser": "^13.0.0" + }, + "dependencies": { + "resolve-from": { + "version": "4.0.0" + } + } + }, + "oauth-sign": { + "version": "0.9.0" + }, + "object-assign": { + "version": "4.1.1" + }, + "object-component": { + "version": "0.0.3" + }, + "object-copy": { + "version": "0.1.0", + "requires": { + "copy-descriptor": "^0.1.0", + "define-property": "^0.2.5", + "kind-of": "^3.0.3" + }, + "dependencies": { + "is-buffer": { + "version": "1.1.6" + }, + "kind-of": { + "version": "3.2.2", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "object-inspect": { + "version": "1.7.0" + }, + "object-keys": { + "version": "1.1.1" + }, + "object-visit": { + "version": "1.0.1", + "requires": { + "isobject": "^3.0.0" + } + }, + "object.assign": { + "version": "4.1.0", + "requires": { + "define-properties": "^1.1.2", + "function-bind": "^1.1.1", + "has-symbols": "^1.0.0", + "object-keys": "^1.0.11" + } + }, + "object.getownpropertydescriptors": { + "version": "2.1.0", + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1" + } + }, + "object.pick": { + "version": "1.3.0", + "requires": { + "isobject": "^3.0.1" + } + }, + "object.values": { + "version": "1.1.1", + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1", + "function-bind": "^1.1.1", + "has": "^1.0.3" + } + }, + "observable-webworkers": { + "version": "1.0.0" + }, + "on-finished": { + "version": "2.3.0", + "requires": { + "ee-first": "1.1.1" + } + }, + "once": { + "version": "1.4.0", + "requires": { + "wrappy": "1" + } + }, + "onetime": { + "version": "5.1.0", + "requires": { + "mimic-fn": "^2.1.0" + } + }, + "opencollective-postinstall": { + "version": "2.0.2" + }, + "opener": { + "version": "1.5.1" + }, + "optimist": { + "version": "0.6.1", + "requires": { + "minimist": "~0.0.1", + "wordwrap": "~0.0.2" + }, + "dependencies": { + "minimist": { + "version": "0.0.10" + } + } + }, + "optional": { + "version": "0.1.4", + "optional": true + }, + "optionator": { + "version": "0.8.3", + "requires": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + } + }, + "options": { + "version": "0.0.6" + }, + "ordered-read-streams": { + "version": "1.0.1", + "requires": { + "readable-stream": "^2.0.1" + } + }, + "os-browserify": { + "version": "0.3.0" + }, + "os-homedir": { + "version": "1.0.2" + }, + "os-locale": { + "version": "3.1.0", + "requires": { + "execa": "^1.0.0", + "lcid": "^2.0.0", + "mem": "^4.0.0" + } + }, + "os-tmpdir": { + "version": "1.0.2" + }, + "osenv": { + "version": "0.1.5", + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + }, + "p-cancelable": { + "version": "0.4.1" + }, + "p-defer": { + "version": "3.0.0" + }, + "p-fifo": { + "version": "1.0.0", + "requires": { + "fast-fifo": "^1.0.0", + "p-defer": "^3.0.0" + } + }, + "p-finally": { + "version": "1.0.0" + }, + "p-is-promise": { + "version": "1.1.0" + }, + "p-iteration": { + "version": "1.1.8" + }, + "p-limit": { + "version": "2.2.2", + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-map": { + "version": "3.0.0", + "requires": { + "aggregate-error": "^3.0.0" + } + }, + "p-queue": { + "version": "6.2.1", + "requires": { + "eventemitter3": "^4.0.0", + "p-timeout": "^3.1.0" + } + }, + "p-timeout": { + "version": "3.2.0", + "requires": { + "p-finally": "^1.0.0" + } + }, + "p-times": { + "version": "2.1.0", + "requires": { + "p-map": "^2.0.0" + }, + "dependencies": { + "p-map": { + "version": "2.1.0" + } + } + }, + "p-try": { + "version": "2.2.0" + }, + "p-try-each": { + "version": "1.0.1" + }, + "package-hash": { + "version": "3.0.0", + "requires": { + "graceful-fs": "^4.1.15", + "hasha": "^3.0.0", + "lodash.flattendeep": "^4.4.0", + "release-zalgo": "^1.0.0" + } + }, + "package-json": { + "version": "6.5.0", + "requires": { + "got": "^9.6.0", + "registry-auth-token": "^4.0.0", + "registry-url": "^5.0.0", + "semver": "^6.2.0" + }, + "dependencies": { + "@sindresorhus/is": { + "version": "0.14.0" + }, + "cacheable-request": { + "version": "6.1.0", + "requires": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^3.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^4.1.0", + "responselike": "^1.0.2" + }, + "dependencies": { + "get-stream": { + "version": "5.1.0", + "requires": { + "pump": "^3.0.0" + } + }, + "lowercase-keys": { + "version": "2.0.0" + } + } + }, + "get-stream": { + "version": "4.1.0", + "requires": { + "pump": "^3.0.0" + } + }, + "got": { + "version": "9.6.0", + "requires": { + "@sindresorhus/is": "^0.14.0", + "@szmarczak/http-timer": "^1.1.2", + "cacheable-request": "^6.0.0", + "decompress-response": "^3.3.0", + "duplexer3": "^0.1.4", + "get-stream": "^4.1.0", + "lowercase-keys": "^1.0.1", + "mimic-response": "^1.0.1", + "p-cancelable": "^1.0.0", + "to-readable-stream": "^1.0.0", + "url-parse-lax": "^3.0.0" + } + }, + "http-cache-semantics": { + "version": "4.0.3" + }, + "keyv": { + "version": "3.1.0", + "requires": { + "json-buffer": "3.0.0" + } + }, + "normalize-url": { + "version": "4.5.0" + }, + "p-cancelable": { + "version": "1.1.0" + }, + "semver": { + "version": "6.3.0" + } + } + }, + "pako": { + "version": "1.0.10" + }, + "parallel-transform": { + "version": "1.2.0", + "requires": { + "cyclist": "^1.0.1", + "inherits": "^2.0.3", + "readable-stream": "^2.1.5" + } + }, + "parent-module": { + "version": "1.0.1", + "requires": { + "callsites": "^3.0.0" + } + }, + "parse-asn1": { + "version": "5.1.5", + "requires": { + "asn1.js": "^4.0.0", + "browserify-aes": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.0", + "pbkdf2": "^3.0.3", + "safe-buffer": "^5.1.1" + }, + "dependencies": { + "asn1.js": { + "version": "4.10.1", + "requires": { + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + } + } + }, + "parse-duration": { + "version": "0.1.2" + }, + "parse-entities": { + "version": "1.2.2", + "requires": { + "character-entities": "^1.0.0", + "character-entities-legacy": "^1.0.0", + "character-reference-invalid": "^1.0.0", + "is-alphanumerical": "^1.0.0", + "is-decimal": "^1.0.0", + "is-hexadecimal": "^1.0.0" + } + }, + "parse-filepath": { + "version": "1.0.2", + "requires": { + "is-absolute": "^1.0.0", + "map-cache": "^0.2.0", + "path-root": "^0.1.1" + } + }, + "parse-github-repo-url": { + "version": "1.4.1" + }, + "parse-headers": { + "version": "2.0.3" + }, + "parse-json": { + "version": "4.0.0", + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, + "parse-passwd": { + "version": "1.0.0" + }, + "parse-path": { + "version": "4.0.1", + "requires": { + "is-ssh": "^1.3.0", + "protocols": "^1.4.0" + } + }, + "parse-url": { + "version": "5.0.1", + "requires": { + "is-ssh": "^1.3.0", + "normalize-url": "^3.3.0", + "parse-path": "^4.0.0", + "protocols": "^1.4.0" + }, + "dependencies": { + "normalize-url": { + "version": "3.3.0" + } + } + }, + "parseqs": { + "version": "0.0.5", + "requires": { + "better-assert": "~1.0.0" + } + }, + "parseuri": { + "version": "0.0.5", + "requires": { + "better-assert": "~1.0.0" + } + }, + "parseurl": { + "version": "1.3.3" + }, + "pascalcase": { + "version": "0.1.1" + }, + "path-browserify": { + "version": "0.0.1" + }, + "path-dirname": { + "version": "1.0.2" + }, + "path-exists": { + "version": "3.0.0" + }, + "path-is-absolute": { + "version": "1.0.1" + }, + "path-is-inside": { + "version": "1.0.2" + }, + "path-key": { + "version": "2.0.1" + }, + "path-parse": { + "version": "1.0.6" + }, + "path-root": { + "version": "0.1.1", + "requires": { + "path-root-regex": "^0.1.0" + } + }, + "path-root-regex": { + "version": "0.1.2" + }, + "path-to-regexp": { + "version": "0.1.7" + }, + "path-type": { + "version": "3.0.0", + "requires": { + "pify": "^3.0.0" + }, + "dependencies": { + "pify": { + "version": "3.0.0" + } + } + }, + "pathval": { + "version": "1.1.0" + }, + "pbkdf2": { + "version": "3.0.17", + "requires": { + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4", + "ripemd160": "^2.0.1", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "peek-stream": { + "version": "1.1.3", + "requires": { + "buffer-from": "^1.0.0", + "duplexify": "^3.5.0", + "through2": "^2.0.3" + } + }, + "peer-book": { + "version": "0.9.2", + "requires": { + "bs58": "^4.0.1", + "peer-id": "~0.12.2", + "peer-info": "~0.15.1" + } + }, + "peer-id": { + "version": "0.12.5", + "requires": { + "async": "^2.6.3", + "class-is": "^1.1.0", + "libp2p-crypto": "~0.16.1", + "multihashes": "~0.4.15" + }, + "dependencies": { + "async": { + "version": "2.6.3", + "requires": { + "lodash": "^4.17.14" + } + } + } + }, + "peer-info": { + "version": "0.15.1", + "requires": { + "mafmt": "^6.0.2", + "multiaddr": "^6.0.3", + "peer-id": "~0.12.2", + "unique-by": "^1.0.0" + }, + "dependencies": { + "ip-regex": { + "version": "2.1.0" + }, + "is-ip": { + "version": "2.0.0", + "requires": { + "ip-regex": "^2.0.0" + } + }, + "multiaddr": { + "version": "6.1.1", + "requires": { + "bs58": "^4.0.1", + "class-is": "^1.1.0", + "hi-base32": "~0.5.0", + "ip": "^1.1.5", + "is-ip": "^2.0.0", + "varint": "^5.0.0" + } + } + } + }, + "pem-jwk": { + "version": "2.0.0", + "requires": { + "asn1.js": "^5.0.1" + } + }, + "pend": { + "version": "1.2.0" + }, + "performance-now": { + "version": "2.1.0" + }, + "picomatch": { + "version": "2.2.1" + }, + "pify": { + "version": "4.0.1" + }, + "pinkie": { + "version": "2.0.4" + }, + "pinkie-promise": { + "version": "2.0.1", + "requires": { + "pinkie": "^2.0.0" + } + }, + "pino": { + "version": "5.16.0", + "requires": { + "fast-redact": "^2.0.0", + "fast-safe-stringify": "^2.0.7", + "flatstr": "^1.0.12", + "pino-std-serializers": "^2.4.2", + "quick-format-unescaped": "^3.0.3", + "sonic-boom": "^0.7.5" + } + }, + "pino-pretty": { + "version": "3.5.0", + "requires": { + "@hapi/bourne": "^1.3.2", + "args": "^5.0.1", + "chalk": "^2.4.2", + "dateformat": "^3.0.3", + "fast-safe-stringify": "^2.0.7", + "jmespath": "^0.15.0", + "joycon": "^2.2.5", + "pump": "^3.0.0", + "readable-stream": "^3.4.0", + "split2": "^3.1.1", + "strip-json-comments": "^3.0.1" + }, + "dependencies": { + "readable-stream": { + "version": "3.5.0", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "split2": { + "version": "3.1.1", + "requires": { + "readable-stream": "^3.0.0" + } + }, + "string_decoder": { + "version": "1.3.0", + "requires": { + "safe-buffer": "~5.2.0" + } + }, + "strip-json-comments": { + "version": "3.0.1" + } + } + }, + "pino-std-serializers": { + "version": "2.4.2" + }, + "pirates": { + "version": "4.0.1", + "requires": { + "node-modules-regexp": "^1.0.0" + } + }, + "pkg-conf": { + "version": "3.1.0", + "requires": { + "find-up": "^3.0.0", + "load-json-file": "^5.2.0" + }, + "dependencies": { + "load-json-file": { + "version": "5.3.0", + "requires": { + "graceful-fs": "^4.1.15", + "parse-json": "^4.0.0", + "pify": "^4.0.1", + "strip-bom": "^3.0.0", + "type-fest": "^0.3.0" + } + }, + "type-fest": { + "version": "0.3.1" + } + } + }, + "pkg-dir": { + "version": "3.0.0", + "requires": { + "find-up": "^3.0.0" + } + }, + "pkg-up": { + "version": "3.1.0", + "requires": { + "find-up": "^3.0.0" + } + }, + "plur": { + "version": "3.1.1", + "requires": { + "irregular-plurals": "^2.0.0" + } + }, + "posix-character-classes": { + "version": "0.1.1" + }, + "prebuild-install": { + "version": "5.3.3", + "requires": { + "detect-libc": "^1.0.3", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.0", + "mkdirp": "^0.5.1", + "napi-build-utils": "^1.0.1", + "node-abi": "^2.7.0", + "noop-logger": "^0.1.1", + "npmlog": "^4.0.1", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^3.0.3", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0", + "which-pm-runs": "^1.0.0" + } + }, + "prelude-ls": { + "version": "1.1.2" + }, + "prepend-http": { + "version": "2.0.0" + }, + "pretty-bytes": { + "version": "5.3.0" + }, + "pretty-hrtime": { + "version": "1.0.3" + }, + "prettycli": { + "version": "1.4.3", + "requires": { + "chalk": "2.1.0" + }, + "dependencies": { + "chalk": { + "version": "2.1.0", + "requires": { + "ansi-styles": "^3.1.0", + "escape-string-regexp": "^1.0.5", + "supports-color": "^4.0.0" + } + }, + "has-flag": { + "version": "2.0.0" + }, + "supports-color": { + "version": "4.5.0", + "requires": { + "has-flag": "^2.0.0" + } + } + } + }, + "private": { + "version": "0.1.8" + }, + "process": { + "version": "0.11.10" + }, + "process-nextick-args": { + "version": "1.0.7" + }, + "progress": { + "version": "2.0.3" + }, + "progress-stream": { + "version": "1.2.0", + "requires": { + "speedometer": "~0.1.2", + "through2": "~0.2.3" + }, + "dependencies": { + "isarray": { + "version": "0.0.1" + }, + "object-keys": { + "version": "0.4.0" + }, + "readable-stream": { + "version": "1.1.14", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "through2": { + "version": "0.2.3", + "requires": { + "readable-stream": "~1.1.9", + "xtend": "~2.1.1" + } + }, + "xtend": { + "version": "2.1.2", + "requires": { + "object-keys": "~0.4.0" + } + } + } + }, + "prom-client": { + "version": "11.5.3", + "optional": true, + "requires": { + "tdigest": "^0.1.1" + } + }, + "prometheus-gc-stats": { + "version": "0.6.2", + "optional": true, + "requires": { + "gc-stats": "^1.2.1", + "optional": "^0.1.3" + } + }, + "promise": { + "version": "1.3.0", + "requires": { + "is-promise": "~1" + } + }, + "promise-inflight": { + "version": "1.0.1" + }, + "promise-nodeify": { + "version": "3.0.1" + }, + "promise-timeout": { + "version": "1.3.0" + }, + "promise-to-callback": { + "version": "1.0.0", + "requires": { + "is-fn": "^1.0.0", + "set-immediate-shim": "^1.0.1" + } + }, + "promisify-es6": { + "version": "1.0.3" + }, + "prompt-promise": { + "version": "1.0.3", + "requires": { + "keypress": "~0.2.1", + "native-or-another": "~2.0.0" + } + }, + "propagate": { + "version": "2.0.1" + }, + "proper-lockfile": { + "version": "4.1.1", + "requires": { + "graceful-fs": "^4.1.11", + "retry": "^0.12.0", + "signal-exit": "^3.0.2" + } + }, + "property-information": { + "version": "4.2.0", + "requires": { + "xtend": "^4.0.1" + } + }, + "protocol-buffers-schema": { + "version": "3.3.3" + }, + "protocols": { + "version": "1.4.7" + }, + "protons": { + "version": "1.1.0", + "requires": { + "protocol-buffers-schema": "^3.3.1", + "safe-buffer": "^5.1.1", + "signed-varint": "^2.0.1", + "varint": "^5.0.0" + } + }, + "proxy-addr": { + "version": "2.0.5", + "requires": { + "forwarded": "~0.1.2", + "ipaddr.js": "1.9.0" + } + }, + "prr": { + "version": "1.0.1" + }, + "pseudomap": { + "version": "1.0.2" + }, + "psl": { + "version": "1.7.0" + }, + "public-encrypt": { + "version": "4.0.3", + "requires": { + "bn.js": "^4.1.0", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "parse-asn1": "^5.0.0", + "randombytes": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "pull-abortable": { + "version": "4.1.1" + }, + "pull-cat": { + "version": "1.1.11" + }, + "pull-defer": { + "version": "0.2.3" + }, + "pull-file": { + "version": "1.1.0", + "requires": { + "pull-utf8-decoder": "^1.0.2" + } + }, + "pull-handshake": { + "version": "1.1.4", + "requires": { + "pull-cat": "^1.1.9", + "pull-pair": "~1.1.0", + "pull-pushable": "^2.0.0", + "pull-reader": "^1.2.3" + } + }, + "pull-length-prefixed": { + "version": "1.3.3", + "requires": { + "pull-pushable": "^2.2.0", + "pull-reader": "^1.3.1", + "safe-buffer": "^5.1.2", + "varint": "^5.0.0" + } + }, + "pull-mplex": { + "version": "0.1.2", + "requires": { + "async": "^2.6.1", + "buffer-reuse-pool": "^1.0.0", + "debug": "^4.1.1", + "interface-connection": "~0.3.3", + "looper": "^4.0.0", + "pull-offset-limit": "^1.1.1", + "pull-pair": "^1.1.0", + "pull-pushable": "^2.2.0", + "pull-stream": "^3.6.9", + "pull-through": "^1.0.18", + "varint": "^5.0.0" + }, + "dependencies": { + "async": { + "version": "2.6.3", + "requires": { + "lodash": "^4.17.14" + } + }, + "looper": { + "version": "4.0.0" + } + } + }, + "pull-ndjson": { + "version": "0.2.0", + "requires": { + "pull-split": "^0.2.0", + "pull-stream": "^3.4.5", + "pull-stringify": "^2.0.0" + } + }, + "pull-offset-limit": { + "version": "1.1.1", + "requires": { + "pull-abortable": "^4.1.0", + "pull-stream": "^3.5.0" + } + }, + "pull-pair": { + "version": "1.1.0" + }, + "pull-pushable": { + "version": "2.2.0" + }, + "pull-reader": { + "version": "1.3.1" + }, + "pull-sort": { + "version": "1.0.2", + "requires": { + "pull-defer": "^0.2.3", + "pull-stream": "^3.6.9" + } + }, + "pull-split": { + "version": "0.2.1", + "requires": { + "pull-through": "~1.0.6" + } + }, + "pull-stream": { + "version": "3.6.14" + }, + "pull-stream-to-async-iterator": { + "version": "1.0.2", + "requires": { + "pull-stream": "^3.6.9" + } + }, + "pull-stream-to-stream": { + "version": "2.0.0" + }, + "pull-stringify": { + "version": "2.0.0", + "requires": { + "defined": "^1.0.0" + } + }, + "pull-through": { + "version": "1.0.18", + "requires": { + "looper": "~3.0.0" + } + }, + "pull-to-stream": { + "version": "0.1.1", + "requires": { + "readable-stream": "^3.1.1" + }, + "dependencies": { + "readable-stream": { + "version": "3.5.0", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "string_decoder": { + "version": "1.3.0", + "requires": { + "safe-buffer": "~5.2.0" + } + } + } + }, + "pull-traverse": { + "version": "1.0.3" + }, + "pull-utf8-decoder": { + "version": "1.0.2" + }, + "pull-ws": { + "version": "3.3.1", + "requires": { + "iso-url": "^0.4.4", + "relative-url": "^1.0.2", + "safe-buffer": "^5.1.1", + "ws": "^1.1.0" + }, + "dependencies": { + "ultron": { + "version": "1.0.2" + }, + "ws": { + "version": "1.1.5", + "requires": { + "options": ">=0.0.5", + "ultron": "1.0.x" + } + } + } + }, + "pump": { + "version": "3.0.0", + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "pumpify": { + "version": "1.5.1", + "requires": { + "duplexify": "^3.6.0", + "inherits": "^2.0.3", + "pump": "^2.0.0" + }, + "dependencies": { + "pump": { + "version": "2.0.1", + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + } + } + }, + "punycode": { + "version": "1.4.1" + }, + "pushdata-bitcoin": { + "version": "1.0.1", + "requires": { + "bitcoin-ops": "^1.3.0" + } + }, + "q": { + "version": "1.5.1" + }, + "qjobs": { + "version": "1.2.0" + }, + "qs": { + "version": "6.9.1" + }, + "query-string": { + "version": "4.3.4", + "requires": { + "object-assign": "^4.1.0", + "strict-uri-encode": "^1.0.0" + } + }, + "querystring": { + "version": "0.2.0" + }, + "querystring-es3": { + "version": "0.2.1" + }, + "queue-microtask": { + "version": "1.1.2" + }, + "quick-format-unescaped": { + "version": "3.0.3" + }, + "quick-lru": { + "version": "1.1.0" + }, + "rabin-wasm": { + "version": "0.0.8", + "requires": { + "bl": "^1.0.0", + "debug": "^4.1.1", + "minimist": "^1.2.0", + "node-fetch": "^2.6.0", + "readable-stream": "^2.0.4" + }, + "dependencies": { + "bl": { + "version": "1.2.2", + "requires": { + "readable-stream": "^2.3.5", + "safe-buffer": "^5.1.1" + } + } + } + }, + "randombytes": { + "version": "2.1.0", + "requires": { + "safe-buffer": "^5.1.0" + } + }, + "randomfill": { + "version": "1.0.4", + "requires": { + "randombytes": "^2.0.5", + "safe-buffer": "^5.1.0" + } + }, + "range-parser": { + "version": "1.2.1" + }, + "raw-body": { + "version": "2.4.0", + "requires": { + "bytes": "3.1.0", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + } + }, + "rc": { + "version": "1.2.8", + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + } + }, + "read-package-json": { + "version": "2.1.1", + "requires": { + "glob": "^7.1.1", + "graceful-fs": "^4.1.2", + "json-parse-better-errors": "^1.0.1", + "normalize-package-data": "^2.0.0", + "npm-normalize-package-bin": "^1.0.0" + } + }, + "read-pkg": { + "version": "3.0.0", + "requires": { + "load-json-file": "^4.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^3.0.0" + } + }, + "read-pkg-up": { + "version": "3.0.0", + "requires": { + "find-up": "^2.0.0", + "read-pkg": "^3.0.0" + }, + "dependencies": { + "find-up": { + "version": "2.1.0", + "requires": { + "locate-path": "^2.0.0" + } + }, + "locate-path": { + "version": "2.0.0", + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } + }, + "p-limit": { + "version": "1.3.0", + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "requires": { + "p-limit": "^1.1.0" + } + }, + "p-try": { + "version": "1.0.0" + } + } + }, + "readable-stream": { + "version": "2.3.7", + "requires": { + "core-util-is": "~1.0.0", + "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.1" + }, + "dependencies": { + "process-nextick-args": { + "version": "2.0.1" + }, + "safe-buffer": { + "version": "5.1.2" + }, + "string_decoder": { + "version": "1.1.1", + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "readdirp": { + "version": "2.2.1", + "requires": { + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" + } + }, + "receptacle": { + "version": "1.3.2", + "requires": { + "ms": "^2.1.1" + }, + "dependencies": { + "ms": { + "version": "2.1.2" + } + } + }, + "redent": { + "version": "2.0.0", + "requires": { + "indent-string": "^3.0.0", + "strip-indent": "^2.0.0" + } + }, + "regenerate": { + "version": "1.4.0" + }, + "regenerate-unicode-properties": { + "version": "8.1.0", + "requires": { + "regenerate": "^1.4.0" + } + }, + "regenerator-runtime": { + "version": "0.13.3" + }, + "regenerator-transform": { + "version": "0.14.1", + "requires": { + "private": "^0.1.6" + } + }, + "regex-not": { + "version": "1.0.2", + "requires": { + "extend-shallow": "^3.0.2", + "safe-regex": "^1.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "3.0.2", + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + } + }, + "is-extendable": { + "version": "1.0.1", + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "regexpp": { + "version": "2.0.1" + }, + "regexpu-core": { + "version": "4.6.0", + "requires": { + "regenerate": "^1.4.0", + "regenerate-unicode-properties": "^8.1.0", + "regjsgen": "^0.5.0", + "regjsparser": "^0.6.0", + "unicode-match-property-ecmascript": "^1.0.4", + "unicode-match-property-value-ecmascript": "^1.1.0" + } + }, + "registry-auth-token": { + "version": "4.1.0", + "requires": { + "rc": "^1.2.8", + "safe-buffer": "^5.0.1" + } + }, + "registry-url": { + "version": "5.1.0", + "requires": { + "rc": "^1.2.8" + } + }, + "regjsgen": { + "version": "0.5.1" + }, + "regjsparser": { + "version": "0.6.2", + "requires": { + "jsesc": "~0.5.0" + }, + "dependencies": { + "jsesc": { + "version": "0.5.0" + } + } + }, + "relative-url": { + "version": "1.0.2" + }, + "release-zalgo": { + "version": "1.0.0", + "requires": { + "es6-error": "^4.0.1" + } + }, + "remark": { + "version": "9.0.0", + "requires": { + "remark-parse": "^5.0.0", + "remark-stringify": "^5.0.0", + "unified": "^6.0.0" + } + }, + "remark-html": { + "version": "8.0.0", + "requires": { + "hast-util-sanitize": "^1.0.0", + "hast-util-to-html": "^4.0.0", + "mdast-util-to-hast": "^3.0.0", + "xtend": "^4.0.1" + } + }, + "remark-parse": { + "version": "5.0.0", + "requires": { + "collapse-white-space": "^1.0.2", + "is-alphabetical": "^1.0.0", + "is-decimal": "^1.0.0", + "is-whitespace-character": "^1.0.0", + "is-word-character": "^1.0.0", + "markdown-escapes": "^1.0.0", + "parse-entities": "^1.1.0", + "repeat-string": "^1.5.4", + "state-toggle": "^1.0.0", + "trim": "0.0.1", + "trim-trailing-lines": "^1.0.0", + "unherit": "^1.0.4", + "unist-util-remove-position": "^1.0.0", + "vfile-location": "^2.0.0", + "xtend": "^4.0.1" + } + }, + "remark-reference-links": { + "version": "4.0.4", + "requires": { + "unist-util-visit": "^1.0.0" + } + }, + "remark-slug": { + "version": "5.1.2", + "requires": { + "github-slugger": "^1.0.0", + "mdast-util-to-string": "^1.0.0", + "unist-util-visit": "^1.0.0" + } + }, + "remark-stringify": { + "version": "5.0.0", + "requires": { + "ccount": "^1.0.0", + "is-alphanumeric": "^1.0.0", + "is-decimal": "^1.0.0", + "is-whitespace-character": "^1.0.0", + "longest-streak": "^2.0.1", + "markdown-escapes": "^1.0.0", + "markdown-table": "^1.1.0", + "mdast-util-compact": "^1.0.0", + "parse-entities": "^1.0.2", + "repeat-string": "^1.5.4", + "state-toggle": "^1.0.0", + "stringify-entities": "^1.0.1", + "unherit": "^1.0.4", + "xtend": "^4.0.1" + } + }, + "remark-toc": { + "version": "5.1.1", + "requires": { + "mdast-util-toc": "^3.0.0", + "remark-slug": "^5.0.0" + } + }, + "remove-bom-buffer": { + "version": "3.0.0", + "requires": { + "is-buffer": "^1.1.5", + "is-utf8": "^0.2.1" + }, + "dependencies": { + "is-buffer": { + "version": "1.1.6" + } + } + }, + "remove-bom-stream": { + "version": "1.2.0", + "requires": { + "remove-bom-buffer": "^3.0.0", + "safe-buffer": "^5.1.0", + "through2": "^2.0.3" + } + }, + "remove-trailing-separator": { + "version": "1.1.0" + }, + "repeat-element": { + "version": "1.1.3" + }, + "repeat-string": { + "version": "1.6.1" + }, + "repeating": { + "version": "2.0.1", + "requires": { + "is-finite": "^1.0.0" + } + }, + "replace-ext": { + "version": "1.0.0" + }, + "request": { + "version": "2.88.0", + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.0", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.4.3", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + }, + "dependencies": { + "form-data": { + "version": "2.3.3", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + } + }, + "qs": { + "version": "6.5.2" + } + } + }, + "require-directory": { + "version": "2.1.1" + }, + "require-main-filename": { + "version": "2.0.0" + }, + "requires-port": { + "version": "1.0.0" + }, + "resolve": { + "version": "1.14.2", + "requires": { + "path-parse": "^1.0.6" + } + }, + "resolve-bin": { + "version": "0.4.0", + "requires": { + "find-parent-dir": "~0.3.0" + } + }, + "resolve-cwd": { + "version": "3.0.0", + "requires": { + "resolve-from": "^5.0.0" + } + }, + "resolve-dir": { + "version": "1.0.1", + "requires": { + "expand-tilde": "^2.0.0", + "global-modules": "^1.0.0" + }, + "dependencies": { + "global-modules": { + "version": "1.0.0", + "requires": { + "global-prefix": "^1.0.1", + "is-windows": "^1.0.1", + "resolve-dir": "^1.0.0" + } + }, + "global-prefix": { + "version": "1.0.2", + "requires": { + "expand-tilde": "^2.0.2", + "homedir-polyfill": "^1.0.1", + "ini": "^1.3.4", + "is-windows": "^1.0.1", + "which": "^1.2.14" + } + } + } + }, + "resolve-from": { + "version": "5.0.0" + }, + "resolve-global": { + "version": "1.0.0", + "requires": { + "global-dirs": "^0.1.1" + } + }, + "resolve-options": { + "version": "1.1.0", + "requires": { + "value-or-function": "^3.0.0" + } + }, + "resolve-url": { + "version": "0.2.1" + }, + "responselike": { + "version": "1.0.2", + "requires": { + "lowercase-keys": "^1.0.0" + } + }, + "restore-cursor": { + "version": "2.0.0", + "requires": { + "onetime": "^2.0.0", + "signal-exit": "^3.0.2" + }, + "dependencies": { + "mimic-fn": { + "version": "1.2.0" + }, + "onetime": { + "version": "2.0.1", + "requires": { + "mimic-fn": "^1.0.0" + } + } + } + }, + "ret": { + "version": "0.1.15" + }, + "retimer": { + "version": "2.0.0" + }, + "retry": { + "version": "0.12.0" + }, + "reusify": { + "version": "1.0.4" + }, + "rfdc": { + "version": "1.1.4" + }, + "rimraf": { + "version": "2.7.1", + "requires": { + "glob": "^7.1.3" + } + }, + "ripemd160": { + "version": "2.0.2", + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" + } + }, + "rlp": { + "version": "2.2.4", + "requires": { + "bn.js": "^4.11.1" + } + }, + "rsa-pem-to-jwk": { + "version": "1.1.3", + "requires": { + "object-assign": "^2.0.0", + "rsa-unpack": "0.0.6" + }, + "dependencies": { + "object-assign": { + "version": "2.1.1" + } + } + }, + "rsa-unpack": { + "version": "0.0.6", + "requires": { + "optimist": "~0.3.5" + }, + "dependencies": { + "optimist": { + "version": "0.3.7", + "requires": { + "wordwrap": "~0.0.2" + } + } + } + }, + "run-async": { + "version": "2.3.0", + "requires": { + "is-promise": "^2.1.0" + }, + "dependencies": { + "is-promise": { + "version": "2.1.0" + } + } + }, + "run-parallel": { + "version": "1.1.9" + }, + "run-queue": { + "version": "1.0.3", + "requires": { + "aproba": "^1.1.1" + } + }, + "rxjs": { + "version": "6.5.4", + "requires": { + "tslib": "^1.9.0" + } + }, + "safe-buffer": { + "version": "5.2.0" + }, + "safe-json-parse": { + "version": "1.0.1" + }, + "safe-regex": { + "version": "1.1.0", + "requires": { + "ret": "~0.1.10" + } + }, + "safer-buffer": { + "version": "2.1.2" + }, + "sanitize-filename": { + "version": "1.6.3", + "requires": { + "truncate-utf8-bytes": "^1.0.0" + } + }, + "sax": { + "version": "1.2.4" + }, + "schema-utils": { + "version": "1.0.0", + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + }, + "secp256k1": { + "version": "3.8.0", + "requires": { + "bindings": "^1.5.0", + "bip66": "^1.1.5", + "bn.js": "^4.11.8", + "create-hash": "^1.2.0", + "drbg.js": "^1.0.1", + "elliptic": "^6.5.2", + "nan": "^2.14.0", + "safe-buffer": "^5.1.2" + } + }, + "semaphore": { + "version": "1.1.0" + }, + "semver": { + "version": "5.7.1" + }, + "semver-diff": { + "version": "2.1.0", + "requires": { + "semver": "^5.0.3" + } + }, + "semver-regex": { + "version": "2.0.0" + }, + "send": { + "version": "0.17.1", + "requires": { + "debug": "2.6.9", + "depd": "~1.1.2", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "~1.7.2", + "mime": "1.6.0", + "ms": "2.1.1", + "on-finished": "~2.3.0", + "range-parser": "~1.2.1", + "statuses": "~1.5.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "requires": { + "ms": "2.0.0" + }, + "dependencies": { + "ms": { + "version": "2.0.0" + } + } + }, + "http-errors": { + "version": "1.7.3", + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.4", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + } + }, + "mime": { + "version": "1.6.0" + } + } + }, + "serialize-javascript": { + "version": "2.1.2" + }, + "serve-static": { + "version": "1.14.1", + "requires": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.17.1" + } + }, + "set-blocking": { + "version": "2.0.0" + }, + "set-immediate-shim": { + "version": "1.0.1" + }, + "set-value": { + "version": "2.0.1", + "requires": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.3", + "split-string": "^3.0.1" + } + }, + "setimmediate": { + "version": "1.0.5" + }, + "setprototypeof": { + "version": "1.1.1" + }, + "sha.js": { + "version": "2.4.11", + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "shallow-clone": { + "version": "3.0.1", + "requires": { + "kind-of": "^6.0.2" + } + }, + "shebang-command": { + "version": "1.2.0", + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0" + }, + "shortid": { + "version": "2.2.15", + "requires": { + "nanoid": "^2.1.0" + } + }, + "signal-exit": { + "version": "3.0.2" + }, + "signed-varint": { + "version": "2.0.1", + "requires": { + "varint": "~5.0.0" + } + }, + "simple-concat": { + "version": "1.0.0" + }, + "simple-get": { + "version": "3.1.0", + "requires": { + "decompress-response": "^4.2.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + }, + "dependencies": { + "decompress-response": { + "version": "4.2.1", + "requires": { + "mimic-response": "^2.0.0" + } + }, + "mimic-response": { + "version": "2.0.0" + } + } + }, + "simple-git": { + "version": "1.130.0", + "requires": { + "debug": "^4.0.1" + } + }, + "simple-peer": { + "version": "9.6.2", + "requires": { + "debug": "^4.0.1", + "get-browser-rtc": "^1.0.0", + "queue-microtask": "^1.1.0", + "randombytes": "^2.0.3", + "readable-stream": "^3.4.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.5.0", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "string_decoder": { + "version": "1.3.0", + "requires": { + "safe-buffer": "~5.2.0" + } + } + } + }, + "single-line-log": { + "version": "1.1.2", + "requires": { + "string-width": "^1.0.1" + }, + "dependencies": { + "is-fullwidth-code-point": { + "version": "1.0.0", + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "string-width": { + "version": "1.0.2", + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + } + } + }, + "sinon": { + "version": "7.5.0", + "requires": { + "@sinonjs/commons": "^1.4.0", + "@sinonjs/formatio": "^3.2.1", + "@sinonjs/samsam": "^3.3.3", + "diff": "^3.5.0", + "lolex": "^4.2.0", + "nise": "^1.5.2", + "supports-color": "^5.5.0" + }, + "dependencies": { + "supports-color": { + "version": "5.5.0", + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "slash": { + "version": "3.0.0" + }, + "slice-ansi": { + "version": "2.1.0", + "requires": { + "ansi-styles": "^3.2.0", + "astral-regex": "^1.0.0", + "is-fullwidth-code-point": "^2.0.0" + } + }, + "smart-buffer": { + "version": "4.1.0" + }, + "snapdragon": { + "version": "0.8.2", + "requires": { + "base": "^0.11.1", + "debug": "^2.2.0", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "map-cache": "^0.2.2", + "source-map": "^0.5.6", + "source-map-resolve": "^0.5.0", + "use": "^3.1.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0" + }, + "source-map": { + "version": "0.5.7" + } + } + }, + "snapdragon-node": { + "version": "2.1.1", + "requires": { + "define-property": "^1.0.0", + "isobject": "^3.0.0", + "snapdragon-util": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "requires": { + "is-descriptor": "^1.0.0" + } + } + } + }, + "snapdragon-util": { + "version": "3.0.1", + "requires": { + "kind-of": "^3.2.0" + }, + "dependencies": { + "is-buffer": { + "version": "1.1.6" + }, + "kind-of": { + "version": "3.2.2", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "socket.io": { + "version": "2.1.1", + "requires": { + "debug": "~3.1.0", + "engine.io": "~3.2.0", + "has-binary2": "~1.0.2", + "socket.io-adapter": "~1.1.0", + "socket.io-client": "2.1.1", + "socket.io-parser": "~3.2.0" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "requires": { + "ms": "2.0.0" + } + }, + "engine.io-client": { + "version": "3.2.1", + "requires": { + "component-emitter": "1.2.1", + "component-inherit": "0.0.3", + "debug": "~3.1.0", + "engine.io-parser": "~2.1.1", + "has-cors": "1.1.0", + "indexof": "0.0.1", + "parseqs": "0.0.5", + "parseuri": "0.0.5", + "ws": "~3.3.1", + "xmlhttprequest-ssl": "~1.5.4", + "yeast": "0.1.2" + } + }, + "ms": { + "version": "2.0.0" + }, + "socket.io-client": { + "version": "2.1.1", + "requires": { + "backo2": "1.0.2", + "base64-arraybuffer": "0.1.5", + "component-bind": "1.0.0", + "component-emitter": "1.2.1", + "debug": "~3.1.0", + "engine.io-client": "~3.2.0", + "has-binary2": "~1.0.2", + "has-cors": "1.1.0", + "indexof": "0.0.1", + "object-component": "0.0.3", + "parseqs": "0.0.5", + "parseuri": "0.0.5", + "socket.io-parser": "~3.2.0", + "to-array": "0.1.4" + } + } + } + }, + "socket.io-adapter": { + "version": "1.1.2" + }, + "socket.io-client": { + "version": "2.3.0", + "requires": { + "backo2": "1.0.2", + "base64-arraybuffer": "0.1.5", + "component-bind": "1.0.0", + "component-emitter": "1.2.1", + "debug": "~4.1.0", + "engine.io-client": "~3.4.0", + "has-binary2": "~1.0.2", + "has-cors": "1.1.0", + "indexof": "0.0.1", + "object-component": "0.0.3", + "parseqs": "0.0.5", + "parseuri": "0.0.5", + "socket.io-parser": "~3.3.0", + "to-array": "0.1.4" + }, + "dependencies": { + "isarray": { + "version": "2.0.1" + }, + "ms": { + "version": "2.0.0" + }, + "socket.io-parser": { + "version": "3.3.0", + "requires": { + "component-emitter": "1.2.1", + "debug": "~3.1.0", + "isarray": "2.0.1" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "requires": { + "ms": "2.0.0" + } + } + } + } + } + }, + "socket.io-parser": { + "version": "3.2.0", + "requires": { + "component-emitter": "1.2.1", + "debug": "~3.1.0", + "isarray": "2.0.1" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "requires": { + "ms": "2.0.0" + } + }, + "isarray": { + "version": "2.0.1" + }, + "ms": { + "version": "2.0.0" + } + } + }, + "socket.io-pull-stream": { + "version": "0.1.5", + "requires": { + "data-queue": "0.0.3", + "debug": "^3.1.0", + "pull-stream": "^3.6.2", + "uuid": "^3.2.1" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.2" + } + } + }, + "sonic-boom": { + "version": "0.7.6", + "requires": { + "flatstr": "^1.0.12" + } + }, + "sort-keys": { + "version": "3.0.0", + "requires": { + "is-plain-obj": "^2.0.0" + }, + "dependencies": { + "is-plain-obj": { + "version": "2.1.0" + } + } + }, + "source-list-map": { + "version": "2.0.1" + }, + "source-map": { + "version": "0.6.1" + }, + "source-map-resolve": { + "version": "0.5.3", + "requires": { + "atob": "^2.1.2", + "decode-uri-component": "^0.2.0", + "resolve-url": "^0.2.1", + "source-map-url": "^0.4.0", + "urix": "^0.1.0" + } + }, + "source-map-support": { + "version": "0.5.16", + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "source-map-url": { + "version": "0.4.0" + }, + "space-separated-tokens": { + "version": "1.1.4" + }, + "sparse-array": { + "version": "1.3.2" + }, + "spawn-wrap": { + "version": "1.4.3", + "requires": { + "foreground-child": "^1.5.6", + "mkdirp": "^0.5.0", + "os-homedir": "^1.0.1", + "rimraf": "^2.6.2", + "signal-exit": "^3.0.2", + "which": "^1.3.0" + } + }, + "spdx-correct": { + "version": "3.1.0", + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.2.0" + }, + "spdx-expression-parse": { + "version": "3.0.0", + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.5" + }, + "speedometer": { + "version": "0.1.4" + }, + "split": { + "version": "1.0.1", + "requires": { + "through": "2" + } + }, + "split-string": { + "version": "3.1.0", + "requires": { + "extend-shallow": "^3.0.0" + }, + "dependencies": { + "extend-shallow": { + "version": "3.0.2", + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + } + }, + "is-extendable": { + "version": "1.0.1", + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "split2": { + "version": "2.2.0", + "requires": { + "through2": "^2.0.2" + } + }, + "sprintf-js": { + "version": "1.0.3" + }, + "sshpk": { + "version": "1.16.1", + "requires": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + } + }, + "ssri": { + "version": "7.1.0", + "requires": { + "figgy-pudding": "^3.5.1", + "minipass": "^3.1.1" + } + }, + "stable": { + "version": "0.1.8" + }, + "state-toggle": { + "version": "1.0.2" + }, + "static-extend": { + "version": "0.1.2", + "requires": { + "define-property": "^0.2.5", + "object-copy": "^0.1.0" + } + }, + "stats-webpack-plugin": { + "version": "0.7.0", + "requires": { + "lodash": "^4.17.4" + } + }, + "statuses": { + "version": "1.5.0" + }, + "stream-array": { + "version": "1.1.2", + "requires": { + "readable-stream": "~2.1.0" + }, + "dependencies": { + "readable-stream": { + "version": "2.1.5", + "requires": { + "buffer-shims": "^1.0.0", + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "~1.0.0", + "process-nextick-args": "~1.0.6", + "string_decoder": "~0.10.x", + "util-deprecate": "~1.0.1" + } + } + } + }, + "stream-browserify": { + "version": "2.0.2", + "requires": { + "inherits": "~2.0.1", + "readable-stream": "^2.0.2" + } + }, + "stream-combiner2": { + "version": "1.1.1", + "requires": { + "duplexer2": "~0.1.0", + "readable-stream": "^2.0.2" + } + }, + "stream-each": { + "version": "1.2.3", + "requires": { + "end-of-stream": "^1.1.0", + "stream-shift": "^1.0.0" + } + }, + "stream-http": { + "version": "3.1.0", + "requires": { + "builtin-status-codes": "^3.0.0", + "inherits": "^2.0.1", + "readable-stream": "^3.0.6", + "xtend": "^4.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.5.0", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "string_decoder": { + "version": "1.3.0", + "requires": { + "safe-buffer": "~5.2.0" + } + } + } + }, + "stream-shift": { + "version": "1.0.1" + }, + "stream-to-blob": { + "version": "2.0.0" + }, + "stream-to-it": { + "version": "0.2.0", + "requires": { + "get-iterator": "^1.0.2", + "p-defer": "^3.0.0" + } + }, + "stream-to-pull-stream": { + "version": "1.7.3", + "requires": { + "looper": "^3.0.0", + "pull-stream": "^3.2.3" + } + }, + "streaming-iterables": { + "version": "4.1.2" + }, + "streamroller": { + "version": "1.0.6", + "requires": { + "async": "^2.6.2", + "date-format": "^2.0.0", + "debug": "^3.2.6", + "fs-extra": "^7.0.1", + "lodash": "^4.17.14" + }, + "dependencies": { + "async": { + "version": "2.6.3", + "requires": { + "lodash": "^4.17.14" + } + }, + "debug": { + "version": "3.2.6", + "requires": { + "ms": "^2.1.1" + } + }, + "fs-extra": { + "version": "7.0.1", + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "ms": { + "version": "2.1.2" + } + } + }, + "strftime": { + "version": "0.10.0" + }, + "strict-uri-encode": { + "version": "1.1.0" + }, + "string-template": { + "version": "0.2.1" + }, + "string-width": { + "version": "3.1.0", + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0" + }, + "emoji-regex": { + "version": "7.0.3" + }, + "strip-ansi": { + "version": "5.2.0", + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "string.prototype.trimleft": { + "version": "2.1.1", + "requires": { + "define-properties": "^1.1.3", + "function-bind": "^1.1.1" + } + }, + "string.prototype.trimright": { + "version": "2.1.1", + "requires": { + "define-properties": "^1.1.3", + "function-bind": "^1.1.1" + } + }, + "string_decoder": { + "version": "0.10.31" + }, + "stringify-entities": { + "version": "1.3.2", + "requires": { + "character-entities-html4": "^1.0.0", + "character-entities-legacy": "^1.0.0", + "is-alphanumerical": "^1.0.0", + "is-hexadecimal": "^1.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-bom": { + "version": "3.0.0" + }, + "strip-eof": { + "version": "1.0.0" + }, + "strip-final-newline": { + "version": "2.0.0" + }, + "strip-hex-prefix": { + "version": "1.0.0", + "requires": { + "is-hex-prefixed": "1.0.0" + } + }, + "strip-indent": { + "version": "2.0.0" + }, + "strip-json-comments": { + "version": "2.0.1" + }, + "strip-outer": { + "version": "1.0.1", + "requires": { + "escape-string-regexp": "^1.0.2" + } + }, + "strip-url-auth": { + "version": "1.0.1" + }, + "subarg": { + "version": "1.0.0", + "requires": { + "minimist": "^1.1.0" + } + }, + "sumchecker": { + "version": "2.0.2", + "requires": { + "debug": "^2.2.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0" + } + } + }, + "superstruct": { + "version": "0.6.2", + "requires": { + "clone-deep": "^2.0.1", + "kind-of": "^6.0.1" + }, + "dependencies": { + "clone-deep": { + "version": "2.0.2", + "requires": { + "for-own": "^1.0.0", + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.0", + "shallow-clone": "^1.0.0" + } + }, + "shallow-clone": { + "version": "1.0.0", + "requires": { + "is-extendable": "^0.1.1", + "kind-of": "^5.0.0", + "mixin-object": "^2.0.1" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0" + } + } + } + } + }, + "supports-color": { + "version": "6.1.0", + "requires": { + "has-flag": "^3.0.0" + } + }, + "symbol-observable": { + "version": "1.2.0" + }, + "table": { + "version": "5.4.6", + "requires": { + "ajv": "^6.10.2", + "lodash": "^4.17.14", + "slice-ansi": "^2.1.0", + "string-width": "^3.0.0" + } + }, + "tapable": { + "version": "1.1.3" + }, + "tar": { + "version": "4.4.13", + "requires": { + "chownr": "^1.1.1", + "fs-minipass": "^1.2.5", + "minipass": "^2.8.6", + "minizlib": "^1.2.1", + "mkdirp": "^0.5.0", + "safe-buffer": "^5.1.2", + "yallist": "^3.0.3" + }, + "dependencies": { + "fs-minipass": { + "version": "1.2.7", + "requires": { + "minipass": "^2.6.0" + } + }, + "minipass": { + "version": "2.9.0", + "requires": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + } + } + } + }, + "tar-fs": { + "version": "2.0.0", + "requires": { + "chownr": "^1.1.1", + "mkdirp": "^0.5.1", + "pump": "^3.0.0", + "tar-stream": "^2.0.0" + } + }, + "tar-stream": { + "version": "2.1.0", + "requires": { + "bl": "^3.0.0", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "dependencies": { + "bl": { + "version": "3.0.0", + "requires": { + "readable-stream": "^3.0.1" + } + }, + "readable-stream": { + "version": "3.5.0", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "string_decoder": { + "version": "1.3.0", + "requires": { + "safe-buffer": "~5.2.0" + } + } + } + }, + "tdigest": { + "version": "0.1.1", + "requires": { + "bintrees": "1.0.1" + } + }, + "teeny-request": { + "version": "3.11.3", + "requires": { + "https-proxy-agent": "^2.2.1", + "node-fetch": "^2.2.0", + "uuid": "^3.3.2" + } + }, + "temp": { + "version": "0.9.1", + "requires": { + "rimraf": "~2.6.2" + }, + "dependencies": { + "rimraf": { + "version": "2.6.3", + "requires": { + "glob": "^7.1.3" + } + } + } + }, + "temp-dir": { + "version": "1.0.0" + }, + "temp-write": { + "version": "4.0.0", + "requires": { + "graceful-fs": "^4.1.15", + "is-stream": "^2.0.0", + "make-dir": "^3.0.0", + "temp-dir": "^1.0.0", + "uuid": "^3.3.2" + }, + "dependencies": { + "make-dir": { + "version": "3.0.0", + "requires": { + "semver": "^6.0.0" + } + }, + "semver": { + "version": "6.3.0" + } + } + }, + "term-size": { + "version": "1.2.0", + "requires": { + "execa": "^0.7.0" + }, + "dependencies": { + "cross-spawn": { + "version": "5.1.0", + "requires": { + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "execa": { + "version": "0.7.0", + "requires": { + "cross-spawn": "^5.0.1", + "get-stream": "^3.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "is-stream": { + "version": "1.1.0" + } + } + }, + "terser": { + "version": "4.6.3", + "requires": { + "commander": "^2.20.0", + "source-map": "~0.6.1", + "source-map-support": "~0.5.12" + } + }, + "terser-webpack-plugin": { + "version": "2.3.2", + "requires": { + "cacache": "^13.0.1", + "find-cache-dir": "^3.2.0", + "jest-worker": "^24.9.0", + "schema-utils": "^2.6.1", + "serialize-javascript": "^2.1.2", + "source-map": "^0.6.1", + "terser": "^4.4.3", + "webpack-sources": "^1.4.3" + }, + "dependencies": { + "find-cache-dir": { + "version": "3.2.0", + "requires": { + "commondir": "^1.0.1", + "make-dir": "^3.0.0", + "pkg-dir": "^4.1.0" + } + }, + "find-up": { + "version": "4.1.0", + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "locate-path": { + "version": "5.0.0", + "requires": { + "p-locate": "^4.1.0" + } + }, + "make-dir": { + "version": "3.0.0", + "requires": { + "semver": "^6.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "requires": { + "p-limit": "^2.2.0" + } + }, + "path-exists": { + "version": "4.0.0" + }, + "pkg-dir": { + "version": "4.2.0", + "requires": { + "find-up": "^4.0.0" + } + }, + "schema-utils": { + "version": "2.6.4", + "requires": { + "ajv": "^6.10.2", + "ajv-keywords": "^3.4.1" + } + }, + "semver": { + "version": "6.3.0" + } + } + }, + "test-exclude": { + "version": "5.2.3", + "requires": { + "glob": "^7.1.3", + "minimatch": "^3.0.4", + "read-pkg-up": "^4.0.0", + "require-main-filename": "^2.0.0" + }, + "dependencies": { + "read-pkg-up": { + "version": "4.0.0", + "requires": { + "find-up": "^3.0.0", + "read-pkg": "^3.0.0" + } + } + } + }, + "text-extensions": { + "version": "1.9.0" + }, + "text-table": { + "version": "0.2.0" + }, + "throttleit": { + "version": "0.0.2" + }, + "through": { + "version": "2.3.8" + }, + "through2": { + "version": "2.0.5", + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "through2-filter": { + "version": "3.0.0", + "requires": { + "through2": "~2.0.0", + "xtend": "~4.0.0" + } + }, + "thunky": { + "version": "1.1.0" + }, + "time-cache": { + "version": "0.3.0", + "requires": { + "lodash.throttle": "^4.1.1" + } + }, + "timed-out": { + "version": "4.0.1" + }, + "timers-browserify": { + "version": "2.0.11", + "requires": { + "setimmediate": "^1.0.4" + } + }, + "timestamp-nano": { + "version": "1.0.0" + }, + "tiny-each-async": { + "version": "2.0.3" + }, + "tiny-lr": { + "version": "1.1.1", + "requires": { + "body": "^5.1.0", + "debug": "^3.1.0", + "faye-websocket": "~0.10.0", + "livereload-js": "^2.3.0", + "object-assign": "^4.1.0", + "qs": "^6.4.0" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.2" + } + } + }, + "tiny-secp256k1": { + "version": "1.1.3", + "requires": { + "bindings": "^1.3.0", + "bn.js": "^4.11.8", + "create-hmac": "^1.1.7", + "elliptic": "^6.4.0", + "nan": "^2.13.2" + } + }, + "tmp": { + "version": "0.0.33", + "requires": { + "os-tmpdir": "~1.0.2" + } + }, + "to-absolute-glob": { + "version": "2.0.2", + "requires": { + "is-absolute": "^1.0.0", + "is-negated-glob": "^1.0.0" + } + }, + "to-array": { + "version": "0.1.4" + }, + "to-arraybuffer": { + "version": "1.0.1" + }, + "to-fast-properties": { + "version": "2.0.0" + }, + "to-object-path": { + "version": "0.3.0", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "is-buffer": { + "version": "1.1.6" + }, + "kind-of": { + "version": "3.2.2", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "to-readable-stream": { + "version": "1.0.0" + }, + "to-regex": { + "version": "3.0.2", + "requires": { + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "regex-not": "^1.0.2", + "safe-regex": "^1.1.0" + }, + "dependencies": { + "define-property": { + "version": "2.0.2", + "requires": { + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" + } + }, + "extend-shallow": { + "version": "3.0.2", + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + } + }, + "is-extendable": { + "version": "1.0.1", + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "to-regex-range": { + "version": "5.0.1", + "requires": { + "is-number": "^7.0.0" + }, + "dependencies": { + "is-number": { + "version": "7.0.0" + } + } + }, + "to-through": { + "version": "2.0.0", + "requires": { + "through2": "^2.0.3" + } + }, + "toidentifier": { + "version": "1.0.0" + }, + "tough-cookie": { + "version": "2.4.3", + "requires": { + "psl": "^1.1.24", + "punycode": "^1.4.1" + } + }, + "transform-loader": { + "version": "0.2.4", + "requires": { + "loader-utils": "^1.0.2" + } + }, + "traverse": { + "version": "0.3.9" + }, + "trim": { + "version": "0.0.1" + }, + "trim-lines": { + "version": "1.1.2" + }, + "trim-newlines": { + "version": "2.0.0" + }, + "trim-off-newlines": { + "version": "1.0.1" + }, + "trim-repeated": { + "version": "1.0.0", + "requires": { + "escape-string-regexp": "^1.0.2" + } + }, + "trim-trailing-lines": { + "version": "1.1.2" + }, + "trough": { + "version": "1.0.4" + }, + "truncate-utf8-bytes": { + "version": "1.0.2", + "requires": { + "utf8-byte-length": "^1.0.1" + } + }, + "tryer": { + "version": "1.0.1" + }, + "tslib": { + "version": "1.10.0" + }, + "tty-browserify": { + "version": "0.0.0" + }, + "tunnel-agent": { + "version": "0.6.0", + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5" + }, + "type-check": { + "version": "0.3.2", + "requires": { + "prelude-ls": "~1.1.2" + } + }, + "type-detect": { + "version": "4.0.8" + }, + "type-fest": { + "version": "0.8.1" + }, + "type-is": { + "version": "1.6.18", + "requires": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + } + }, + "typedarray": { + "version": "0.0.6" + }, + "typedarray-to-buffer": { + "version": "3.1.5", + "requires": { + "is-typedarray": "^1.0.0" + } + }, + "typeforce": { + "version": "1.18.0" + }, + "typical": { + "version": "6.0.0" + }, + "uglify-js": { + "version": "3.7.6", + "optional": true, + "requires": { + "commander": "~2.20.3", + "source-map": "~0.6.1" + } + }, + "ultron": { + "version": "1.1.1" + }, + "unc-path-regex": { + "version": "0.1.2" + }, + "unherit": { + "version": "1.1.2", + "requires": { + "inherits": "^2.0.1", + "xtend": "^4.0.1" + } + }, + "unicode-canonical-property-names-ecmascript": { + "version": "1.0.4" + }, + "unicode-match-property-ecmascript": { + "version": "1.0.4", + "requires": { + "unicode-canonical-property-names-ecmascript": "^1.0.4", + "unicode-property-aliases-ecmascript": "^1.0.4" + } + }, + "unicode-match-property-value-ecmascript": { + "version": "1.1.0" + }, + "unicode-property-aliases-ecmascript": { + "version": "1.0.5" + }, + "unified": { + "version": "6.2.0", + "requires": { + "bail": "^1.0.0", + "extend": "^3.0.0", + "is-plain-obj": "^1.1.0", + "trough": "^1.0.0", + "vfile": "^2.0.0", + "x-is-string": "^0.1.0" + }, + "dependencies": { + "is-buffer": { + "version": "1.1.6" + }, + "unist-util-stringify-position": { + "version": "1.1.2" + }, + "vfile": { + "version": "2.3.0", + "requires": { + "is-buffer": "^1.1.4", + "replace-ext": "1.0.0", + "unist-util-stringify-position": "^1.0.0", + "vfile-message": "^1.0.0" + } + }, + "vfile-message": { + "version": "1.1.1", + "requires": { + "unist-util-stringify-position": "^1.1.1" + } + } + } + }, + "union-value": { + "version": "1.0.1", + "requires": { + "arr-union": "^3.1.0", + "get-value": "^2.0.6", + "is-extendable": "^0.1.1", + "set-value": "^2.0.1" + } + }, + "unique-by": { + "version": "1.0.0" + }, + "unique-filename": { + "version": "1.1.1", + "requires": { + "unique-slug": "^2.0.0" + } + }, + "unique-slug": { + "version": "2.0.2", + "requires": { + "imurmurhash": "^0.1.4" + } + }, + "unique-stream": { + "version": "2.3.1", + "requires": { + "json-stable-stringify-without-jsonify": "^1.0.1", + "through2-filter": "^3.0.0" + } + }, + "unique-string": { + "version": "1.0.0", + "requires": { + "crypto-random-string": "^1.0.0" + } + }, + "unist-builder": { + "version": "1.0.4", + "requires": { + "object-assign": "^4.1.0" + } + }, + "unist-util-generated": { + "version": "1.1.5" + }, + "unist-util-is": { + "version": "2.1.3" + }, + "unist-util-position": { + "version": "3.0.4" + }, + "unist-util-remove-position": { + "version": "1.1.4", + "requires": { + "unist-util-visit": "^1.1.0" + } + }, + "unist-util-stringify-position": { + "version": "2.0.2", + "requires": { + "@types/unist": "^2.0.2" + } + }, + "unist-util-visit": { + "version": "1.4.1", + "requires": { + "unist-util-visit-parents": "^2.0.0" + } + }, + "unist-util-visit-parents": { + "version": "2.1.2", + "requires": { + "unist-util-is": "^3.0.0" + }, + "dependencies": { + "unist-util-is": { + "version": "3.0.0" + } + } + }, + "universalify": { + "version": "0.1.2" + }, + "unpipe": { + "version": "1.0.0" + }, + "unset-value": { + "version": "1.0.0", + "requires": { + "has-value": "^0.3.1", + "isobject": "^3.0.0" + }, + "dependencies": { + "has-value": { + "version": "0.3.1", + "requires": { + "get-value": "^2.0.3", + "has-values": "^0.1.4", + "isobject": "^2.0.0" + }, + "dependencies": { + "isobject": { + "version": "2.1.0", + "requires": { + "isarray": "1.0.0" + } + } + } + }, + "has-values": { + "version": "0.1.4" + } + } + }, + "unzip-stream": { + "version": "0.3.0", + "requires": { + "binary": "^0.3.0", + "mkdirp": "^0.5.1" + } + }, + "upath": { + "version": "1.2.0" + }, + "update-notifier": { + "version": "3.0.1", + "requires": { + "boxen": "^3.0.0", + "chalk": "^2.0.1", + "configstore": "^4.0.0", + "has-yarn": "^2.1.0", + "import-lazy": "^2.1.0", + "is-ci": "^2.0.0", + "is-installed-globally": "^0.1.0", + "is-npm": "^3.0.0", + "is-yarn-global": "^0.3.0", + "latest-version": "^5.0.0", + "semver-diff": "^2.0.0", + "xdg-basedir": "^3.0.0" + } + }, + "uri-js": { + "version": "4.2.2", + "requires": { + "punycode": "^2.1.0" + }, + "dependencies": { + "punycode": { + "version": "2.1.1" + } + } + }, + "uri-to-multiaddr": { + "version": "3.0.2", + "requires": { + "is-ip": "^3.1.0", + "multiaddr": "^7.2.1" + } + }, + "urix": { + "version": "0.1.0" + }, + "url": { + "version": "0.11.0", + "requires": { + "punycode": "1.3.2", + "querystring": "0.2.0" + }, + "dependencies": { + "punycode": { + "version": "1.3.2" + } + } + }, + "url-parse-lax": { + "version": "3.0.0", + "requires": { + "prepend-http": "^2.0.0" + } + }, + "url-to-options": { + "version": "1.0.1" + }, + "urlgrey": { + "version": "0.4.4" + }, + "ursa-optional": { + "version": "0.10.1", + "requires": { + "bindings": "^1.5.0", + "nan": "^2.14.0" + } + }, + "use": { + "version": "3.1.1" + }, + "useragent": { + "version": "2.3.0", + "requires": { + "lru-cache": "4.1.x", + "tmp": "0.0.x" + } + }, + "utf8-byte-length": { + "version": "1.0.4" + }, + "util": { + "version": "0.11.1", + "requires": { + "inherits": "2.0.3" + }, + "dependencies": { + "inherits": { + "version": "2.0.3" + } + } + }, + "util-deprecate": { + "version": "1.0.2" + }, + "utils-merge": { + "version": "1.0.1" + }, + "uuid": { + "version": "3.4.0" + }, + "v8-compile-cache": { + "version": "2.0.3" + }, + "validate-npm-package-license": { + "version": "3.0.4", + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "value-or-function": { + "version": "3.0.0" + }, + "varint": { + "version": "5.0.0" + }, + "varint-decoder": { + "version": "0.1.1", + "requires": { + "varint": "^5.0.0" + } + }, + "varuint-bitcoin": { + "version": "1.1.2", + "requires": { + "safe-buffer": "^5.1.1" + } + }, + "vary": { + "version": "1.1.2" + }, + "verror": { + "version": "1.10.0", + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + }, + "dependencies": { + "extsprintf": { + "version": "1.4.0" + } + } + }, + "vfile": { + "version": "4.0.2", + "requires": { + "@types/unist": "^2.0.0", + "is-buffer": "^2.0.0", + "replace-ext": "1.0.0", + "unist-util-stringify-position": "^2.0.0", + "vfile-message": "^2.0.0" + } + }, + "vfile-location": { + "version": "2.0.6" + }, + "vfile-message": { + "version": "2.0.2", + "requires": { + "@types/unist": "^2.0.0", + "unist-util-stringify-position": "^2.0.0" + } + }, + "vfile-reporter": { + "version": "6.0.0", + "requires": { + "repeat-string": "^1.5.0", + "string-width": "^4.0.0", + "supports-color": "^6.0.0", + "unist-util-stringify-position": "^2.0.0", + "vfile-sort": "^2.1.2", + "vfile-statistics": "^1.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.0" + }, + "emoji-regex": { + "version": "8.0.0" + }, + "is-fullwidth-code-point": { + "version": "3.0.0" + }, + "string-width": { + "version": "4.2.0", + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + } + }, + "strip-ansi": { + "version": "6.0.0", + "requires": { + "ansi-regex": "^5.0.0" + } + } + } + }, + "vfile-sort": { + "version": "2.2.1" + }, + "vfile-statistics": { + "version": "1.1.3" + }, + "vinyl": { + "version": "2.2.0", + "requires": { + "clone": "^2.1.1", + "clone-buffer": "^1.0.0", + "clone-stats": "^1.0.0", + "cloneable-readable": "^1.0.0", + "remove-trailing-separator": "^1.0.1", + "replace-ext": "^1.0.0" + } + }, + "vinyl-fs": { + "version": "3.0.3", + "requires": { + "fs-mkdirp-stream": "^1.0.0", + "glob-stream": "^6.1.0", + "graceful-fs": "^4.0.0", + "is-valid-glob": "^1.0.0", + "lazystream": "^1.0.0", + "lead": "^1.0.0", + "object.assign": "^4.0.4", + "pumpify": "^1.3.5", + "readable-stream": "^2.3.3", + "remove-bom-buffer": "^3.0.0", + "remove-bom-stream": "^1.2.0", + "resolve-options": "^1.1.0", + "through2": "^2.0.0", + "to-through": "^2.0.0", + "value-or-function": "^3.0.0", + "vinyl": "^2.0.0", + "vinyl-sourcemap": "^1.1.0" + } + }, + "vinyl-sourcemap": { + "version": "1.1.0", + "requires": { + "append-buffer": "^1.0.2", + "convert-source-map": "^1.5.0", + "graceful-fs": "^4.1.6", + "normalize-path": "^2.1.1", + "now-and-later": "^2.0.0", + "remove-bom-buffer": "^3.0.0", + "vinyl": "^2.0.0" + }, + "dependencies": { + "normalize-path": { + "version": "2.1.1", + "requires": { + "remove-trailing-separator": "^1.0.1" + } + } + } + }, + "vm-browserify": { + "version": "1.1.2" + }, + "void-elements": { + "version": "2.0.1" + }, + "vue-template-compiler": { + "version": "2.6.11", + "requires": { + "de-indent": "^1.0.2", + "he": "^1.1.0" + } + }, + "watchpack": { + "version": "1.6.0", + "requires": { + "chokidar": "^2.0.2", + "graceful-fs": "^4.1.2", + "neo-async": "^2.5.0" + } + }, + "webcrypto": { + "version": "0.1.1", + "requires": { + "crypto-browserify": "^3.10.0", + "detect-node": "^2.0.3" + } + }, + "webpack": { + "version": "4.41.5", + "requires": { + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/helper-module-context": "1.8.5", + "@webassemblyjs/wasm-edit": "1.8.5", + "@webassemblyjs/wasm-parser": "1.8.5", + "acorn": "^6.2.1", + "ajv": "^6.10.2", + "ajv-keywords": "^3.4.1", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^4.1.0", + "eslint-scope": "^4.0.3", + "json-parse-better-errors": "^1.0.2", + "loader-runner": "^2.4.0", + "loader-utils": "^1.2.3", + "memory-fs": "^0.4.1", + "micromatch": "^3.1.10", + "mkdirp": "^0.5.1", + "neo-async": "^2.6.1", + "node-libs-browser": "^2.2.1", + "schema-utils": "^1.0.0", + "tapable": "^1.1.3", + "terser-webpack-plugin": "^1.4.3", + "watchpack": "^1.6.0", + "webpack-sources": "^1.4.1" + }, + "dependencies": { + "acorn": { + "version": "6.4.0" + }, + "cacache": { + "version": "12.0.3", + "requires": { + "bluebird": "^3.5.5", + "chownr": "^1.1.1", + "figgy-pudding": "^3.5.1", + "glob": "^7.1.4", + "graceful-fs": "^4.1.15", + "infer-owner": "^1.0.3", + "lru-cache": "^5.1.1", + "mississippi": "^3.0.0", + "mkdirp": "^0.5.1", + "move-concurrently": "^1.0.1", + "promise-inflight": "^1.0.1", + "rimraf": "^2.6.3", + "ssri": "^6.0.1", + "unique-filename": "^1.1.1", + "y18n": "^4.0.0" + } + }, + "enhanced-resolve": { + "version": "4.1.1", + "requires": { + "graceful-fs": "^4.1.2", + "memory-fs": "^0.5.0", + "tapable": "^1.0.0" + }, + "dependencies": { + "memory-fs": { + "version": "0.5.0", + "requires": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + } + } + } + }, + "is-wsl": { + "version": "1.1.0" + }, + "lru-cache": { + "version": "5.1.1", + "requires": { + "yallist": "^3.0.2" + } + }, + "ssri": { + "version": "6.0.1", + "requires": { + "figgy-pudding": "^3.5.1" + } + }, + "terser-webpack-plugin": { + "version": "1.4.3", + "requires": { + "cacache": "^12.0.2", + "find-cache-dir": "^2.1.0", + "is-wsl": "^1.1.0", + "schema-utils": "^1.0.0", + "serialize-javascript": "^2.1.2", + "source-map": "^0.6.1", + "terser": "^4.1.2", + "webpack-sources": "^1.4.0", + "worker-farm": "^1.7.0" + } + } + } + }, + "webpack-bundle-analyzer": { + "version": "3.6.0", + "requires": { + "acorn": "^6.0.7", + "acorn-walk": "^6.1.1", + "bfj": "^6.1.1", + "chalk": "^2.4.1", + "commander": "^2.18.0", + "ejs": "^2.6.1", + "express": "^4.16.3", + "filesize": "^3.6.1", + "gzip-size": "^5.0.0", + "lodash": "^4.17.15", + "mkdirp": "^0.5.1", + "opener": "^1.5.1", + "ws": "^6.0.0" + }, + "dependencies": { + "acorn": { + "version": "6.4.0" + }, + "gzip-size": { + "version": "5.1.1", + "requires": { + "duplexer": "^0.1.1", + "pify": "^4.0.1" + } + }, + "ws": { + "version": "6.2.1", + "requires": { + "async-limiter": "~1.0.0" + } + } + } + }, + "webpack-cli": { + "version": "3.3.10", + "requires": { + "chalk": "2.4.2", + "cross-spawn": "6.0.5", + "enhanced-resolve": "4.1.0", + "findup-sync": "3.0.0", + "global-modules": "2.0.0", + "import-local": "2.0.0", + "interpret": "1.2.0", + "loader-utils": "1.2.3", + "supports-color": "6.1.0", + "v8-compile-cache": "2.0.3", + "yargs": "13.2.4" + }, + "dependencies": { + "findup-sync": { + "version": "3.0.0", + "requires": { + "detect-file": "^1.0.0", + "is-glob": "^4.0.0", + "micromatch": "^3.0.4", + "resolve-dir": "^1.0.1" + } + }, + "yargs": { + "version": "13.2.4", + "requires": { + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "os-locale": "^3.1.0", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.0" + } + } + } + }, + "webpack-dev-middleware": { + "version": "3.7.2", + "requires": { + "memory-fs": "^0.4.1", + "mime": "^2.4.4", + "mkdirp": "^0.5.1", + "range-parser": "^1.2.1", + "webpack-log": "^2.0.0" + } + }, + "webpack-log": { + "version": "2.0.0", + "requires": { + "ansi-colors": "^3.0.0", + "uuid": "^3.3.2" + }, + "dependencies": { + "ansi-colors": { + "version": "3.2.4" + } + } + }, + "webpack-merge": { + "version": "4.2.2", + "requires": { + "lodash": "^4.17.15" + } + }, + "webpack-sources": { + "version": "1.4.3", + "requires": { + "source-list-map": "^2.0.0", + "source-map": "~0.6.1" + } + }, + "webrtcsupport": { + "version": "2.2.0" + }, + "websocket-driver": { + "version": "0.7.3", + "requires": { + "http-parser-js": ">=0.4.0 <0.4.11", + "safe-buffer": ">=5.1.0", + "websocket-extensions": ">=0.1.1" + } + }, + "websocket-extensions": { + "version": "0.1.3" + }, + "which": { + "version": "1.3.1", + "requires": { + "isexe": "^2.0.0" + } + }, + "which-module": { + "version": "2.0.0" + }, + "which-pm-runs": { + "version": "1.0.0" + }, + "wide-align": { + "version": "1.1.3", + "requires": { + "string-width": "^1.0.2 || 2" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0" + }, + "string-width": { + "version": "2.1.1", + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "widest-line": { + "version": "2.0.1", + "requires": { + "string-width": "^2.1.1" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0" + }, + "string-width": { + "version": "2.1.1", + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "wif": { + "version": "2.0.6", + "requires": { + "bs58check": "<3.0.0" + } + }, + "word-wrap": { + "version": "1.2.3" + }, + "wordwrap": { + "version": "0.0.3" + }, + "worker-farm": { + "version": "1.7.0", + "requires": { + "errno": "~0.1.7" + } + }, + "wrap-ansi": { + "version": "5.1.0", + "requires": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0" + }, + "strip-ansi": { + "version": "5.2.0", + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "wrappy": { + "version": "1.0.2" + }, + "write": { + "version": "1.0.3", + "requires": { + "mkdirp": "^0.5.1" + } + }, + "write-file-atomic": { + "version": "2.4.3", + "requires": { + "graceful-fs": "^4.1.11", + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.2" + } + }, + "ws": { + "version": "3.3.3", + "requires": { + "async-limiter": "~1.0.0", + "safe-buffer": "~5.1.0", + "ultron": "~1.1.0" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2" + } + } + }, + "x-is-string": { + "version": "0.1.0" + }, + "xdg-basedir": { + "version": "3.0.0" + }, + "xmlbuilder": { + "version": "12.0.0" + }, + "xmlhttprequest-ssl": { + "version": "1.5.5" + }, + "xor-distance": { + "version": "2.0.0" + }, + "xsalsa20": { + "version": "1.1.0" + }, + "xtend": { + "version": "4.0.2" + }, + "y18n": { + "version": "4.0.0" + }, + "yallist": { + "version": "3.1.1" + }, + "yargs": { + "version": "13.3.0", + "requires": { + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.1" + } + }, + "yargs-parser": { + "version": "13.1.1", + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + }, + "yargs-promise": { + "version": "1.1.0" + }, + "yargs-unparser": { + "version": "1.6.0", + "requires": { + "flat": "^4.1.0", + "lodash": "^4.17.15", + "yargs": "^13.3.0" + } + }, + "yauzl": { + "version": "2.4.1", + "requires": { + "fd-slicer": "~1.0.1" + } + }, + "yeast": { + "version": "0.1.2" + }, + "zcash-block": { + "version": "2.0.0", + "requires": { + "multihashing": "~0.3.3" + } + } + } + }, + "is-absolute-url": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-2.1.0.tgz", + "integrity": "sha1-UFMN+4T8yap9vnhS6Do3uTufKqY=", + "dev": true + }, + "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=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "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.5" + } + } + } + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "dev": true, + "requires": { + "binary-extensions": "^1.0.0" + } + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "is-callable": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.5.tgz", + "integrity": "sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q==", + "dev": true + }, + "is-color-stop": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-color-stop/-/is-color-stop-1.1.0.tgz", + "integrity": "sha1-z/9HGu5N1cnhWFmPvhKWe1za00U=", + "dev": true, + "requires": { + "css-color-names": "^0.0.4", + "hex-color-regex": "^1.1.0", + "hsl-regex": "^1.0.0", + "hsla-regex": "^1.0.0", + "rgb-regex": "^1.0.1", + "rgba-regex": "^1.0.0" + } + }, + "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=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "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.5" + } + } + } + }, + "is-date-object": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", + "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", + "dev": true + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "dependencies": { + "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==", + "dev": true + } + } + }, + "is-directory": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz", + "integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE=", + "dev": true + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-html": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-html/-/is-html-1.1.0.tgz", + "integrity": "sha1-4E8cGNOUhRETlvmgJz6rUa8hhGQ=", + "dev": true, + "requires": { + "html-tags": "^1.0.0" + } + }, + "is-number": { + "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.0.2" + }, + "dependencies": { + "kind-of": { + "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.5" + } + } + } + }, + "is-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", + "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", + "dev": true + }, + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "requires": { + "isobject": "^3.0.1" + } + }, + "is-regex": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz", + "integrity": "sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, + "is-resolvable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", + "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==", + "dev": true + }, + "is-svg": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-svg/-/is-svg-3.0.0.tgz", + "integrity": "sha512-gi4iHK53LR2ujhLVVj+37Ykh9GLqYHX6JOVXbLAucaG/Cqw9xwdFOjDM2qeifLs1sF1npXXFvDu0r5HNgCMrzQ==", + "dev": true, + "requires": { + "html-comment-regex": "^1.1.0" + } + }, + "is-symbol": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", + "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", + "dev": true, + "requires": { + "has-symbols": "^1.0.1" + } + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", + "dev": true + }, + "is-url": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz", + "integrity": "sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==", + "dev": true + }, + "is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "dev": true + }, + "is-wsl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", + "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", + "dev": true + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "js-yaml": { + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", + "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "dependencies": { + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + } + } + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "dev": true + }, + "jsdom": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-14.1.0.tgz", + "integrity": "sha512-O901mfJSuTdwU2w3Sn+74T+RnDVP+FuV5fH8tcPWyqrseRAb0s5xOtPgCFiPOtLcyK7CLIJwPyD83ZqQWvA5ng==", + "dev": true, + "requires": { + "abab": "^2.0.0", + "acorn": "^6.0.4", + "acorn-globals": "^4.3.0", + "array-equal": "^1.0.0", + "cssom": "^0.3.4", + "cssstyle": "^1.1.1", + "data-urls": "^1.1.0", + "domexception": "^1.0.1", + "escodegen": "^1.11.0", + "html-encoding-sniffer": "^1.0.2", + "nwsapi": "^2.1.3", + "parse5": "5.1.0", + "pn": "^1.1.0", + "request": "^2.88.0", + "request-promise-native": "^1.0.5", + "saxes": "^3.1.9", + "symbol-tree": "^3.2.2", + "tough-cookie": "^2.5.0", + "w3c-hr-time": "^1.0.1", + "w3c-xmlserializer": "^1.1.2", + "webidl-conversions": "^4.0.2", + "whatwg-encoding": "^1.0.5", + "whatwg-mimetype": "^2.3.0", + "whatwg-url": "^7.0.0", + "ws": "^6.1.2", + "xml-name-validator": "^3.0.0" + }, + "dependencies": { + "escodegen": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.13.0.tgz", + "integrity": "sha512-eYk2dCkxR07DsHA/X2hRBj0CFAZeri/LyDMc0C8JT1Hqi6JnVpMhJ7XFITbb0+yZS3lVkaPL2oCkZ3AVmeVbMw==", + "dev": true, + "requires": { + "esprima": "^4.0.1", + "estraverse": "^4.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1", + "source-map": "~0.6.1" + } + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "optional": true + }, + "ws": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz", + "integrity": "sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==", + "dev": true, + "requires": { + "async-limiter": "~1.0.0" + } + } + } + }, + "jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true + }, + "json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "dev": true + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", + "dev": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", + "dev": true + }, + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "dev": true, + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true + }, + "leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "dev": true + }, + "levenary": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/levenary/-/levenary-1.1.0.tgz", + "integrity": "sha512-VHcwhO0UTpUW7rLPN2/OiWJdgA1e9BqEDALhrgCe/F+uUJnep6CoUsTzMeP8Rh0NGr9uKquXxqe7lwLZo509nQ==", + "dev": true, + "requires": { + "leven": "^3.1.0" + } + }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "lodash": { + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", + "dev": true + }, + "lodash.clone": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clone/-/lodash.clone-4.5.0.tgz", + "integrity": "sha1-GVhwRQ9aExkkeN9Lw9I9LeoZB7Y=", + "dev": true + }, + "lodash.sortby": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", + "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=", + "dev": true + }, + "lodash.uniq": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", + "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=", + "dev": true + }, + "log-symbols": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", + "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", + "dev": true, + "requires": { + "chalk": "^2.0.1" + } + }, + "loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dev": true, + "requires": { + "js-tokens": "^3.0.0 || ^4.0.0" + } + }, + "magic-string": { + "version": "0.22.5", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.22.5.tgz", + "integrity": "sha512-oreip9rJZkzvA8Qzk9HFs8fZGF/u7H/gtrE8EN6RjKJ9kh2HlC+yQ2QezifqTZfGyiuAV0dRv5a+y/8gBb1m9w==", + "dev": true, + "requires": { + "vlq": "^0.2.2" + } + }, + "map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", + "dev": true + }, + "map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "dev": true, + "requires": { + "object-visit": "^1.0.0" + } + }, + "md5.js": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", + "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "dev": true, + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "mdn-data": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.4.tgz", + "integrity": "sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA==", + "dev": true + }, + "merge-source-map": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/merge-source-map/-/merge-source-map-1.0.4.tgz", + "integrity": "sha1-pd5GU42uhNQRTMXqArR3KmNGcB8=", + "dev": true, + "requires": { + "source-map": "^0.5.6" + } + }, + "merge2": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.3.0.tgz", + "integrity": "sha512-2j4DAdlBOkiSZIsaXk4mTE3sRS02yBHAtfy127xRV3bQUFqXkjHCHLW6Scv7DwNRbIWNHH8zpnz9zMaKXIdvYw==", + "dev": true + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "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.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "miller-rabin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", + "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "dev": true, + "requires": { + "bn.js": "^4.0.0", + "brorand": "^1.0.1" + } + }, + "mime-db": { + "version": "1.43.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.43.0.tgz", + "integrity": "sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ==", + "dev": true + }, + "mime-types": { + "version": "2.1.26", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.26.tgz", + "integrity": "sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ==", + "dev": true, + "requires": { + "mime-db": "1.43.0" + } + }, + "mimic-fn": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", + "dev": true + }, + "minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "dev": true + }, + "minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "mixin-deep": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", + "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", + "dev": true, + "requires": { + "for-in": "^1.0.2", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true, + "requires": { + "minimist": "0.0.8" + }, + "dependencies": { + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + } + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "nan": { + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz", + "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==", + "dev": true, + "optional": true + }, + "nanomatch": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", + "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "fragment-cache": "^0.2.1", + "is-windows": "^1.0.2", + "kind-of": "^6.0.2", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + } + }, + "nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "dev": true + }, + "node-addon-api": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-1.7.1.tgz", + "integrity": "sha512-2+DuKodWvwRTrCfKOeR24KIc5unKjOh8mz17NCzVnHWfjAdDqbfbjqh7gUT+BkXBRQM52+xCHciKWonJ3CbJMQ==", + "dev": true + }, + "node-forge": { + "version": "0.7.6", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.7.6.tgz", + "integrity": "sha512-sol30LUpz1jQFBjOKwbjxijiE3b6pjd74YwfD0fJOKPjF+fONKb2Yg8rYgS6+bK6VDl+/wfr4IYpC7jDzLUIfw==", + "dev": true + }, + "node-libs-browser": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.1.tgz", + "integrity": "sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q==", + "dev": true, + "requires": { + "assert": "^1.1.1", + "browserify-zlib": "^0.2.0", + "buffer": "^4.3.0", + "console-browserify": "^1.1.0", + "constants-browserify": "^1.0.0", + "crypto-browserify": "^3.11.0", + "domain-browser": "^1.1.1", + "events": "^3.0.0", + "https-browserify": "^1.0.0", + "os-browserify": "^0.3.0", + "path-browserify": "0.0.1", + "process": "^0.11.10", + "punycode": "^1.2.4", + "querystring-es3": "^0.2.0", + "readable-stream": "^2.3.3", + "stream-browserify": "^2.0.1", + "stream-http": "^2.7.2", + "string_decoder": "^1.0.0", + "timers-browserify": "^2.0.4", + "tty-browserify": "0.0.0", + "url": "^0.11.0", + "util": "^0.11.0", + "vm-browserify": "^1.0.1" + }, + "dependencies": { + "buffer": { + "version": "4.9.2", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", + "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==", + "dev": true, + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4", + "isarray": "^1.0.0" + } + }, + "events": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.1.0.tgz", + "integrity": "sha512-Rv+u8MLHNOdMjTAFeT3nCjHn2aGlx435FP/sDHNaRhDEMwyI/aB22Kj2qIN8R0cw3z28psEQLYwxVKLsKrMgWg==", + "dev": true + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "timers-browserify": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.11.tgz", + "integrity": "sha512-60aV6sgJ5YEbzUdn9c8kYGIqOubPoUdqQCul3SBAsRCZ40s6Y5cMcrW4dt3/k/EsbLVJNl9n6Vz3fTc+k2GeKQ==", + "dev": true, + "requires": { + "setimmediate": "^1.0.4" + } + }, + "tty-browserify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", + "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=", + "dev": true + }, + "util": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz", + "integrity": "sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ==", + "dev": true, + "requires": { + "inherits": "2.0.3" + } + } + } + }, + "node-releases": { + "version": "1.1.46", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.46.tgz", + "integrity": "sha512-YOjdx+Uoh9FbRO7yVYbnbt1puRWPQMemR3SutLeyv2XfxKs1ihpe0OLAUwBPEP2ImNH/PZC7SEiC6j32dwRZ7g==", + "dev": true, + "requires": { + "semver": "^6.3.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "normalize-html-whitespace": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/normalize-html-whitespace/-/normalize-html-whitespace-1.0.0.tgz", + "integrity": "sha512-9ui7CGtOOlehQu0t/OhhlmDyc71mKVlv+4vF+me4iZLPrNtRL2xoquEdfZxasC/bdQi/Hr3iTrpyRKIG+ocabA==", + "dev": true + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + }, + "normalize-url": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-3.3.0.tgz", + "integrity": "sha512-U+JJi7duF1o+u2pynbp2zXDW2/PADgC30f0GsHZtRh+HOcXHnw137TrNlyxxRvWW5fjKd3bcLHPxofWuCjaeZg==", + "dev": true + }, + "nth-check": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz", + "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==", + "dev": true, + "requires": { + "boolbase": "~1.0.0" + } + }, + "nwsapi": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.0.tgz", + "integrity": "sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ==", + "dev": true + }, + "oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + }, + "object-copy": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "dev": true, + "requires": { + "copy-descriptor": "^0.1.0", + "define-property": "^0.2.5", + "kind-of": "^3.0.3" + }, + "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=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "kind-of": { + "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.5" + } + } + } + }, + "object-inspect": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.4.1.tgz", + "integrity": "sha512-wqdhLpfCUbEsoEwl3FXwGyv8ief1k/1aUdIPCqVnupM6e8l63BEJdiF/0swtn04/8p05tG/T0FrpTlfwvljOdw==", + "dev": true + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true + }, + "object-visit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", + "dev": true, + "requires": { + "isobject": "^3.0.0" + } + }, + "object.assign": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", + "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "function-bind": "^1.1.1", + "has-symbols": "^1.0.0", + "object-keys": "^1.0.11" + } + }, + "object.getownpropertydescriptors": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.0.tgz", + "integrity": "sha512-Z53Oah9A3TdLoblT7VKJaTDdXdT+lQO+cNpKVnya5JDe9uLvzu1YyY1yFDFrcxrlRgWrEFH0jJtD/IbuwjcEVg==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1" + } + }, + "object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "dev": true, + "requires": { + "isobject": "^3.0.1" + } + }, + "object.values": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.1.tgz", + "integrity": "sha512-WTa54g2K8iu0kmS/us18jEmdv1a4Wi//BZ/DTVYEcH0XhLM5NYdpDHja3gt57VrZLcNAO2WGA+KpWsDBaHt6eA==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1", + "function-bind": "^1.1.1", + "has": "^1.0.3" + } + }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "dev": true, + "requires": { + "ee-first": "1.1.1" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "onetime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", + "dev": true, + "requires": { + "mimic-fn": "^1.0.0" + } + }, + "opn": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/opn/-/opn-5.5.0.tgz", + "integrity": "sha512-PqHpggC9bLV0VeWcdKhkpxY+3JTzetLSqTCWL/z/tFIbI6G8JCjondXklT1JinczLz2Xib62sSp0T/gKT4KksA==", + "dev": true, + "requires": { + "is-wsl": "^1.1.0" + } + }, + "optionator": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "dev": true, + "requires": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + } + }, + "ora": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ora/-/ora-2.1.0.tgz", + "integrity": "sha512-hNNlAd3gfv/iPmsNxYoAPLvxg7HuPozww7fFonMZvL84tP6Ox5igfk5j/+a9rtJJwqMgKK+JgWsAQik5o0HTLA==", + "dev": true, + "requires": { + "chalk": "^2.3.1", + "cli-cursor": "^2.1.0", + "cli-spinners": "^1.1.0", + "log-symbols": "^2.2.0", + "strip-ansi": "^4.0.0", + "wcwidth": "^1.0.1" + } + }, + "os-browserify": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", + "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=", + "dev": true + }, + "p-limit": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.2.tgz", + "integrity": "sha512-WGR+xHecKTr7EbUEhyLSh5Dube9JtdiG78ufaeLxTgpudf/20KqyMioIUZJAezlTIi6evxuoUs9YXc11cU+yzQ==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "pako": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.10.tgz", + "integrity": "sha512-0DTvPVU3ed8+HNXOu5Bs+o//Mbdj9VNQMUOe9oKCwh8l0GNwpTDMKCWbRjgtD291AWnkAgkqA/LOnQS8AmS1tw==", + "dev": true + }, + "parcel-bundler": { + "version": "1.12.4", + "resolved": "https://registry.npmjs.org/parcel-bundler/-/parcel-bundler-1.12.4.tgz", + "integrity": "sha512-G+iZGGiPEXcRzw0fiRxWYCKxdt/F7l9a0xkiU4XbcVRJCSlBnioWEwJMutOCCpoQmaQtjB4RBHDGIHN85AIhLQ==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/core": "^7.4.4", + "@babel/generator": "^7.4.4", + "@babel/parser": "^7.4.4", + "@babel/plugin-transform-flow-strip-types": "^7.4.4", + "@babel/plugin-transform-modules-commonjs": "^7.4.4", + "@babel/plugin-transform-react-jsx": "^7.0.0", + "@babel/preset-env": "^7.4.4", + "@babel/runtime": "^7.4.4", + "@babel/template": "^7.4.4", + "@babel/traverse": "^7.4.4", + "@babel/types": "^7.4.4", + "@iarna/toml": "^2.2.0", + "@parcel/fs": "^1.11.0", + "@parcel/logger": "^1.11.1", + "@parcel/utils": "^1.11.0", + "@parcel/watcher": "^1.12.1", + "@parcel/workers": "^1.11.0", + "ansi-to-html": "^0.6.4", + "babylon-walk": "^1.0.2", + "browserslist": "^4.1.0", + "chalk": "^2.1.0", + "clone": "^2.1.1", + "command-exists": "^1.2.6", + "commander": "^2.11.0", + "core-js": "^2.6.5", + "cross-spawn": "^6.0.4", + "css-modules-loader-core": "^1.1.0", + "cssnano": "^4.0.0", + "deasync": "^0.1.14", + "dotenv": "^5.0.0", + "dotenv-expand": "^5.1.0", + "envinfo": "^7.3.1", + "fast-glob": "^2.2.2", + "filesize": "^3.6.0", + "get-port": "^3.2.0", + "htmlnano": "^0.2.2", + "is-glob": "^4.0.0", + "is-url": "^1.2.2", + "js-yaml": "^3.10.0", + "json5": "^1.0.1", + "micromatch": "^3.0.4", + "mkdirp": "^0.5.1", + "node-forge": "^0.7.1", + "node-libs-browser": "^2.0.0", + "opn": "^5.1.0", + "postcss": "^7.0.11", + "postcss-value-parser": "^3.3.1", + "posthtml": "^0.11.2", + "posthtml-parser": "^0.4.0", + "posthtml-render": "^1.1.3", + "resolve": "^1.4.0", + "semver": "^5.4.1", + "serialize-to-js": "^3.0.0", + "serve-static": "^1.12.4", + "source-map": "0.6.1", + "terser": "^3.7.3", + "v8-compile-cache": "^2.0.0", + "ws": "^5.1.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "parse-asn1": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.4.tgz", + "integrity": "sha512-Qs5duJcuvNExRfFZ99HDD3z4mAi3r9Wl/FOjEOijlxwCZs7E7mW2vjTpgQ4J8LpTF8x5v+1Vn5UQFejmWT11aw==", + "dev": true, + "requires": { + "asn1.js": "^4.0.0", + "browserify-aes": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.0", + "pbkdf2": "^3.0.3", + "safe-buffer": "^5.1.1" + } + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, + "parse5": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.0.tgz", + "integrity": "sha512-fxNG2sQjHvlVAYmzBZS9YlDp6PTSSDwa98vkD4QgVDDCAo84z5X1t5XyJQ62ImdLXx5NdIIfihey6xpum9/gRQ==", + "dev": true + }, + "parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "dev": true + }, + "pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", + "dev": true + }, + "path-browserify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.1.tgz", + "integrity": "sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ==", + "dev": true + }, + "path-dirname": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", + "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", + "dev": true + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true + }, + "path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "dev": true + }, + "pbkdf2": { + "version": "3.0.17", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.17.tgz", + "integrity": "sha512-U/il5MsrZp7mGg3mSQfn742na2T+1/vHDCG5/iTI3X9MKUuYUZVLQhyRsg06mCgDBTd57TxzgZt7P+fYfjRLtA==", + "dev": true, + "requires": { + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4", + "ripemd160": "^2.0.1", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", + "dev": true + }, + "physical-cpu-count": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/physical-cpu-count/-/physical-cpu-count-2.0.0.tgz", + "integrity": "sha1-GN4vl+S/epVRrXURlCtUlverpmA=", + "dev": true + }, + "pn": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pn/-/pn-1.1.0.tgz", + "integrity": "sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA==", + "dev": true + }, + "posix-character-classes": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", + "dev": true + }, + "postcss": { + "version": "7.0.26", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.26.tgz", + "integrity": "sha512-IY4oRjpXWYshuTDFxMVkJDtWIk2LhsTlu8bZnbEJA4+bYT16Lvpo8Qv6EvDumhYRgzjZl489pmsY3qVgJQ08nA==", + "dev": true, + "requires": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "postcss-calc": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-7.0.1.tgz", + "integrity": "sha512-oXqx0m6tb4N3JGdmeMSc/i91KppbYsFZKdH0xMOqK8V1rJlzrKlTdokz8ozUXLVejydRN6u2IddxpcijRj2FqQ==", + "dev": true, + "requires": { + "css-unit-converter": "^1.1.1", + "postcss": "^7.0.5", + "postcss-selector-parser": "^5.0.0-rc.4", + "postcss-value-parser": "^3.3.1" + } + }, + "postcss-colormin": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-4.0.3.tgz", + "integrity": "sha512-WyQFAdDZpExQh32j0U0feWisZ0dmOtPl44qYmJKkq9xFWY3p+4qnRzCHeNrkeRhwPHz9bQ3mo0/yVkaply0MNw==", + "dev": true, + "requires": { + "browserslist": "^4.0.0", + "color": "^3.0.0", + "has": "^1.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + } + }, + "postcss-convert-values": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-4.0.1.tgz", + "integrity": "sha512-Kisdo1y77KUC0Jmn0OXU/COOJbzM8cImvw1ZFsBgBgMgb1iL23Zs/LXRe3r+EZqM3vGYKdQ2YJVQ5VkJI+zEJQ==", + "dev": true, + "requires": { + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + } + }, + "postcss-discard-comments": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-4.0.2.tgz", + "integrity": "sha512-RJutN259iuRf3IW7GZyLM5Sw4GLTOH8FmsXBnv8Ab/Tc2k4SR4qbV4DNbyyY4+Sjo362SyDmW2DQ7lBSChrpkg==", + "dev": true, + "requires": { + "postcss": "^7.0.0" + } + }, + "postcss-discard-duplicates": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-4.0.2.tgz", + "integrity": "sha512-ZNQfR1gPNAiXZhgENFfEglF93pciw0WxMkJeVmw8eF+JZBbMD7jp6C67GqJAXVZP2BWbOztKfbsdmMp/k8c6oQ==", + "dev": true, + "requires": { + "postcss": "^7.0.0" + } + }, + "postcss-discard-empty": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-4.0.1.tgz", + "integrity": "sha512-B9miTzbznhDjTfjvipfHoqbWKwd0Mj+/fL5s1QOz06wufguil+Xheo4XpOnc4NqKYBCNqqEzgPv2aPBIJLox0w==", + "dev": true, + "requires": { + "postcss": "^7.0.0" + } + }, + "postcss-discard-overridden": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-4.0.1.tgz", + "integrity": "sha512-IYY2bEDD7g1XM1IDEsUT4//iEYCxAmP5oDSFMVU/JVvT7gh+l4fmjciLqGgwjdWpQIdb0Che2VX00QObS5+cTg==", + "dev": true, + "requires": { + "postcss": "^7.0.0" + } + }, + "postcss-merge-longhand": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-4.0.11.tgz", + "integrity": "sha512-alx/zmoeXvJjp7L4mxEMjh8lxVlDFX1gqWHzaaQewwMZiVhLo42TEClKaeHbRf6J7j82ZOdTJ808RtN0ZOZwvw==", + "dev": true, + "requires": { + "css-color-names": "0.0.4", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0", + "stylehacks": "^4.0.0" + } + }, + "postcss-merge-rules": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-4.0.3.tgz", + "integrity": "sha512-U7e3r1SbvYzO0Jr3UT/zKBVgYYyhAz0aitvGIYOYK5CPmkNih+WDSsS5tvPrJ8YMQYlEMvsZIiqmn7HdFUaeEQ==", + "dev": true, + "requires": { + "browserslist": "^4.0.0", + "caniuse-api": "^3.0.0", + "cssnano-util-same-parent": "^4.0.0", + "postcss": "^7.0.0", + "postcss-selector-parser": "^3.0.0", + "vendors": "^1.0.0" + }, + "dependencies": { + "postcss-selector-parser": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-3.1.1.tgz", + "integrity": "sha1-T4dfSvsMllc9XPTXQBGu4lCn6GU=", + "dev": true, + "requires": { + "dot-prop": "^4.1.1", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + } + } + } + }, + "postcss-minify-font-values": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-4.0.2.tgz", + "integrity": "sha512-j85oO6OnRU9zPf04+PZv1LYIYOprWm6IA6zkXkrJXyRveDEuQggG6tvoy8ir8ZwjLxLuGfNkCZEQG7zan+Hbtg==", + "dev": true, + "requires": { + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + } + }, + "postcss-minify-gradients": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-4.0.2.tgz", + "integrity": "sha512-qKPfwlONdcf/AndP1U8SJ/uzIJtowHlMaSioKzebAXSG4iJthlWC9iSWznQcX4f66gIWX44RSA841HTHj3wK+Q==", + "dev": true, + "requires": { + "cssnano-util-get-arguments": "^4.0.0", + "is-color-stop": "^1.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + } + }, + "postcss-minify-params": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-4.0.2.tgz", + "integrity": "sha512-G7eWyzEx0xL4/wiBBJxJOz48zAKV2WG3iZOqVhPet/9geefm/Px5uo1fzlHu+DOjT+m0Mmiz3jkQzVHe6wxAWg==", + "dev": true, + "requires": { + "alphanum-sort": "^1.0.0", + "browserslist": "^4.0.0", + "cssnano-util-get-arguments": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0", + "uniqs": "^2.0.0" + } + }, + "postcss-minify-selectors": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-4.0.2.tgz", + "integrity": "sha512-D5S1iViljXBj9kflQo4YutWnJmwm8VvIsU1GeXJGiG9j8CIg9zs4voPMdQDUmIxetUOh60VilsNzCiAFTOqu3g==", + "dev": true, + "requires": { + "alphanum-sort": "^1.0.0", + "has": "^1.0.0", + "postcss": "^7.0.0", + "postcss-selector-parser": "^3.0.0" + }, + "dependencies": { + "postcss-selector-parser": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-3.1.1.tgz", + "integrity": "sha1-T4dfSvsMllc9XPTXQBGu4lCn6GU=", + "dev": true, + "requires": { + "dot-prop": "^4.1.1", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + } + } + } + }, + "postcss-modules-extract-imports": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-1.1.0.tgz", + "integrity": "sha1-thTJcgvmgW6u41+zpfqh26agXds=", + "dev": true, + "requires": { + "postcss": "^6.0.1" + }, + "dependencies": { + "postcss": { + "version": "6.0.23", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", + "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", + "dev": true, + "requires": { + "chalk": "^2.4.1", + "source-map": "^0.6.1", + "supports-color": "^5.4.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "postcss-modules-local-by-default": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-1.2.0.tgz", + "integrity": "sha1-99gMOYxaOT+nlkRmvRlQCn1hwGk=", + "dev": true, + "requires": { + "css-selector-tokenizer": "^0.7.0", + "postcss": "^6.0.1" + }, + "dependencies": { + "postcss": { + "version": "6.0.23", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", + "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", + "dev": true, + "requires": { + "chalk": "^2.4.1", + "source-map": "^0.6.1", + "supports-color": "^5.4.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "postcss-modules-scope": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-1.1.0.tgz", + "integrity": "sha1-1upkmUx5+XtipytCb75gVqGUu5A=", + "dev": true, + "requires": { + "css-selector-tokenizer": "^0.7.0", + "postcss": "^6.0.1" + }, + "dependencies": { + "postcss": { + "version": "6.0.23", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", + "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", + "dev": true, + "requires": { + "chalk": "^2.4.1", + "source-map": "^0.6.1", + "supports-color": "^5.4.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "postcss-modules-values": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-1.3.0.tgz", + "integrity": "sha1-7P+p1+GSUYOJ9CrQ6D9yrsRW6iA=", + "dev": true, + "requires": { + "icss-replace-symbols": "^1.1.0", + "postcss": "^6.0.1" + }, + "dependencies": { + "postcss": { + "version": "6.0.23", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", + "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", + "dev": true, + "requires": { + "chalk": "^2.4.1", + "source-map": "^0.6.1", + "supports-color": "^5.4.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "postcss-normalize-charset": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-4.0.1.tgz", + "integrity": "sha512-gMXCrrlWh6G27U0hF3vNvR3w8I1s2wOBILvA87iNXaPvSNo5uZAMYsZG7XjCUf1eVxuPfyL4TJ7++SGZLc9A3g==", + "dev": true, + "requires": { + "postcss": "^7.0.0" + } + }, + "postcss-normalize-display-values": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-4.0.2.tgz", + "integrity": "sha512-3F2jcsaMW7+VtRMAqf/3m4cPFhPD3EFRgNs18u+k3lTJJlVe7d0YPO+bnwqo2xg8YiRpDXJI2u8A0wqJxMsQuQ==", + "dev": true, + "requires": { + "cssnano-util-get-match": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + } + }, + "postcss-normalize-positions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-4.0.2.tgz", + "integrity": "sha512-Dlf3/9AxpxE+NF1fJxYDeggi5WwV35MXGFnnoccP/9qDtFrTArZ0D0R+iKcg5WsUd8nUYMIl8yXDCtcrT8JrdA==", + "dev": true, + "requires": { + "cssnano-util-get-arguments": "^4.0.0", + "has": "^1.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + } + }, + "postcss-normalize-repeat-style": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-4.0.2.tgz", + "integrity": "sha512-qvigdYYMpSuoFs3Is/f5nHdRLJN/ITA7huIoCyqqENJe9PvPmLhNLMu7QTjPdtnVf6OcYYO5SHonx4+fbJE1+Q==", + "dev": true, + "requires": { + "cssnano-util-get-arguments": "^4.0.0", + "cssnano-util-get-match": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + } + }, + "postcss-normalize-string": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-4.0.2.tgz", + "integrity": "sha512-RrERod97Dnwqq49WNz8qo66ps0swYZDSb6rM57kN2J+aoyEAJfZ6bMx0sx/F9TIEX0xthPGCmeyiam/jXif0eA==", + "dev": true, + "requires": { + "has": "^1.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + } + }, + "postcss-normalize-timing-functions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-4.0.2.tgz", + "integrity": "sha512-acwJY95edP762e++00Ehq9L4sZCEcOPyaHwoaFOhIwWCDfik6YvqsYNxckee65JHLKzuNSSmAdxwD2Cud1Z54A==", + "dev": true, + "requires": { + "cssnano-util-get-match": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + } + }, + "postcss-normalize-unicode": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-4.0.1.tgz", + "integrity": "sha512-od18Uq2wCYn+vZ/qCOeutvHjB5jm57ToxRaMeNuf0nWVHaP9Hua56QyMF6fs/4FSUnVIw0CBPsU0K4LnBPwYwg==", + "dev": true, + "requires": { + "browserslist": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + } + }, + "postcss-normalize-url": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-4.0.1.tgz", + "integrity": "sha512-p5oVaF4+IHwu7VpMan/SSpmpYxcJMtkGppYf0VbdH5B6hN8YNmVyJLuY9FmLQTzY3fag5ESUUHDqM+heid0UVA==", + "dev": true, + "requires": { + "is-absolute-url": "^2.0.0", + "normalize-url": "^3.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + } + }, + "postcss-normalize-whitespace": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-4.0.2.tgz", + "integrity": "sha512-tO8QIgrsI3p95r8fyqKV+ufKlSHh9hMJqACqbv2XknufqEDhDvbguXGBBqxw9nsQoXWf0qOqppziKJKHMD4GtA==", + "dev": true, + "requires": { + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + } + }, + "postcss-ordered-values": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-4.1.2.tgz", + "integrity": "sha512-2fCObh5UanxvSxeXrtLtlwVThBvHn6MQcu4ksNT2tsaV2Fg76R2CV98W7wNSlX+5/pFwEyaDwKLLoEV7uRybAw==", + "dev": true, + "requires": { + "cssnano-util-get-arguments": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + } + }, + "postcss-reduce-initial": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-4.0.3.tgz", + "integrity": "sha512-gKWmR5aUulSjbzOfD9AlJiHCGH6AEVLaM0AV+aSioxUDd16qXP1PCh8d1/BGVvpdWn8k/HiK7n6TjeoXN1F7DA==", + "dev": true, + "requires": { + "browserslist": "^4.0.0", + "caniuse-api": "^3.0.0", + "has": "^1.0.0", + "postcss": "^7.0.0" + } + }, + "postcss-reduce-transforms": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-4.0.2.tgz", + "integrity": "sha512-EEVig1Q2QJ4ELpJXMZR8Vt5DQx8/mo+dGWSR7vWXqcob2gQLyQGsionYcGKATXvQzMPn6DSN1vTN7yFximdIAg==", + "dev": true, + "requires": { + "cssnano-util-get-match": "^4.0.0", + "has": "^1.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + } + }, + "postcss-selector-parser": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-5.0.0.tgz", + "integrity": "sha512-w+zLE5Jhg6Liz8+rQOWEAwtwkyqpfnmsinXjXg6cY7YIONZZtgvE0v2O0uhQBs0peNomOJwWRKt6JBfTdTd3OQ==", + "dev": true, + "requires": { + "cssesc": "^2.0.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + }, + "dependencies": { + "cssesc": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-2.0.0.tgz", + "integrity": "sha512-MsCAG1z9lPdoO/IUMLSBWBSVxVtJ1395VGIQ+Fc2gNdkQ1hNDnQdw3YhA71WJCBW1vdwA0cAnk/DnW6bqoEUYg==", + "dev": true + } + } + }, + "postcss-svgo": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-4.0.2.tgz", + "integrity": "sha512-C6wyjo3VwFm0QgBy+Fu7gCYOkCmgmClghO+pjcxvrcBKtiKt0uCF+hvbMO1fyv5BMImRK90SMb+dwUnfbGd+jw==", + "dev": true, + "requires": { + "is-svg": "^3.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0", + "svgo": "^1.0.0" + } + }, + "postcss-unique-selectors": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-4.0.1.tgz", + "integrity": "sha512-+JanVaryLo9QwZjKrmJgkI4Fn8SBgRO6WXQBJi7KiAVPlmxikB5Jzc4EvXMT2H0/m0RjrVVm9rGNhZddm/8Spg==", + "dev": true, + "requires": { + "alphanum-sort": "^1.0.0", + "postcss": "^7.0.0", + "uniqs": "^2.0.0" + } + }, + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + }, + "posthtml": { + "version": "0.11.6", + "resolved": "https://registry.npmjs.org/posthtml/-/posthtml-0.11.6.tgz", + "integrity": "sha512-C2hrAPzmRdpuL3iH0TDdQ6XCc9M7Dcc3zEW5BLerY65G4tWWszwv6nG/ksi6ul5i2mx22ubdljgktXCtNkydkw==", + "dev": true, + "requires": { + "posthtml-parser": "^0.4.1", + "posthtml-render": "^1.1.5" + } + }, + "posthtml-parser": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/posthtml-parser/-/posthtml-parser-0.4.2.tgz", + "integrity": "sha512-BUIorsYJTvS9UhXxPTzupIztOMVNPa/HtAm9KHni9z6qEfiJ1bpOBL5DfUOL9XAc3XkLIEzBzpph+Zbm4AdRAg==", + "dev": true, + "requires": { + "htmlparser2": "^3.9.2" + } + }, + "posthtml-render": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/posthtml-render/-/posthtml-render-1.1.5.tgz", + "integrity": "sha512-yvt54j0zCBHQVEFAuR+yHld8CZrCa/E1Z/OcFNCV1IEWTLVxT8O7nYnM4IIw1CD4r8kaRd3lc42+0lgCKgm87w==", + "dev": true + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "dev": true + }, + "private": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", + "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==", + "dev": true + }, + "process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", + "dev": true + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, + "psl": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.7.0.tgz", + "integrity": "sha512-5NsSEDv8zY70ScRnOTn7bK7eanl2MvFrOrS/R6x+dBt5g1ghnj9Zv90kO8GwT8gxcu2ANyFprnFYB85IogIJOQ==", + "dev": true + }, + "public-encrypt": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", + "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "parse-asn1": "^5.0.0", + "randombytes": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true + }, + "purgecss": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/purgecss/-/purgecss-1.4.2.tgz", + "integrity": "sha512-hkOreFTgiyMHMmC2BxzdIw5DuC6kxAbP/gGOGd3MEsF3+5m69rIvUEPaxrnoUtfODTFKe9hcXjGwC6jcjoyhOw==", + "dev": true, + "requires": { + "glob": "^7.1.3", + "postcss": "^7.0.14", + "postcss-selector-parser": "^6.0.0", + "yargs": "^14.0.0" + }, + "dependencies": { + "cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true + }, + "postcss-selector-parser": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.2.tgz", + "integrity": "sha512-36P2QR59jDTOAiIkqEprfJDsoNrvwFei3eCqKd1Y0tUsBimsq39BLp7RD+JWny3WgB1zGhJX8XVePwm9k4wdBg==", + "dev": true, + "requires": { + "cssesc": "^3.0.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + } + } + } + }, + "q": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", + "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", + "dev": true + }, + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", + "dev": true + }, + "querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", + "dev": true + }, + "querystring-es3": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", + "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=", + "dev": true + }, + "quote-stream": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/quote-stream/-/quote-stream-1.0.2.tgz", + "integrity": "sha1-hJY/jJwmuULhU/7rU6rnRlK34LI=", + "dev": true, + "requires": { + "buffer-equal": "0.0.1", + "minimist": "^1.1.3", + "through2": "^2.0.0" + } + }, + "randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "requires": { + "safe-buffer": "^5.1.0" + } + }, + "randomfill": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", + "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", + "dev": true, + "requires": { + "randombytes": "^2.0.5", + "safe-buffer": "^5.1.0" + } + }, + "range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "dev": true + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "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.1" + }, + "dependencies": { + "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==", + "dev": true + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "readdirp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" + } + }, + "regenerate": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz", + "integrity": "sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg==", + "dev": true + }, + "regenerate-unicode-properties": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-8.1.0.tgz", + "integrity": "sha512-LGZzkgtLY79GeXLm8Dp0BVLdQlWICzBnJz/ipWUgo59qBaZ+BHtq51P2q1uVZlppMuUAT37SDk39qUbjTWB7bA==", + "dev": true, + "requires": { + "regenerate": "^1.4.0" + } + }, + "regenerator-runtime": { + "version": "0.13.3", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.3.tgz", + "integrity": "sha512-naKIZz2GQ8JWh///G7L3X6LaQUAMp2lvb1rvwwsURe/VXwD6VMfr+/1NuNw3ag8v2kY1aQ/go5SNn79O9JU7yw==", + "dev": true + }, + "regenerator-transform": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.1.tgz", + "integrity": "sha512-flVuee02C3FKRISbxhXl9mGzdbWUVHubl1SMaknjxkFB1/iqpJhArQUvRxOOPEc/9tAiX0BaQ28FJH10E4isSQ==", + "dev": true, + "requires": { + "private": "^0.1.6" + } + }, + "regex-not": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", + "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "dev": true, + "requires": { + "extend-shallow": "^3.0.2", + "safe-regex": "^1.1.0" + } + }, + "regexpu-core": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.6.0.tgz", + "integrity": "sha512-YlVaefl8P5BnFYOITTNzDvan1ulLOiXJzCNZxduTIosN17b87h3bvG9yHMoHaRuo88H4mQ06Aodj5VtYGGGiTg==", + "dev": true, + "requires": { + "regenerate": "^1.4.0", + "regenerate-unicode-properties": "^8.1.0", + "regjsgen": "^0.5.0", + "regjsparser": "^0.6.0", + "unicode-match-property-ecmascript": "^1.0.4", + "unicode-match-property-value-ecmascript": "^1.1.0" + } + }, + "regjsgen": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.1.tgz", + "integrity": "sha512-5qxzGZjDs9w4tzT3TPhCJqWdCc3RLYwy9J2NB0nm5Lz+S273lvWcpjaTGHsT1dc6Hhfq41uSEOw8wBmxrKOuyg==", + "dev": true + }, + "regjsparser": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.2.tgz", + "integrity": "sha512-E9ghzUtoLwDekPT0DYCp+c4h+bvuUpe6rRHCTYn6eGoqj1LgKXxT6I0Il4WbjhQkOghzi/V+y03bPKvbllL93Q==", + "dev": true, + "requires": { + "jsesc": "~0.5.0" + }, + "dependencies": { + "jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", + "dev": true + } + } + }, + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", + "dev": true + }, + "repeat-element": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", + "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", + "dev": true + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "dev": true + }, + "request": { + "version": "2.88.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", + "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", + "dev": true, + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.0", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.4.3", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + }, + "dependencies": { + "tough-cookie": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", + "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", + "dev": true, + "requires": { + "psl": "^1.1.24", + "punycode": "^1.4.1" + } + } + } + }, + "request-promise-core": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.3.tgz", + "integrity": "sha512-QIs2+ArIGQVp5ZYbWD5ZLCY29D5CfWizP8eWnm8FoGD1TX61veauETVQbrV60662V0oFBkrDOuaBI8XgtuyYAQ==", + "dev": true, + "requires": { + "lodash": "^4.17.15" + } + }, + "request-promise-native": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.8.tgz", + "integrity": "sha512-dapwLGqkHtwL5AEbfenuzjTYg35Jd6KPytsC2/TLkVMz8rm+tNt72MGUWT1RP/aYawMpN6HqbNGBQaRcBtjQMQ==", + "dev": true, + "requires": { + "request-promise-core": "1.1.3", + "stealthy-require": "^1.1.1", + "tough-cookie": "^2.3.3" + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true + }, + "require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "dev": true + }, + "resolve": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.11.1.tgz", + "integrity": "sha512-vIpgF6wfuJOZI7KKKSP+HmiKggadPQAdsp5HiC1mvqnfp0gF1vdwgBWZIdrVft9pgqoMFQN+R7BSWZiBxx+BBw==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } + }, + "resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", + "dev": true + }, + "resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", + "dev": true + }, + "restore-cursor": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", + "dev": true, + "requires": { + "onetime": "^2.0.0", + "signal-exit": "^3.0.2" + } + }, + "ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", + "dev": true + }, + "rgb-regex": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/rgb-regex/-/rgb-regex-1.0.1.tgz", + "integrity": "sha1-wODWiC3w4jviVKR16O3UGRX+rrE=", + "dev": true + }, + "rgba-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/rgba-regex/-/rgba-regex-1.0.0.tgz", + "integrity": "sha1-QzdOLiyglosO8VI0YLfXMP8i7rM=", + "dev": true + }, + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "ripemd160": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", + "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "dev": true, + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" + } + }, + "safe-buffer": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz", + "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==", + "dev": true + }, + "safe-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", + "dev": true, + "requires": { + "ret": "~0.1.10" + } + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", + "dev": true + }, + "saxes": { + "version": "3.1.11", + "resolved": "https://registry.npmjs.org/saxes/-/saxes-3.1.11.tgz", + "integrity": "sha512-Ydydq3zC+WYDJK1+gRxRapLIED9PWeSuuS41wqyoRmzvhhh9nc+QQrVMKJYzJFULazeGhzSV0QleN2wD3boh2g==", + "dev": true, + "requires": { + "xmlchars": "^2.1.1" + } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + }, + "send": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", + "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", + "dev": true, + "requires": { + "debug": "2.6.9", + "depd": "~1.1.2", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "~1.7.2", + "mime": "1.6.0", + "ms": "2.1.1", + "on-finished": "~2.3.0", + "range-parser": "~1.2.1", + "statuses": "~1.5.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + }, + "dependencies": { + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + } + } + }, + "serialize-to-js": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/serialize-to-js/-/serialize-to-js-3.0.2.tgz", + "integrity": "sha512-o5FqeMyxGx1wkp8p14q9QqGXh1JjXtIDYTr15N/B4ThM5ULqlpXdtOO84m950jFGvBkeRD1utW+WyNKvao2ybQ==", + "dev": true + }, + "serve-static": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", + "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", + "dev": true, + "requires": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.17.1" + } + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "dev": true + }, + "set-value": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", + "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.3", + "split-string": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", + "dev": true + }, + "setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==", + "dev": true + }, + "sha.js": { + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "shallow-copy": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/shallow-copy/-/shallow-copy-0.0.1.tgz", + "integrity": "sha1-QV9CcC1z2BAzApLMXuhurhoRoXA=", + "dev": true + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "dev": true + }, + "simple-swizzle": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", + "integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=", + "dev": true, + "requires": { + "is-arrayish": "^0.3.1" + }, + "dependencies": { + "is-arrayish": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==", + "dev": true + } + } + }, + "snapdragon": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", + "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "dev": true, + "requires": { + "base": "^0.11.1", + "debug": "^2.2.0", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "map-cache": "^0.2.2", + "source-map": "^0.5.6", + "source-map-resolve": "^0.5.0", + "use": "^3.1.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "snapdragon-node": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "dev": true, + "requires": { + "define-property": "^1.0.0", + "isobject": "^3.0.0", + "snapdragon-util": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "snapdragon-util": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "dev": true, + "requires": { + "kind-of": "^3.2.0" + }, + "dependencies": { + "kind-of": { + "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.5" + } + } + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "source-map-resolve": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", + "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", + "dev": true, + "requires": { + "atob": "^2.1.2", + "decode-uri-component": "^0.2.0", + "resolve-url": "^0.2.1", + "source-map-url": "^0.4.0", + "urix": "^0.1.0" + } + }, + "source-map-support": { + "version": "0.5.16", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.16.tgz", + "integrity": "sha512-efyLRJDr68D9hBBNIPWFjhpFzURh+KJykQwvMyW5UiZzYwoF6l4YMMDIJJEyFWxWCqfyxLzz6tSfUFR+kXXsVQ==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "source-map-url": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", + "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", + "dev": true + }, + "split-string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "dev": true, + "requires": { + "extend-shallow": "^3.0.0" + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "sshpk": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", + "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", + "dev": true, + "requires": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + } + }, + "stable": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", + "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==", + "dev": true + }, + "static-eval": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/static-eval/-/static-eval-2.0.3.tgz", + "integrity": "sha512-zsxDGucfAh8T339sSKgpFbvg15Fms2IVaJGC+jqp0bVsxhcpM+iMeAI8weNo8dmf4OblgifTBUoyk1vGVtYw2w==", + "dev": true, + "requires": { + "escodegen": "^1.11.1" + }, + "dependencies": { + "escodegen": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.13.0.tgz", + "integrity": "sha512-eYk2dCkxR07DsHA/X2hRBj0CFAZeri/LyDMc0C8JT1Hqi6JnVpMhJ7XFITbb0+yZS3lVkaPL2oCkZ3AVmeVbMw==", + "dev": true, + "requires": { + "esprima": "^4.0.1", + "estraverse": "^4.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1", + "source-map": "~0.6.1" + } + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "optional": true + } + } + }, + "static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "dev": true, + "requires": { + "define-property": "^0.2.5", + "object-copy": "^0.1.0" + }, + "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=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, + "static-module": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/static-module/-/static-module-2.2.5.tgz", + "integrity": "sha512-D8vv82E/Kpmz3TXHKG8PPsCPg+RAX6cbCOyvjM6x04qZtQ47EtJFVwRsdov3n5d6/6ynrOY9XB4JkaZwB2xoRQ==", + "dev": true, + "requires": { + "concat-stream": "~1.6.0", + "convert-source-map": "^1.5.1", + "duplexer2": "~0.1.4", + "escodegen": "~1.9.0", + "falafel": "^2.1.0", + "has": "^1.0.1", + "magic-string": "^0.22.4", + "merge-source-map": "1.0.4", + "object-inspect": "~1.4.0", + "quote-stream": "~1.0.2", + "readable-stream": "~2.3.3", + "shallow-copy": "~0.0.1", + "static-eval": "^2.0.0", + "through2": "~2.0.3" + }, + "dependencies": { + "convert-source-map": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", + "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.1" + } + }, + "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==", + "dev": true + } + } + }, + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", + "dev": true + }, + "stealthy-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz", + "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=", + "dev": true + }, + "stream-browserify": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz", + "integrity": "sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg==", + "dev": true, + "requires": { + "inherits": "~2.0.1", + "readable-stream": "^2.0.2" + } + }, + "stream-http": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz", + "integrity": "sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==", + "dev": true, + "requires": { + "builtin-status-codes": "^3.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.3.6", + "to-arraybuffer": "^1.0.0", + "xtend": "^4.0.0" + } + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "string.prototype.trimleft": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.1.tgz", + "integrity": "sha512-iu2AGd3PuP5Rp7x2kEZCrB2Nf41ehzh+goo8TV7z8/XDBbsvc6HQIlUl9RjkZ4oyrW1XM5UwlGl1oVEaDjg6Ag==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "function-bind": "^1.1.1" + } + }, + "string.prototype.trimright": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.1.tgz", + "integrity": "sha512-qFvWL3/+QIgZXVmJBfpHmxLB7xsUXz6HsUmP8+5dRaC3Q7oKUv9Vo6aMCRZC1smrtyECFsIT30PqBJ1gTjAs+g==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "function-bind": "^1.1.1" + } + }, + "string_decoder": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.2.0.tgz", + "integrity": "sha512-6YqyX6ZWEYguAxgZzHGL7SsCeGx3V2TtOTqZz1xSTSWnqsbWwbptafNyvf/ACquZUXV3DANr5BDIwNYe1mN42w==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + }, + "dependencies": { + "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==", + "dev": true + } + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + }, + "stylehacks": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-4.0.3.tgz", + "integrity": "sha512-7GlLk9JwlElY4Y6a/rmbH2MhVlTyVmiJd1PfTCqFaIBEGMYNsrO/v3SeGTdhBThLg4Z+NbOk/qFMwCa+J+3p/g==", + "dev": true, + "requires": { + "browserslist": "^4.0.0", + "postcss": "^7.0.0", + "postcss-selector-parser": "^3.0.0" + }, + "dependencies": { + "postcss-selector-parser": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-3.1.1.tgz", + "integrity": "sha1-T4dfSvsMllc9XPTXQBGu4lCn6GU=", + "dev": true, + "requires": { + "dot-prop": "^4.1.1", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + } + } + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "svgo": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-1.3.2.tgz", + "integrity": "sha512-yhy/sQYxR5BkC98CY7o31VGsg014AKLEPxdfhora76l36hD9Rdy5NZA/Ocn6yayNPgSamYdtX2rFJdcv07AYVw==", + "dev": true, + "requires": { + "chalk": "^2.4.1", + "coa": "^2.0.2", + "css-select": "^2.0.0", + "css-select-base-adapter": "^0.1.1", + "css-tree": "1.0.0-alpha.37", + "csso": "^4.0.2", + "js-yaml": "^3.13.1", + "mkdirp": "~0.5.1", + "object.values": "^1.1.0", + "sax": "~1.2.4", + "stable": "^0.1.8", + "unquote": "~1.1.1", + "util.promisify": "~1.0.0" + } + }, + "symbol-tree": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", + "dev": true + }, + "terser": { + "version": "3.17.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-3.17.0.tgz", + "integrity": "sha512-/FQzzPJmCpjAH9Xvk2paiWrFq+5M6aVOf+2KRbwhByISDX/EujxsK+BAvrhb6H+2rtrLCHK9N01wO014vrIwVQ==", + "dev": true, + "requires": { + "commander": "^2.19.0", + "source-map": "~0.6.1", + "source-map-support": "~0.5.10" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", "dev": true, "requires": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1" + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" } }, - "safe-buffer": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz", - "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==", + "timsort": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/timsort/-/timsort-0.3.0.tgz", + "integrity": "sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=", "dev": true }, - "sha.js": { - "version": "2.4.11", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", - "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "tiny-inflate": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tiny-inflate/-/tiny-inflate-1.0.3.tgz", + "integrity": "sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==", + "dev": true + }, + "to-arraybuffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", + "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=", + "dev": true + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true + }, + "to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", "dev": true, "requires": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "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.5" + } + } } }, - "shasum": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/shasum/-/shasum-1.0.2.tgz", - "integrity": "sha1-5wEjENj0F/TetXEhUOVni4euVl8=", + "to-regex": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", "dev": true, "requires": { - "json-stable-stringify": "~0.0.0", - "sha.js": "~2.4.4" + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "regex-not": "^1.0.2", + "safe-regex": "^1.1.0" } }, - "shell-quote": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.6.1.tgz", - "integrity": "sha1-9HgZSczkAmlxJ0MOo7PFR29IF2c=", + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", "dev": true, "requires": { - "array-filter": "~0.0.0", - "array-map": "~0.0.0", - "array-reduce": "~0.0.0", - "jsonify": "~0.0.0" + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" } }, - "simple-concat": { + "toidentifier": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.0.tgz", - "integrity": "sha1-c0TLuLbib7J9ZrL8hvn21Zl1IcY=", - "dev": true - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", + "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", "dev": true }, - "stream-browserify": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz", - "integrity": "sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg==", + "tough-cookie": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", "dev": true, "requires": { - "inherits": "~2.0.1", - "readable-stream": "^2.0.2" + "psl": "^1.1.28", + "punycode": "^2.1.1" + }, + "dependencies": { + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true + } } }, - "stream-combiner2": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/stream-combiner2/-/stream-combiner2-1.1.1.tgz", - "integrity": "sha1-+02KFCDqNidk4hrUeAOXvry0HL4=", + "tr46": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", + "integrity": "sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk=", "dev": true, "requires": { - "duplexer2": "~0.1.0", - "readable-stream": "^2.0.2" + "punycode": "^2.1.0" + }, + "dependencies": { + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true + } } }, - "stream-http": { - "version": "2.8.3", - "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz", - "integrity": "sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==", + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", "dev": true, "requires": { - "builtin-status-codes": "^3.0.0", - "inherits": "^2.0.1", - "readable-stream": "^2.3.6", - "to-arraybuffer": "^1.0.0", - "xtend": "^4.0.0" + "safe-buffer": "^5.0.1" } }, - "stream-splicer": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/stream-splicer/-/stream-splicer-2.0.1.tgz", - "integrity": "sha512-Xizh4/NPuYSyAXyT7g8IvdJ9HJpxIGL9PjyhtywCZvvP0OPIdqyrr4dMikeuvY8xahpdKEBlBTySe583totajg==", + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "dev": true + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", "dev": true, "requires": { - "inherits": "^2.0.1", - "readable-stream": "^2.0.2" + "prelude-ls": "~1.1.2" } }, - "string_decoder": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.2.0.tgz", - "integrity": "sha512-6YqyX6ZWEYguAxgZzHGL7SsCeGx3V2TtOTqZz1xSTSWnqsbWwbptafNyvf/ACquZUXV3DANr5BDIwNYe1mN42w==", + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", + "dev": true + }, + "uncss": { + "version": "0.17.2", + "resolved": "https://registry.npmjs.org/uncss/-/uncss-0.17.2.tgz", + "integrity": "sha512-hu2HquwDItuGDem4YsJROdAD8SknmWtM24zwhQax6J1se8tPjV1cnwPKhtjodzBaUhaL8Zb3hlGdZ2WAUpbAOg==", "dev": true, "requires": { - "safe-buffer": "~5.1.0" + "commander": "^2.20.0", + "glob": "^7.1.4", + "is-absolute-url": "^3.0.1", + "is-html": "^1.1.0", + "jsdom": "^14.1.0", + "lodash": "^4.17.15", + "postcss": "^7.0.17", + "postcss-selector-parser": "6.0.2", + "request": "^2.88.0" }, "dependencies": { - "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==", + "cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true + }, + "is-absolute-url": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-3.0.3.tgz", + "integrity": "sha512-opmNIX7uFnS96NtPmhWQgQx6/NYFgsUXYMllcfzwWKUMwfo8kku1TvE6hkNcH+Q1ts5cMVrsY7j0bxXQDciu9Q==", "dev": true + }, + "postcss-selector-parser": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.2.tgz", + "integrity": "sha512-36P2QR59jDTOAiIkqEprfJDsoNrvwFei3eCqKd1Y0tUsBimsq39BLp7RD+JWny3WgB1zGhJX8XVePwm9k4wdBg==", + "dev": true, + "requires": { + "cssesc": "^3.0.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + } } } }, - "subarg": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/subarg/-/subarg-1.0.0.tgz", - "integrity": "sha1-9izxdYHplrSPyWVpn1TAauJouNI=", - "dev": true, - "requires": { - "minimist": "^1.1.0" - } + "unicode-canonical-property-names-ecmascript": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz", + "integrity": "sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ==", + "dev": true }, - "syntax-error": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/syntax-error/-/syntax-error-1.4.0.tgz", - "integrity": "sha512-YPPlu67mdnHGTup2A8ff7BC2Pjq0e0Yp/IyTFN03zWO0RcK07uLcbi7C2KpGR2FvWbaB0+bfE27a+sBKebSo7w==", + "unicode-match-property-ecmascript": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz", + "integrity": "sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg==", "dev": true, "requires": { - "acorn-node": "^1.2.0" + "unicode-canonical-property-names-ecmascript": "^1.0.4", + "unicode-property-aliases-ecmascript": "^1.0.4" } }, - "through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "unicode-match-property-value-ecmascript": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.1.0.tgz", + "integrity": "sha512-hDTHvaBk3RmFzvSl0UVrUmC3PuW9wKVnpoUDYH0JDkSIovzw+J5viQmeYHxVSBptubnr7PbH2e0fnpDRQnQl5g==", "dev": true }, - "through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "unicode-property-aliases-ecmascript": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.0.5.tgz", + "integrity": "sha512-L5RAqCfXqAwR3RriF8pM0lU0w4Ryf/GgzONwi6KnL1taJQa7x1TCxdJnILX59WIGOwR57IVxn7Nej0fz1Ny6fw==", + "dev": true + }, + "unicode-trie": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/unicode-trie/-/unicode-trie-0.3.1.tgz", + "integrity": "sha1-1nHd3YkQGgi6w3tqUWEBBgIFIIU=", "dev": true, "requires": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" + "pako": "^0.2.5", + "tiny-inflate": "^1.0.0" + }, + "dependencies": { + "pako": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", + "integrity": "sha1-8/dSL073gjSNqBYbrZ7P1Rv4OnU=", + "dev": true + } } }, - "timers-browserify": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-1.4.2.tgz", - "integrity": "sha1-ycWLV1voQHN1y14kYtrO50NZ9B0=", + "union-value": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", + "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", "dev": true, "requires": { - "process": "~0.11.0" + "arr-union": "^3.1.0", + "get-value": "^2.0.6", + "is-extendable": "^0.1.1", + "set-value": "^2.0.1" } }, - "to-arraybuffer": { + "uniq": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", - "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=", + "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz", + "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=", "dev": true }, - "tty-browserify": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.1.tgz", - "integrity": "sha512-C3TaO7K81YvjCgQH9Q1S3R3P3BtN3RIM8n+OvX4il1K1zgE8ZhI0op7kClgkxtutIE8hQrcrHBXvIheqKUUCxw==", + "uniqs": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/uniqs/-/uniqs-2.0.0.tgz", + "integrity": "sha1-/+3ks2slKQaW5uFl1KWe25mOawI=", "dev": true }, - "typedarray": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", + "unquote": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unquote/-/unquote-1.1.1.tgz", + "integrity": "sha1-j97XMk7G6IoP+LkF58CYzcCG1UQ=", "dev": true }, - "umd": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/umd/-/umd-3.0.3.tgz", - "integrity": "sha512-4IcGSufhFshvLNcMCV80UnQVlZ5pMOC8mvNPForqwA4+lzYQuetTESLDQkeLmihq8bRcnpbQa48Wb8Lh16/xow==", + "unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "dev": true, + "requires": { + "has-value": "^0.3.1", + "isobject": "^3.0.0" + }, + "dependencies": { + "has-value": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", + "dev": true, + "requires": { + "get-value": "^2.0.3", + "has-values": "^0.1.4", + "isobject": "^2.0.0" + }, + "dependencies": { + "isobject": { + "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" + } + } + } + }, + "has-values": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", + "dev": true + } + } + }, + "upath": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", + "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", "dev": true }, - "undeclared-identifiers": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/undeclared-identifiers/-/undeclared-identifiers-1.1.3.tgz", - "integrity": "sha512-pJOW4nxjlmfwKApE4zvxLScM/njmwj/DiUBv7EabwE4O8kRUy+HIwxQtZLBPll/jx1LJyBcqNfB3/cpv9EZwOw==", + "uri-js": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", + "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", "dev": true, "requires": { - "acorn-node": "^1.3.0", - "dash-ast": "^1.0.0", - "get-assigned-identifiers": "^1.2.0", - "simple-concat": "^1.0.0", - "xtend": "^4.0.1" + "punycode": "^2.1.0" + }, + "dependencies": { + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true + } } }, + "urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", + "dev": true + }, "url": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", @@ -1292,52 +24576,248 @@ } } }, - "url-join": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz", - "integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==", + "use": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", + "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", "dev": true }, - "util": { - "version": "0.10.4", - "resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz", - "integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==", - "dev": true, - "requires": { - "inherits": "2.0.3" - }, - "dependencies": { - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true - } - } - }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", "dev": true }, + "util.promisify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.1.tgz", + "integrity": "sha512-g9JpC/3He3bm38zsLupWryXHoEcS22YHthuPQSJdMy6KNrzIRzWqcsHzD/WUnqe45whVou4VIsPew37DoXWNrA==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.2", + "has-symbols": "^1.0.1", + "object.getownpropertydescriptors": "^2.1.0" + } + }, + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "dev": true + }, + "v8-compile-cache": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.0.tgz", + "integrity": "sha512-usZBT3PW+LOjM25wbqIlZwPeJV+3OSz3M1k1Ws8snlW39dZyYL9lOGC5FgPVHfk0jKmjiDV8Z0mIbVQPiwFs7g==", + "dev": true + }, + "vendors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/vendors/-/vendors-1.0.3.tgz", + "integrity": "sha512-fOi47nsJP5Wqefa43kyWSg80qF+Q3XA6MUkgi7Hp1HQaKDQW4cQrK2D0P7mmbFtsV1N89am55Yru/nyEwRubcw==", + "dev": true + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "vlq": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/vlq/-/vlq-0.2.3.tgz", + "integrity": "sha512-DRibZL6DsNhIgYQ+wNdWDL2SL3bKPlVrRiBqV5yuMm++op8W4kGFtaQfCs4KEJn0wBZcHVHJ3eoywX8983k1ow==", + "dev": true + }, "vm-browserify": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.0.tgz", "integrity": "sha512-iq+S7vZJE60yejDYM0ek6zg308+UZsdtPExWP9VZoCFCz1zkJoXFnAX7aZfd/ZwrkidzdUZL0C/ryW+JwAiIGw==", "dev": true }, + "w3c-hr-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.1.tgz", + "integrity": "sha1-gqwr/2PZUOqeMYmlimViX+3xkEU=", + "dev": true, + "requires": { + "browser-process-hrtime": "^0.1.2" + } + }, + "w3c-xmlserializer": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-1.1.2.tgz", + "integrity": "sha512-p10l/ayESzrBMYWRID6xbuCKh2Fp77+sA0doRuGn4tTIMrrZVeqfpKjXHY+oDh3K4nLdPgNwMTVP6Vp4pvqbNg==", + "dev": true, + "requires": { + "domexception": "^1.0.1", + "webidl-conversions": "^4.0.2", + "xml-name-validator": "^3.0.0" + } + }, + "wcwidth": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=", + "dev": true, + "requires": { + "defaults": "^1.0.3" + } + }, + "webidl-conversions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", + "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==", + "dev": true + }, + "whatwg-encoding": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz", + "integrity": "sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==", + "dev": true, + "requires": { + "iconv-lite": "0.4.24" + } + }, + "whatwg-mimetype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz", + "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==", + "dev": true + }, + "whatwg-url": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz", + "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==", + "dev": true, + "requires": { + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" + } + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", + "dev": true + }, + "word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true + }, + "wrap-ansi": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", "dev": true }, + "ws": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/ws/-/ws-5.2.2.tgz", + "integrity": "sha512-jaHFD6PFv6UgoIVda6qZllptQsMlDEJkTQcybzzXDYM1XO9Y8em691FGMPmM46WGyLU4z9KMgQN+qrux/nhlHA==", + "dev": true, + "requires": { + "async-limiter": "~1.0.0" + } + }, + "xml-name-validator": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", + "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==", + "dev": true + }, + "xmlchars": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", + "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", + "dev": true + }, "xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", "dev": true + }, + "y18n": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", + "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", + "dev": true + }, + "yargs": { + "version": "14.2.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-14.2.2.tgz", + "integrity": "sha512-/4ld+4VV5RnrynMhPZJ/ZpOCGSCeghMykZ3BhdFBDa9Wy/RH6uEGNWDJog+aUlq+9OM1CFTgtYRW5Is1Po9NOA==", + "dev": true, + "requires": { + "cliui": "^5.0.0", + "decamelize": "^1.2.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^15.0.0" + } + }, + "yargs-parser": { + "version": "15.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-15.0.0.tgz", + "integrity": "sha512-xLTUnCMc4JhxrPEPUYD5IBR1mWCK/aT6+RJ/K29JY2y1vD+FhtgKK0AXRWvI262q3QSffAQuTouFIKUuHX89wQ==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } } } } diff --git a/examples/name-api/package.json b/examples/name-api/package.json index 143e733d2..3929830dc 100644 --- a/examples/name-api/package.json +++ b/examples/name-api/package.json @@ -4,12 +4,17 @@ "description": "", "main": "index.js", "scripts": { - "start": "browserify index.js > bundle.js && extatic --host 127.0.0.1 -p 8888" + "start": "parcel index.html" }, "author": "Tara Vancil ", "license": "MIT", "devDependencies": { - "browserify": "^16.2.3", - "extatic": "^4.1.3" - } + "parcel-bundler": "^1.12.4" + }, + "dependencies": { + "ipfs-http-client": "../.." + }, + "browserslist": [ + "last 2 versions and not dead and > 2%" + ] } diff --git a/examples/upload-file-via-browser/README.md b/examples/upload-file-via-browser/README.md index ee0e04d1c..e05452b03 100644 --- a/examples/upload-file-via-browser/README.md +++ b/examples/upload-file-via-browser/README.md @@ -26,9 +26,6 @@ Once the daemon is on, run the following commands within this folder: > npm install > npm start ``` - -Now open your browser at `http://localhost:3000` - After uploading a file (left screen), and opening the uploaded file (right screen), you should see something like: > ![App Screenshot](https://github.com/ipfs/js-ipfs-http-client/raw/master/examples/upload-file-via-browser/screenshot.png) diff --git a/examples/upload-file-via-browser/index.html b/examples/upload-file-via-browser/index.html index c4d9c4902..172aecc6e 100644 --- a/examples/upload-file-via-browser/index.html +++ b/examples/upload-file-via-browser/index.html @@ -5,6 +5,6 @@
- + diff --git a/examples/upload-file-via-browser/package.json b/examples/upload-file-via-browser/package.json index 8827052ca..80b19a536 100644 --- a/examples/upload-file-via-browser/package.json +++ b/examples/upload-file-via-browser/package.json @@ -3,33 +3,22 @@ "version": "1.0.0", "description": "Upload file to IPFS via browser using js-ipfs-http-client with Webpack", "scripts": { - "start": "webpack-dev-server" + "start": "parcel index.html" }, "author": "Harlan T Wood ", "contributors": [ "Victor Bjelkholm " ], "license": "MIT", + "dependencies": { + "ipfs-http-client": "../.." + }, "devDependencies": { - "@babel/core": "^7.4.3", - "@babel/preset-env": "^7.3.1", - "@babel/preset-react": "^7.0.0", - "eslint": "^5.16.0", - "eslint-plugin-react": "^7.11.1", "react": "~16.6.3", "react-dom": "~16.6.3", - "webpack": "~4.30.0", - "webpack-dev-server": "~3.3.1" + "parcel-bundler": "^1.12.4" }, - "eslintConfig" : { - "extends": "standard", - "rules": { - "react/jsx-uses-react": 2, - "react/jsx-uses-vars": 2, - "react/react-in-jsx-scope": 2 - }, - "plugins": [ - "react" - ] - } + "browserslist": [ + "last 2 versions and not dead and > 2%" + ] } diff --git a/examples/upload-file-via-browser/src/App.js b/examples/upload-file-via-browser/src/App.js index 258dc53ed..16e48ef43 100644 --- a/examples/upload-file-via-browser/src/App.js +++ b/examples/upload-file-via-browser/src/App.js @@ -1,6 +1,7 @@ +/* eslint-disable no-console */ 'use strict' const React = require('react') -const ipfsClient = require('../../../src') +const ipfsClient = require('ipfs-http-client') class App extends React.Component { constructor () { @@ -8,7 +9,7 @@ class App extends React.Component { this.state = { added_file_hash: null } - this.ipfs = ipfsClient('localhost', '58041') + this.ipfs = ipfsClient('/ip4/127.0.0.1/tcp/5001') // bind methods this.captureFile = this.captureFile.bind(this) @@ -28,24 +29,27 @@ class App extends React.Component { // Example #1 // Add file to IPFS and return a CID - saveToIpfs (files) { - let ipfsId - this.ipfs.add([...files], { progress: (prog) => console.log(`received: ${prog}`) }) - .then((response) => { - console.log(response) - ipfsId = response[0].hash - console.log(ipfsId) - this.setState({ added_file_hash: ipfsId }) - }).catch((err) => { - console.error(err) - }) + async saveToIpfs (files) { + const source = this.ipfs.add( + [...files], + { + progress: (prog) => console.log(`received: ${prog}`) + } + ) + try { + for await (const file of source) { + console.log(file) + this.setState({ added_file_hash: file.path }) + } + } catch (err) { + console.error(err) + } } // Example #2 // Add file to IPFS and wrap it in a directory to keep the original filename - saveToIpfsWithFilename (files) { + async saveToIpfsWithFilename (files) { const file = [...files][0] - let ipfsId const fileDetails = { path: file.name, content: file @@ -54,16 +58,16 @@ class App extends React.Component { wrapWithDirectory: true, progress: (prog) => console.log(`received: ${prog}`) } - this.ipfs.add(fileDetails, options) - .then((response) => { - console.log(response) - // CID of wrapping directory is returned last - ipfsId = response[response.length - 1].hash - console.log(ipfsId) - this.setState({ added_file_hash: ipfsId }) - }).catch((err) => { - console.error(err) - }) + + const source = this.ipfs.add(fileDetails, options) + try { + for await (const file of source) { + console.log(file) + this.setState({ added_file_hash: file.cid.toString() }) + } + } catch (err) { + console.error(err) + } } handleSubmit (event) { diff --git a/examples/upload-file-via-browser/src/index.js b/examples/upload-file-via-browser/src/index.js index 6d9d7badf..2bd77c1df 100644 --- a/examples/upload-file-via-browser/src/index.js +++ b/examples/upload-file-via-browser/src/index.js @@ -1,3 +1,4 @@ +/* eslint-disable no-unused-vars */ 'use strict' const React = require('react') const ReactDOM = require('react-dom') diff --git a/examples/upload-file-via-browser/webpack.config.js b/examples/upload-file-via-browser/webpack.config.js deleted file mode 100644 index c28ec1168..000000000 --- a/examples/upload-file-via-browser/webpack.config.js +++ /dev/null @@ -1,37 +0,0 @@ -'use strict' - -const path = require('path') - -module.exports = { - mode: 'development', - devtool: 'eval', - entry: [ - './src/index' - ], - output: { - path: path.join(__dirname, 'dist'), - filename: 'bundle.js', - publicPath: '/static/' - }, - module: { - rules: [ - { - test: /\.js$/, - include: path.join(__dirname, 'src'), - use: [ - { - loader: 'babel-loader', - options: { - presets: ['@babel/preset-env', '@babel/preset-react'] - } - } - ] - } - ] - }, - node: { - fs: 'empty', - net: 'empty', - tls: 'empty' - } -} From 2e9dd9e8495c275fb0970659fb65cb94615e1c9f Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Tue, 4 Feb 2020 11:57:37 +0000 Subject: [PATCH 229/233] chore: update contributors --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index ccc412bcb..07ad807db 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ipfs-http-client", - "version": "42.0.0-pre.2", + "version": "42.0.0", "description": "A client library for the IPFS HTTP API", "keywords": [ "ipfs" @@ -83,6 +83,7 @@ "Alan Shaw ", "Alan Shaw ", "Alex Mingoia ", + "Alex Potsides ", "Antonio Tenorio-Fornés ", "Bruno Barbieri ", "Clemo ", @@ -160,7 +161,6 @@ "Victor Bjelkholm ", "Volker Mische ", "Zhiyuan Lin ", - "achingbrain ", "dirkmc ", "dmitriy ryajov ", "elsehow ", From c20a568979c7a3872ecb81e3972c3a545fd3d0c2 Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Tue, 4 Feb 2020 11:57:37 +0000 Subject: [PATCH 230/233] chore: release version v42.0.0 --- CHANGELOG.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 709438c6b..e47157acd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,13 @@ + +# [42.0.0](https://github.com/ipfs/js-ipfs-http-client/compare/v42.0.0-pre.2...v42.0.0) (2020-02-04) + + +### Bug Fixes + +* interface tests ([#1233](https://github.com/ipfs/js-ipfs-http-client/issues/1233)) ([d3eee0d](https://github.com/ipfs/js-ipfs-http-client/commit/d3eee0d)) + + + # [42.0.0-pre.0](https://github.com/ipfs/js-ipfs-http-client/compare/v41.0.1...v42.0.0-pre.0) (2020-01-23) From 69b93cc58a7a8562e6ef6aaf22ce52745041468d Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Tue, 4 Feb 2020 12:11:02 +0000 Subject: [PATCH 231/233] docs: add missing changelog --- CHANGELOG.md | 110 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 110 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e47157acd..a40976f0b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,11 +1,121 @@ # [42.0.0](https://github.com/ipfs/js-ipfs-http-client/compare/v42.0.0-pre.2...v42.0.0) (2020-02-04) +There are significant and breaking API changes in this release. Please see the [migration guide](https://gist.github.com/alanshaw/04b2ddc35a6fff25c040c011ac6acf26). ### Bug Fixes * interface tests ([#1233](https://github.com/ipfs/js-ipfs-http-client/issues/1233)) ([d3eee0d](https://github.com/ipfs/js-ipfs-http-client/commit/d3eee0d)) +### Features + +* `add` results now include `mode` and `mtime` properties if they were set. + +* `files.chmod` has been added. See the [core interface docs](https://github.com/ipfs/interface-js-ipfs-core/blob/master/SPEC/FILES.md#fileschmod) for info. + +* `files.flush` now returns the root CID for the path that was flushed (`/` by default) + +* `files.ls` results now include `mode` and `mtime` properties if they were set. See the [core interface docs](https://github.com/ipfs/interface-js-ipfs-core/blob/master/SPEC/FILES.md#ls) for more info. + +* `files.mkdir` now accepts `mode` and `mtime` options to allow setting mode and mtime metadata. See the [core interface docs](https://github.com/ipfs/interface-js-ipfs-core/blob/master/SPEC/FILES.md#filesmkdir) for more info. + +* `files.stat` result now includes `mode` and `mtime` properties if they were set. See the [core interface docs](https://github.com/ipfs/interface-js-ipfs-core/blob/master/SPEC/FILES.md#filesstat) for more info. + +* `files.touch` has been added. See the [core interface docs](https://github.com/ipfs/interface-js-ipfs-core/blob/master/SPEC/FILES.md#filestouch) for info. + +* `files.write` now accepts `mode` and `mtime` options to allow setting mode and mtime metadata. See the [core interface docs](https://github.com/ipfs/interface-js-ipfs-core/blob/master/SPEC/FILES.md#fileswrite) for more info. + +* `object.get` now accepts a `timeout` option. It will cause the method to throw with a `TimeoutError` if no data is received within the timeout window. It can be passed as a `number` or a `string`. If a `number` is passed it is interpreted as milliseconds, if a string is passed it is interpreted as a [human readable duration](https://www.npmjs.com/package/parse-duration). + +* `pin.add` now accepts a `timeout` option. It will cause the method to throw with a `TimeoutError` if no data is received within the timeout window. It can be passed as a `number` or a `string`. If a `number` is passed it is interpreted as milliseconds, if a string is passed it is interpreted as a [human readable duration](https://www.npmjs.com/package/parse-duration). + +* `refs` now accepts a `timeout` option. It will cause the method to throw with a `TimeoutError` if no data is received within the timeout window. It can be passed as a `number` or a `string`. If a `number` is passed it is interpreted as milliseconds, if a string is passed it is interpreted as a [human readable duration](https://www.npmjs.com/package/parse-duration). + +### BREAKING CHANGES + +* Callbacks are no longer supported on any API methods. Please use a utility such as [`callbackify`](https://www.npmjs.com/package/callbackify) on API methods that return Promises to emulate previous behaviour. See the [migration guide](https://gist.github.com/alanshaw/04b2ddc35a6fff25c040c011ac6acf26#migrating-from-callbacks) for more info. + +* `add` now returns an async iterable. + +* `add` now accepts `mode` and `mtime` options on inputs to allow setting mode and mtime metadata for added files. See the [core interface docs](https://github.com/ipfs/interface-js-ipfs-core/blob/master/SPEC/FILES.md#add) for more info. + +* `add` results now contain a `cid` property (a [CID instance](https://github.com/multiformats/js-cid)) instead of a string `hash` property. + +* `addReadableStream`, `addPullStream` have been removed. Please see the [migration guide](https://gist.github.com/alanshaw/04b2ddc35a6fff25c040c011ac6acf26#migrating-to-async-iterables) for more info. + +* `addFromStream` has been removed. Use `add` instead. + +* `addFromFs` has been removed. Please use the exported `globSource` utility and pass the result to `add`. See the [glob source documentation](https://github.com/ipfs/js-ipfs-http-client#glob-source) for more details and an example. + +* `addFromURL` has been removed. Please use the exported `urlSource` utility and pass the result to `add`. See the [URL source documentation](https://github.com/ipfs/js-ipfs-http-client#url-source) for more details and an example. + +* `bitswap.stat` result has changed - `wantlist` and values are now an array of [CID](https://github.com/multiformats/js-cid) instances and `peers` is now a `string[]` of peer IDs. + +* `bitswap.wantlist` now returns an array of [CID](https://github.com/multiformats/js-cid) instances. + +* `block.rm` now returns an async iterable. + +* `block.rm` now yields objects of `{ cid: CID, error: Error }`. + +* `block.stat` result now contains a `cid` property (whose value is a [CID instance](https://github.com/multiformats/js-cid)) instead of a `key` property. + +* `dht.findProvs`, `dht.provide`, `dht.put` and `dht.query` now all return an async iterable. + +* `dht.findPeer`, `dht.findProvs`, `dht.provide`, `dht.put` and `dht.query` now yield/return an object `{ id: string, addrs: Multiaddr[] }` instead of a `PeerInfo` instance(s). + +* `files.lsPullStream` and `files.lsReadableStream` have been removed. Please see the [migration guide](https://gist.github.com/alanshaw/04b2ddc35a6fff25c040c011ac6acf26#migrating-to-async-iterables) for more info. + +* `files.ls` now returns an async iterable. + +* `files.ls` results now contain a `cid` property (whose value is a [CID instance](https://github.com/multiformats/js-cid)) instead of a `hash` property. + +* `files.ls` no longer takes a `long` option (in core) - you will receive all data by default. + +* `files.readPullStream` and `files.readReadableStream` have been removed. Please see the [migration guide](https://gist.github.com/alanshaw/04b2ddc35a6fff25c040c011ac6acf26#migrating-to-async-iterables) for more info. + +* `files.read` now returns an async iterable. + +* `files.stat` result now contains a `cid` property (whose value is a [CID instance](https://github.com/multiformats/js-cid)) instead of a `hash` property. + +* `get` now returns an async iterable. The `content` property value for objects yielded from the iterator is now an async iterable that yields [`BufferList`](https://github.com/rvagg/bl) objects. + +* `id` result has changed, the `addresses` property is now a `Multiaddr[]` + +* `name.resolve` now returns an async iterable. It yields increasingly more accurate resolved values as they are discovered until the best value is selected from the quorum of 16. The "best" resolved value is the last item yielded from the iterator. If you are interested only in this best value you could use `it-last` to extract it like so: + + ```js + const last = require('it-last') + await last(ipfs.name.resolve('/ipns/QmHash')) + ``` + +* `ls` now returns an async iterable. + +* `ls` results now contain a `cid` property (whose value is a [CID instance](https://github.com/multiformats/js-cid)) instead of a `hash` property. + +* `ls` results now include `mode` and `mtime` properties if they were set. See the [core interface docs](https://github.com/ipfs/interface-js-ipfs-core/blob/master/SPEC/FILES.md#ls) for more info. + +* `pin.add` results now contain a `cid` property (a [CID instance](https://github.com/multiformats/js-cid)) instead of a string `hash` property. + +* `pin.ls` now returns an async iterable. + +* `pin.ls` results now contain a `cid` property (a [CID instance](https://github.com/multiformats/js-cid)) instead of a string `hash` property. + +* `pin.rm` results now contain a `cid` property (a [CID instance](https://github.com/multiformats/js-cid)) instead of a string `hash` property. + +* `ping` now returns an async iterable. + +* `refs` and `refs.local` now return an async iterable. + +* `repo.gc` now returns an async iterable. + +* `stats.bw` now returns an async iterable. + +* `swarm.peers` now returns an array of objects with a `peer` property that is a `string`, instead of a `PeerId` instance. + +* `swarm.addrs` now returns an array of objects `{ id: string, addrs: Multiaddr[] }` instead of `PeerInfo` instances. + +* The protocol _name_ for peer IDs in multiaddrs has changed from 'ipfs' to 'p2p'. There's no changes to data on the wire but this change is seen when multiaddrs are converted to strings. + From e9ce88d2523663b9730a0ffa28c6791f45976549 Mon Sep 17 00:00:00 2001 From: Alex Potsides Date: Tue, 11 Feb 2020 15:42:02 +0100 Subject: [PATCH 232/233] chore: update ipfsd-ctl to latest version (#1237) * chore: update ipfsd-ctl to latest version Also uses the same ipfsd factory for all tests. * chore: remove gh dep version --- .aegir.js | 9 ++++++++- package.json | 4 ++-- test/commands.spec.js | 2 +- test/constructor.spec.js | 2 +- test/dag.spec.js | 2 +- test/diag.spec.js | 2 +- test/files-mfs.spec.js | 2 +- test/get.spec.js | 2 +- test/interface.spec.js | 28 +++++++--------------------- test/key.spec.js | 2 +- test/log.spec.js | 2 +- test/ping.spec.js | 2 +- test/repo.spec.js | 2 +- test/stats.spec.js | 2 +- test/utils/factory.js | 23 ++++++++++++++++------- 15 files changed, 44 insertions(+), 42 deletions(-) diff --git a/.aegir.js b/.aegir.js index 2e5fb64db..793c4eb13 100644 --- a/.aegir.js +++ b/.aegir.js @@ -2,7 +2,14 @@ const createServer = require('ipfsd-ctl').createServer const EchoServer = require('interface-ipfs-core/src/utils/echo-http-server') -const server = createServer() +const server = createServer({ + host: '127.0.0.1', + port: 43134 +}, { + type: 'go', + ipfsHttpModule: require('./'), + ipfsBin: require('go-ipfs-dep').path() +}) const echoServer = EchoServer.createServer() module.exports = { diff --git a/package.json b/package.json index 07ad807db..a7a635e9a 100644 --- a/package.json +++ b/package.json @@ -67,9 +67,9 @@ "aegir": "^20.4.1", "async": "^3.1.0", "browser-process-platform": "~0.1.1", - "go-ipfs-dep": "^0.4.23", + "go-ipfs-dep": "^0.4.23-3", "interface-ipfs-core": "^0.131.7", - "ipfsd-ctl": "^2.1.0", + "ipfsd-ctl": "^3.0.0", "it-all": "^1.0.1", "it-concat": "^1.0.0", "it-pipe": "^1.1.0", diff --git a/test/commands.spec.js b/test/commands.spec.js index 9e68a1e01..96f932b92 100644 --- a/test/commands.spec.js +++ b/test/commands.spec.js @@ -2,7 +2,7 @@ 'use strict' const { expect } = require('interface-ipfs-core/src/utils/mocha') -const f = require('./utils/factory') +const f = require('./utils/factory')() describe('.commands', function () { this.timeout(60 * 1000) diff --git a/test/constructor.spec.js b/test/constructor.spec.js index a1a000c84..acffb11e7 100644 --- a/test/constructor.spec.js +++ b/test/constructor.spec.js @@ -3,7 +3,7 @@ const multiaddr = require('multiaddr') const { expect } = require('interface-ipfs-core/src/utils/mocha') -const f = require('./utils/factory') +const f = require('./utils/factory')() const ipfsClient = require('../src/index.js') describe('ipfs-http-client constructor tests', () => { diff --git a/test/dag.spec.js b/test/dag.spec.js index de9217d13..fec5229f6 100644 --- a/test/dag.spec.js +++ b/test/dag.spec.js @@ -6,7 +6,7 @@ const { expect } = require('interface-ipfs-core/src/utils/mocha') const { DAGNode } = require('ipld-dag-pb') const CID = require('cids') -const f = require('./utils/factory') +const f = require('./utils/factory')() let ipfs diff --git a/test/diag.spec.js b/test/diag.spec.js index 37a1911e7..9f16d6932 100644 --- a/test/diag.spec.js +++ b/test/diag.spec.js @@ -3,7 +3,7 @@ const { expect } = require('interface-ipfs-core/src/utils/mocha') const platform = require('browser-process-platform') -const f = require('./utils/factory') +const f = require('./utils/factory')() describe('.diag', function () { this.timeout(50 * 1000) diff --git a/test/files-mfs.spec.js b/test/files-mfs.spec.js index edc7698e1..4d7e0ea83 100644 --- a/test/files-mfs.spec.js +++ b/test/files-mfs.spec.js @@ -9,7 +9,7 @@ const all = require('it-all') const pipe = require('it-pipe') const { TimeoutError } = require('ky-universal') -const f = require('./utils/factory') +const f = require('./utils/factory')() const testfile = loadFixture('test/fixtures/testfile.txt') diff --git a/test/get.spec.js b/test/get.spec.js index c303179c8..5c64e3bf2 100644 --- a/test/get.spec.js +++ b/test/get.spec.js @@ -8,7 +8,7 @@ const loadFixture = require('aegir/fixtures') const all = require('it-all') const concat = require('it-concat') -const f = require('./utils/factory') +const f = require('./utils/factory')() describe('.get (specific go-ipfs features)', function () { this.timeout(60 * 1000) diff --git a/test/interface.spec.js b/test/interface.spec.js index ebec1b0e9..72cc86cfb 100644 --- a/test/interface.spec.js +++ b/test/interface.spec.js @@ -2,27 +2,13 @@ 'use strict' const tests = require('interface-ipfs-core') -const merge = require('merge-options') -const { createFactory } = require('ipfsd-ctl') -const { findBin } = require('ipfsd-ctl/src/utils') +const factory = require('./utils/factory') const isWindows = process.platform && process.platform === 'win32' /** @typedef {import("ipfsd-ctl").ControllerOptions} ControllerOptions */ describe('interface-ipfs-core tests', () => { - /** @type ControllerOptions */ - const commonOptions = { - test: true, - ipfsHttpModule: { - path: require.resolve('../src'), - ref: require('../src') - }, - ipfsOptions: { - pass: 'ipfs-is-awesome-software' - }, - ipfsBin: findBin('go') - } - const commonFactory = createFactory(commonOptions) + const commonFactory = factory() tests.root(commonFactory, { skip: [ @@ -320,13 +306,13 @@ describe('interface-ipfs-core tests', () => { tests.miscellaneous(commonFactory) - tests.name(createFactory(merge(commonOptions, + tests.name(factory( { ipfsOptions: { offline: true } } - )), { + ), { skip: [ { name: 'should resolve a record from peerid as cidv1 in base32', @@ -335,7 +321,7 @@ describe('interface-ipfs-core tests', () => { ] }) - tests.namePubsub(createFactory(merge(commonOptions, + tests.namePubsub(factory( { ipfsOptions: { EXPERIMENTAL: { @@ -343,7 +329,7 @@ describe('interface-ipfs-core tests', () => { } } } - )), { + ), { skip: [ // name.pubsub.cancel { @@ -371,7 +357,7 @@ describe('interface-ipfs-core tests', () => { ] }) - tests.pubsub(createFactory(commonOptions, { + tests.pubsub(factory({}, { go: { args: ['--enable-pubsub-experiment'] } diff --git a/test/key.spec.js b/test/key.spec.js index 180cb795b..eb53b8293 100644 --- a/test/key.spec.js +++ b/test/key.spec.js @@ -2,7 +2,7 @@ 'use strict' const { expect } = require('interface-ipfs-core/src/utils/mocha') -const f = require('./utils/factory') +const f = require('./utils/factory')() describe('.key', function () { this.timeout(50 * 1000) diff --git a/test/log.spec.js b/test/log.spec.js index c56660d07..cfa18582c 100644 --- a/test/log.spec.js +++ b/test/log.spec.js @@ -4,7 +4,7 @@ const { expect } = require('interface-ipfs-core/src/utils/mocha') const all = require('it-all') -const f = require('./utils/factory') +const f = require('./utils/factory')() describe('.log', function () { this.timeout(100 * 1000) diff --git a/test/ping.spec.js b/test/ping.spec.js index 7076f208b..b464062bb 100644 --- a/test/ping.spec.js +++ b/test/ping.spec.js @@ -4,7 +4,7 @@ const { expect } = require('interface-ipfs-core/src/utils/mocha') const all = require('it-all') -const f = require('./utils/factory') +const f = require('./utils/factory')() // Determine if a ping response object is a pong, or something else, like a status message function isPong (pingResponse) { diff --git a/test/repo.spec.js b/test/repo.spec.js index 21482135d..7a1b643d7 100644 --- a/test/repo.spec.js +++ b/test/repo.spec.js @@ -2,7 +2,7 @@ 'use strict' const { expect } = require('interface-ipfs-core/src/utils/mocha') -const f = require('./utils/factory') +const f = require('./utils/factory')() describe('.repo', function () { this.timeout(50 * 1000) // slow CI diff --git a/test/stats.spec.js b/test/stats.spec.js index 1e5d7da25..6b1530bee 100644 --- a/test/stats.spec.js +++ b/test/stats.spec.js @@ -3,7 +3,7 @@ const { expect } = require('interface-ipfs-core/src/utils/mocha') const all = require('it-all') -const f = require('./utils/factory') +const f = require('./utils/factory')() describe('stats', function () { this.timeout(50 * 1000) // slow CI diff --git a/test/utils/factory.js b/test/utils/factory.js index d6ac161ea..70f4e151c 100644 --- a/test/utils/factory.js +++ b/test/utils/factory.js @@ -1,15 +1,24 @@ 'use strict' + const { createFactory } = require('ipfsd-ctl') -const { findBin } = require('ipfsd-ctl/src/utils') +const merge = require('merge-options') +const { isNode } = require('ipfs-utils/src/env') -const factory = createFactory({ +const commonOptions = { test: 'true', type: 'go', - ipfsBin: findBin('go'), - ipfsHttpModule: { - path: require.resolve('../../src'), - ref: require('../../src') + ipfsHttpModule: require('../../src') +} + +const commonOverrides = { + go: { + ipfsBin: isNode ? require('go-ipfs-dep').path() : undefined } -}) +} + +const factory = (options = {}, overrides = {}) => createFactory( + merge(commonOptions, options), + merge(commonOverrides, overrides) +) module.exports = factory From 995abb41b83c8345b16cba67151e9ccb9cbea4de Mon Sep 17 00:00:00 2001 From: achingbrain Date: Fri, 6 Mar 2020 17:51:23 +0000 Subject: [PATCH 233/233] docs: add notice of archival --- README.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/README.md b/README.md index 88ed592f8..bd40851aa 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,9 @@ +# 🔒 Archived + +The contents of this repo have been merged into [ipfs/js-ipfs](https://github.com/ipfs/js-ipfs). + +Please open [issues](https://github.com/ipfs/js-ipfs/issues) or submit [PRs](https://github.com/ipfs/js-ipfs/pulls) there. +

IPFS http client lib logo

@@ -54,7 +60,11 @@ - [Instance Utils](#instance-utils) - [Static Types and Utils](#static-types-and-utils) - [Glob source](#glob-source) + - [`globSource(path, [options])`](#globsourcepath-options) + - [Example](#example) - [URL source](#url-source) + - [`urlSource(url)`](#urlsourceurl) + - [Example](#example-1) - [Development](#development) - [Testing](#testing) - [Contribute](#contribute)