From 0513da7bab4148a14cf77be810a0b488bcc66c04 Mon Sep 17 00:00:00 2001 From: Hugo Dias Date: Mon, 29 Oct 2018 11:37:37 +0000 Subject: [PATCH 01/11] fix: fix non-disposable init start with running node --- package.json | 1 + src/factory-daemon.js | 70 ++++--------- src/ipfsd-daemon.js | 12 ++- test/non-disposable.spec.js | 190 ++++++++++++++++++++++++++++++++++++ test/spawn-options.spec.js | 149 +--------------------------- test/start-stop.node.js | 48 --------- 6 files changed, 226 insertions(+), 244 deletions(-) create mode 100644 test/non-disposable.spec.js diff --git a/package.json b/package.json index e52887e4..62d7d6c6 100644 --- a/package.json +++ b/package.json @@ -82,6 +82,7 @@ "lodash.clone": "^4.5.0", "lodash.defaults": "^4.2.0", "lodash.defaultsdeep": "^4.6.0", + "merge-options": "^1.0.1", "multiaddr": "^5.0.0", "once": "^1.4.0", "protons": "^1.0.1", diff --git a/src/factory-daemon.js b/src/factory-daemon.js index 65279de1..25571339 100644 --- a/src/factory-daemon.js +++ b/src/factory-daemon.js @@ -1,13 +1,11 @@ 'use strict' -const defaultsDeep = require('lodash.defaultsdeep') -const clone = require('lodash.clone') const series = require('async/series') +const merge = require('merge-options') const path = require('path') const tmpDir = require('./utils/tmp-dir') const Daemon = require('./ipfsd-daemon') const defaultConfig = require('./defaults/config.json') -const defaultOptions = require('./defaults/options.json') /** @ignore @typedef {import("./index").SpawnOptions} SpawnOptions */ @@ -23,7 +21,7 @@ class FactoryDaemon { if (options && options.type === 'proc') { throw new Error('This Factory does not know how to spawn in proc nodes') } - this.options = Object.assign({}, { type: 'go' }, options) + this.options = Object.assign({ type: 'go' }, options) } /** @@ -52,7 +50,6 @@ class FactoryDaemon { * - version - the ipfs version * - repo - the repo version * - commit - the commit hash for this version - * @returns {void} */ version (options, callback) { if (typeof options === 'function') { @@ -76,63 +73,38 @@ class FactoryDaemon { * * @param {SpawnOptions} [options={}] - Various config options and ipfs config parameters * @param {function(Error, Daemon): void} callback - Callback receives Error or a Daemon instance, Daemon has a `api` property which is an `ipfs-http-client` instance. - * @returns {void} */ spawn (options, callback) { if (typeof options === 'function') { callback = options options = {} } - - // TODO this options parsing is daunting. Refactor and move to a separate - // func documenting what it is trying to do. - options = defaultsDeep( - { IpfsClient: this.options.IpfsClient }, - options, - defaultOptions + const defaultRepo = path.join( + process.env.HOME || process.env.USERPROFILE, + this.options.type === 'js' ? '.jsipfs' : '.ipfs' ) - - options.init = typeof options.init !== 'undefined' - ? options.init - : true - - if (!options.disposable) { - const nonDisposableConfig = clone(defaultConfig) - options.init = false - options.start = false - - const defaultRepo = path.join( - process.env.HOME || process.env.USERPROFILE, - options.isJs - ? '.jsipfs' - : '.ipfs' - ) - - options.repoPath = options.repoPath || - (process.env.IPFS_PATH || defaultRepo) - options.config = defaultsDeep({}, options.config, nonDisposableConfig) - } else { - options.config = defaultsDeep({}, options.config, defaultConfig) - } + const daemonOptions = merge({ + exec: this.options.exec, + type: this.options.type, + IpfsClient: this.options.IpfsClient, + disposable: true, + start: options.disposable !== false, + init: options.disposable !== false, + config: defaultConfig, + repoPath: defaultRepo + }, options) if (options.defaultAddrs) { - delete options.config.Addresses + delete daemonOptions.config.Addresses } - options.type = this.options.type - options.exec = options.exec || this.options.exec - options.initOptions = defaultsDeep({}, this.options.initOptions, options.initOptions) - - const node = new Daemon(options) + const node = new Daemon(daemonOptions) series([ - (cb) => options.init - ? node.init(options.initOptions, cb) - : cb(null, node), - (cb) => options.start - ? node.start(options.args, cb) - : cb() - ], (err) => { + daemonOptions.init && ((cb) => node.init(daemonOptions.initOptions, cb)), + daemonOptions.start && ((cb) => node.start(daemonOptions.args, cb)) + ].filter(Boolean), + (err) => { if (err) { return callback(err) } callback(null, node) diff --git a/src/ipfsd-daemon.js b/src/ipfsd-daemon.js index 997d6045..b84d239b 100644 --- a/src/ipfsd-daemon.js +++ b/src/ipfsd-daemon.js @@ -64,7 +64,6 @@ class Daemon { delete process.env.IPFS_EXEC } - const envExec = this.opts.type === 'go' ? process.env.IPFS_GO_EXEC : process.env.IPFS_JS_EXEC this.exec = this.opts.exec || envExec || findIpfsExecutable(this.opts.type, rootPath) this.subprocess = null @@ -152,7 +151,16 @@ class Daemon { init (initOptions, callback) { if (typeof initOptions === 'function') { callback = initOptions - initOptions = {} + initOptions = null + } + + if (this.initialized && initOptions) { + callback(new Error(`Repo already initialized can't use different options, ${JSON.stringify(initOptions)}`)) + } + + if (this.initialized) { + this.clean = false + return callback(null, this) } initOptions = initOptions || {} diff --git a/test/non-disposable.spec.js b/test/non-disposable.spec.js new file mode 100644 index 00000000..239ad30c --- /dev/null +++ b/test/non-disposable.spec.js @@ -0,0 +1,190 @@ +/* eslint-env mocha */ +/* eslint max-nested-callbacks: ["error", 8] */ +'use strict' + +const chai = require('chai') +const dirtyChai = require('dirty-chai') +const IPFSFactory = require('../src') +const tmpDir = require('../src/utils/tmp-dir') + +const expect = chai.expect +chai.use(dirtyChai) + +const tests = [ + // { type: 'go', bits: 1024 }, + { type: 'js', bits: 512 } +] + +tests.forEach((fOpts) => { + const config = Object.assign({}, {port: 25000}, fOpts) + + describe.only(`non-disposable ${fOpts.type} daemon`, function () { + this.timeout(40000) + let ipfsd = null + let repoPath = null + let id = null + + before(function (done) { + const f = IPFSFactory.create(fOpts) + + f.spawn({ initOptions: { bits: fOpts.bits } }, (err, _ipfsd) => { + if (err) { + done(err) + } + ipfsd = _ipfsd + repoPath = ipfsd.path + + ipfsd.api.id() + .then(data => { + id = data.id + done() + }) + }) + }) + + after(done => ipfsd.stop(done)) + + it('should fail when passing initOptions to a initialized repo', function (done) { + const df = IPFSFactory.create(config) + df.spawn({ + initOptions: { bits: fOpts.bits }, + repoPath: repoPath, + disposable: false, + init: true + }, (err, ipfsd) => { + expect(err, err.message).to.exist() + done() + }) + }) + + it('should attach to initialized and running node', function (done) { + const df = IPFSFactory.create(config) + df.spawn({ + repoPath: ipfsd.repoPath, + disposable: false, + init: true, + start: true + }, (err, ipfsd) => { + if (err) { + done(err) + } + + ipfsd.api.id() + .then(data => { + expect(data.id).to.be.eq(id) + ipfsd.stop(done) + }) + .catch(done) + }) + }) + + it('should attach to running node with manual start', function (done) { + const df = IPFSFactory.create(config) + df.spawn({ + repoPath: ipfsd.repoPath, + disposable: false + }, (err, daemon) => { + if (err) { + done(err) + } + + daemon.start((err, api) => { + if (err) { + done(err) + } + expect(api).to.exist() + expect(ipfsd.apiAddr).to.be.eql(daemon.apiAddr) + daemon.stop(done) + }) + }) + }) + + it('should not init and start', function (done) { + const df = IPFSFactory.create(config) + df.spawn({ + initOptions: { bits: fOpts.bits }, + repoPath: tmpDir(fOpts.type === 'js'), + disposable: false + }, (err, ipfsd) => { + if (err) { + done(err) + } + + expect(ipfsd.api).to.not.exist() + ipfsd.stop(done()) + }) + }) + + it.only('should init and start', function (done) { + const df = IPFSFactory.create(config) + df.spawn({ + initOptions: { bits: fOpts.bits }, + repoPath: tmpDir(fOpts.type === 'js'), + disposable: false, + start: true, + init: true + }, (err, ipfsd) => { + if (err) { + done(err) + } + + expect(ipfsd.api).to.exist() + ipfsd.stop(err => { + if (err) { + done(err) + } + ipfsd.cleanup(done) + }) + }) + }) + + it('should only init', function (done) { + const df = IPFSFactory.create(config) + df.spawn({ + initOptions: { bits: fOpts.bits }, + repoPath: tmpDir(fOpts.type === 'js'), + disposable: false, + init: true + }, (err, ipfsd) => { + if (err) { + done(err) + } + expect(ipfsd.initialized).to.be.true() + expect(ipfsd.started).to.be.false() + + ipfsd.stop(err => { + if (err) { + done(err) + } + ipfsd.cleanup(done) + }) + }) + }) + + it('should only init manualy', function (done) { + const df = IPFSFactory.create(config) + df.spawn({ + initOptions: { bits: fOpts.bits }, + repoPath: tmpDir(fOpts.type === 'js'), + disposable: false, + init: true + }, (err, ipfsd) => { + if (err) { + done(err) + } + + ipfsd.init((err) => { + expect(err).to.not.exist() + expect(ipfsd.initialized).to.be.true() + expect(ipfsd.started).to.be.false() + ipfsd.stop(err => { + if (err) { + done(err) + } + ipfsd.cleanup(done) + }) + }) + }) + }) + }) +}) diff --git a/test/spawn-options.spec.js b/test/spawn-options.spec.js index 011d693c..1841a98f 100644 --- a/test/spawn-options.spec.js +++ b/test/spawn-options.spec.js @@ -51,116 +51,6 @@ describe('Spawn options', function () { }) }) - describe('init and start', () => { - let prevRepoPath - - describe('init and start manually', () => { - let ipfsd - let repoPath - - before((done) => { - f.tmpDir(fOpts.type, (err, tmpDir) => { - expect(err).to.not.exist() - repoPath = tmpDir - prevRepoPath = repoPath - done() - }) - }) - - it('f.spawn', (done) => { - const options = { - repoPath: repoPath, - init: false, - start: false, - disposable: false, - initOptions: { bits: fOpts.bits } - } - - f.spawn(options, (err, _ipfsd) => { - expect(err).to.not.exist() - expect(_ipfsd).to.exist() - expect(_ipfsd.api).to.not.exist() - expect(_ipfsd.initialized).to.eql(false) - - ipfsd = _ipfsd - repoPath = _ipfsd.repoPath - done() - }) - }) - - it('ipfsd.init', function (done) { - this.timeout(20 * 1000) - - ipfsd.init((err) => { - expect(err).to.not.exist() - expect(ipfsd.initialized).to.be.ok() - done() - }) - }) - - it('ipfsd.start', function (done) { - this.timeout(20 * 1000) - - ipfsd.start((err, api) => { - expect(err).to.not.exist() - expect(api).to.exist() - expect(api.id).to.exist() - done() - }) - }) - - it('ipfsd.stop', function (done) { - this.timeout(20 * 1000) - - ipfsd.stop(done) - }) - }) - - describe('spawn from an initialized repo', () => { - let ipfsd - - it('f.spawn', function (done) { - this.timeout(20 * 1000) - - const options = { - repoPath: prevRepoPath, - init: false, - start: false, - disposable: false - } - - f.spawn(options, (err, _ipfsd) => { - expect(err).to.not.exist() - expect(_ipfsd).to.exist() - - ipfsd = _ipfsd - - expect(ipfsd.api).to.not.exist() - expect(ipfsd.initialized).to.eql(true) - - done() - }) - }) - - it('ipfsd.start', function (done) { - this.timeout(20 * 1000) - - ipfsd.start((err, api) => { - expect(err).to.not.exist() - expect(api).to.exist() - expect(api.id).to.exist() - done() - }) - }) - - it('ipfsd.stop', function (done) { - this.timeout(20 * 1000) - - ipfsd.stop(done) - }) - }) - }) - describe('spawn a node and attach api', () => { let ipfsd @@ -286,7 +176,6 @@ describe('Spawn options', function () { // remote endpoint? if (!isNode) { return } - let ipfsd let repoPath before((done) => { @@ -298,53 +187,23 @@ describe('Spawn options', function () { }) it('allows passing custom repo path to spawn', function (done) { - this.timeout(20 * 1000) - - const config = { - Addresses: { - Swarm: [ - '/ip4/127.0.0.1/tcp/0/ws', - '/ip4/127.0.0.1/tcp/0' - ], - API: '/ip4/127.0.0.1/tcp/0', - Gateway: '/ip4/127.0.0.1/tcp/0' - } - } - const options = { disposable: false, - init: false, - start: false, + init: true, + start: true, repoPath: repoPath, - config: config, initOptions: { bits: fOpts.bits } } - series([ - (cb) => f.spawn(options, (err, _ipfsd) => { - expect(err).to.not.exist() - ipfsd = _ipfsd - cb() - }), - (cb) => { - ipfsd.init(cb) - }, - (cb) => { - ipfsd.start(cb) - } - ], (err) => { + f.spawn(options, (err, ipfsd) => { expect(err).to.not.exist() if (isNode) { // We can only check if it really got created when run in Node.js expect(fs.existsSync(repoPath)).to.be.ok() } - done() + ipfsd.stop(() => ipfsd.cleanup(done)) }) }) - - after((done) => { - ipfsd.stop(() => ipfsd.cleanup(done)) - }) }) describe('f.spawn with args', () => { diff --git a/test/start-stop.node.js b/test/start-stop.node.js index c06a4900..e0b48af9 100644 --- a/test/start-stop.node.js +++ b/test/start-stop.node.js @@ -323,54 +323,6 @@ tests.forEach((fOpts) => { }) }) - describe('should detect and attach to running node', () => { - let ipfsd - let exec - - before(function (done) { - this.timeout(50 * 1000) - - const df = IPFSFactory.create(dfConfig) - exec = findIpfsExecutable(fOpts.type) - - df.spawn({ - exec, - initOptions: { bits: fOpts.bits } - }, (err, daemon) => { - expect(err).to.not.exist() - expect(daemon).to.exist() - - ipfsd = daemon - done() - }) - }) - - after((done) => ipfsd.stop(done)) - - it('should return a node', () => { - expect(ipfsd).to.exist() - }) - - it('shoul attach to running node', function (done) { - this.timeout(50 * 1000) - - const df = IPFSFactory.create(dfConfig) - df.spawn({ - initOptions: { bits: fOpts.bits }, - repoPath: ipfsd.repoPath, - disposable: false - }, (err, daemon) => { - expect(err).to.not.exist() - daemon.start((err, api) => { - expect(err).to.not.exist() - expect(api).to.exist() - expect(ipfsd.apiAddr).to.be.eql(daemon.apiAddr) - daemon.stop(done) - }) - }) - }) - }) - describe('should fail on invalid exec path', function () { this.timeout(20 * 1000) From 557d0cdfa1b9c5fb0d3839ac69b42592fcd82341 Mon Sep 17 00:00:00 2001 From: Hugo Dias Date: Mon, 29 Oct 2018 11:44:20 +0000 Subject: [PATCH 02/11] chore: update readme docs --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6052764c..1f00cdcb 100644 --- a/README.md +++ b/README.md @@ -84,7 +84,7 @@ server.start((err) => { `ipfsd-ctl` can spawn `disposable` and `non-disposable` daemons. - `disposable`- Creates on a temporary repo which will be optionally initialized and started (the default), as well cleaned up on process exit. Great for tests. -- `non-disposable` - Requires the user to initialize and start the node, as well as stop and cleanup after wards. Additionally, a non-disposable will allow you to pass a custom repo using the `repoPath` option, if the `repoPath` is not defined, it will use the default repo for the node type (`$HOME/.ipfs` or `$HOME/.jsipfs`). The `repoPath` parameter is ignored for disposable nodes, as there is a risk of deleting a live repo. +- `non-disposable` - Non disposable daemons will by default attach to any nodes running on the default or the supplied repo. Requires the user to initialize and start the node, as well as stop and cleanup after wards. Additionally, a non-disposable will allow you to pass a custom repo using the `repoPath` option, if the `repoPath` is not defined, it will use the default repo for the node type (`$HOME/.ipfs` or `$HOME/.jsipfs`). The `repoPath` parameter is ignored for disposable nodes, as there is a risk of deleting a live repo. ## Batteries not included. Bring your own IPFS executable. From 62d77dee3c9c58f3897fedbc76b0989cd9bbe564 Mon Sep 17 00:00:00 2001 From: Hugo Dias Date: Mon, 29 Oct 2018 12:01:06 +0000 Subject: [PATCH 03/11] fix: add back commented line --- test/non-disposable.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/non-disposable.spec.js b/test/non-disposable.spec.js index 239ad30c..f2184399 100644 --- a/test/non-disposable.spec.js +++ b/test/non-disposable.spec.js @@ -11,7 +11,7 @@ const expect = chai.expect chai.use(dirtyChai) const tests = [ - // { type: 'go', bits: 1024 }, + { type: 'go', bits: 1024 }, { type: 'js', bits: 512 } ] From 22a29c93b143f9eb2e12cda921dd850a033c3156 Mon Sep 17 00:00:00 2001 From: Hugo Dias Date: Mon, 29 Oct 2018 12:01:32 +0000 Subject: [PATCH 04/11] fix: remove only from describe --- test/non-disposable.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/non-disposable.spec.js b/test/non-disposable.spec.js index f2184399..47a49d14 100644 --- a/test/non-disposable.spec.js +++ b/test/non-disposable.spec.js @@ -18,7 +18,7 @@ const tests = [ tests.forEach((fOpts) => { const config = Object.assign({}, {port: 25000}, fOpts) - describe.only(`non-disposable ${fOpts.type} daemon`, function () { + describe(`non-disposable ${fOpts.type} daemon`, function () { this.timeout(40000) let ipfsd = null let repoPath = null From 741be6696073f75a0816e763457ae408360f0d7c Mon Sep 17 00:00:00 2001 From: Hugo Dias Date: Mon, 29 Oct 2018 12:03:09 +0000 Subject: [PATCH 05/11] fix: remove only from it --- test/non-disposable.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/non-disposable.spec.js b/test/non-disposable.spec.js index 47a49d14..bc1ee8df 100644 --- a/test/non-disposable.spec.js +++ b/test/non-disposable.spec.js @@ -115,7 +115,7 @@ tests.forEach((fOpts) => { }) }) - it.only('should init and start', function (done) { + it('should init and start', function (done) { const df = IPFSFactory.create(config) df.spawn({ initOptions: { bits: fOpts.bits }, From b0d41847862a38874e13898a74219dbde0910733 Mon Sep 17 00:00:00 2001 From: David Dias Date: Wed, 31 Oct 2018 07:46:51 +0000 Subject: [PATCH 06/11] chore: give a kick to CI --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 1f00cdcb..4c512eb6 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,7 @@ [![Dependency Status](https://david-dm.org/ipfs/js-ipfsd-ctl.svg?style=flat-square)](https://david-dm.org/ipfs/js-ipfsd-ctl) [![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat-square)](https://github.com/feross/standard) [![Bundle Size](https://flat.badgen.net/bundlephobia/minzip/ipfsd-ctl)](https://bundlephobia.com/result?p=ipfsd-ctl) + > Spawn IPFS daemons using JavaScript! ## Lead Maintainer From 64c5627a8f773f776d2cc824b899a277cf021804 Mon Sep 17 00:00:00 2001 From: Hugo Dias Date: Wed, 14 Nov 2018 11:36:27 +0000 Subject: [PATCH 07/11] fix: basicaly normalize behaviour across the 3 impls --- src/endpoint/routes.js | 33 +++---- src/factory-client.js | 35 ++++---- src/factory-daemon.js | 13 +-- src/factory-in-proc.js | 89 ++++++------------ src/ipfsd-client.js | 152 +++++++++++++++---------------- src/ipfsd-daemon.js | 117 ++++++++---------------- src/ipfsd-in-proc.js | 174 ++++++++++++++++-------------------- src/utils/repo/browser.js | 17 ++-- src/utils/repo/nodejs.js | 30 +++++-- test/endpoint/client.js | 22 ++--- test/endpoint/routes.js | 91 +++++++------------ test/non-disposable.spec.js | 166 ++++++++++++++++++---------------- test/spawn-options.spec.js | 45 ++-------- 13 files changed, 427 insertions(+), 557 deletions(-) diff --git a/src/endpoint/routes.js b/src/endpoint/routes.js index bf964b98..3ccc5a38 100644 --- a/src/endpoint/routes.js +++ b/src/endpoint/routes.js @@ -61,32 +61,25 @@ module.exports = (server) => { path: '/spawn', handler: (request, reply) => { const payload = request.payload || {} - // TODO: use the ../src/index.js so that the right Factory is picked const f = new FactoryDaemon({ type: payload.type }) - f.spawn(payload.options, (err, ipfsd) => { + f.spawn(payload, (err, ipfsd) => { if (err) { return reply(boom.badRequest(err)) } const id = hat() - const initialized = ipfsd.initialized nodes[id] = ipfsd - let api = null - - if (nodes[id].started) { - api = { - apiAddr: nodes[id].apiAddr - ? nodes[id].apiAddr.toString() - : '', - gatewayAddr: nodes[id].gatewayAddr - ? nodes[id].gatewayAddr.toString() - : '' - } - } - - reply({ id: id, api: api, initialized: initialized }) + reply({ + _id: id, + apiAddr: ipfsd.apiAddr ? ipfsd.apiAddr.toString() : '', + gatewayAddr: ipfsd.gatewayAddr ? ipfsd.gatewayAddr.toString() : '', + initialized: ipfsd.initialized, + started: ipfsd.started, + _env: ipfsd._env, + path: ipfsd.path + }) }) } }) @@ -131,10 +124,8 @@ module.exports = (server) => { } reply({ - api: { - apiAddr: nodes[id].apiAddr.toString(), - gatewayAddr: nodes[id].gatewayAddr.toString() - } + apiAddr: nodes[id].apiAddr.toString(), + gatewayAddr: nodes[id].gatewayAddr ? nodes[id].gatewayAddr.toString() : null }) }) }, diff --git a/src/factory-client.js b/src/factory-client.js index 1ce59c27..83cf22c7 100644 --- a/src/factory-client.js +++ b/src/factory-client.js @@ -1,6 +1,8 @@ 'use strict' const request = require('superagent') +const merge = require('merge-options') +const defaultConfig = require('./defaults/config.json') const DaemonClient = require('./ipfsd-client') /** @ignore @typedef {import("./index").SpawnOptions} SpawnOptions */ @@ -90,29 +92,32 @@ class FactoryClient { options = {} } - options = options || {} - + const daemonOptions = merge({ + exec: this.options.exec, + type: this.options.type, + IpfsClient: this.options.IpfsClient, + disposable: true, + start: options.disposable !== false, + init: options.disposable !== false, + config: defaultConfig + }, options) + + if (options.defaultAddrs) { + delete daemonOptions.config.Addresses + } request - .post(`${this.baseUrl}/spawn`) - .send({ options: options, type: this.options.type }) + .post(`${this.baseUrl}/spawn`, daemonOptions) .end((err, res) => { if (err) { return callback(new Error(err.response ? err.response.body.message : err)) } - - const apiAddr = res.body.api ? res.body.api.apiAddr : '' - const gatewayAddr = res.body.api ? res.body.api.gatewayAddr : '' - - const ipfsd = new DaemonClient( + const node = new DaemonClient( this.baseUrl, - res.body.id, - res.body.initialized, - apiAddr, - gatewayAddr, - { IpfsClient: this.options.IpfsClient } + res.body, + daemonOptions ) - callback(null, ipfsd) + callback(null, node) }) } } diff --git a/src/factory-daemon.js b/src/factory-daemon.js index 25571339..584a5e57 100644 --- a/src/factory-daemon.js +++ b/src/factory-daemon.js @@ -2,7 +2,6 @@ const series = require('async/series') const merge = require('merge-options') -const path = require('path') const tmpDir = require('./utils/tmp-dir') const Daemon = require('./ipfsd-daemon') const defaultConfig = require('./defaults/config.json') @@ -79,10 +78,7 @@ class FactoryDaemon { callback = options options = {} } - const defaultRepo = path.join( - process.env.HOME || process.env.USERPROFILE, - this.options.type === 'js' ? '.jsipfs' : '.ipfs' - ) + const daemonOptions = merge({ exec: this.options.exec, type: this.options.type, @@ -90,8 +86,7 @@ class FactoryDaemon { disposable: true, start: options.disposable !== false, init: options.disposable !== false, - config: defaultConfig, - repoPath: defaultRepo + config: defaultConfig }, options) if (options.defaultAddrs) { @@ -101,8 +96,8 @@ class FactoryDaemon { const node = new Daemon(daemonOptions) series([ - daemonOptions.init && ((cb) => node.init(daemonOptions.initOptions, cb)), - daemonOptions.start && ((cb) => node.start(daemonOptions.args, cb)) + daemonOptions.init && (cb => node.init(daemonOptions.initOptions, cb)), + daemonOptions.start && (cb => node.start(daemonOptions.args, cb)) ].filter(Boolean), (err) => { if (err) { return callback(err) } diff --git a/src/factory-in-proc.js b/src/factory-in-proc.js index 9889adf7..4f2a4e73 100644 --- a/src/factory-in-proc.js +++ b/src/factory-in-proc.js @@ -1,15 +1,10 @@ 'use strict' -const defaults = require('lodash.defaultsdeep') -const clone = require('lodash.clone') const series = require('async/series') -const path = require('path') -const once = require('once') +const merge = require('merge-options') const tmpDir = require('./utils/tmp-dir') -const repoUtils = require('./utils/repo/nodejs') const InProc = require('./ipfsd-in-proc') const defaultConfig = require('./defaults/config.json') -const defaultOptions = require('./defaults/options.json') /** @ignore @typedef {import("./index").SpawnOptions} SpawnOptions */ @@ -38,7 +33,6 @@ class FactoryInProc { * * @param {string} type - the type of the node * @param {function(Error, string): void} callback - * @returns {void} */ tmpDir (type, callback) { callback(null, tmpDir(true)) @@ -49,7 +43,6 @@ class FactoryInProc { * * @param {Object} [options={}] * @param {function(Error, string): void} callback - * @returns {void} */ version (options, callback) { if (typeof options === 'function') { @@ -58,79 +51,51 @@ class FactoryInProc { } const node = new InProc(options) - node.once('ready', () => { - node.version(callback) - }) + node.version(callback) } /** * Spawn JSIPFS instances * - * @param {SpawnOptions} [opts={}] - various config options and ipfs config parameters + * @param {SpawnOptions} [options={}] - various config options and ipfs config parameters * @param {function(Error, InProc): void} callback - a callback that receives an array with an `ipfs-instance` attached to the node and a `Node` * @returns {void} */ - spawn (opts, callback) { - if (typeof opts === 'function') { - callback = opts - opts = defaultOptions + spawn (options, callback) { + if (typeof options === 'function') { + callback = options + options = {} } - const options = defaults({}, opts, defaultOptions) - options.init = typeof options.init !== 'undefined' - ? options.init - : true - - if (options.disposable) { - options.config = defaults({}, options.config, defaultConfig) - } else { - const nonDisposableConfig = clone(defaultConfig) - options.init = false - options.start = false - - const defaultRepo = path.join( - process.env.HOME || process.env.USERPROFILE || '', - options.isJs ? '.jsipfs' : '.ipfs' - ) - - options.repoPath = options.repoPath || (process.env.IPFS_PATH || defaultRepo) - options.config = defaults({}, options.config, nonDisposableConfig) - } + const daemonOptions = merge({ + exec: this.options.exec, + type: this.options.type, + IpfsApi: this.options.IpfsApi, + disposable: true, + start: options.disposable !== false, + init: options.disposable !== false, + config: defaultConfig + }, options) if (options.defaultAddrs) { - delete options.config.Addresses + delete daemonOptions.config.Addresses } - options.type = this.options.type - options.exec = options.exec || this.options.exec - - if (typeof options.exec !== 'function') { + if (typeof this.options.exec !== 'function') { return callback(new Error(`'type' proc requires 'exec' to be a coderef`)) } - const node = new InProc(options) - const callbackOnce = once((err) => { - if (err) { - return callback(err) - } - callback(null, node) - }) - node.once('error', callbackOnce) + const node = new InProc(daemonOptions) series([ - (cb) => node.once('ready', cb), - (cb) => repoUtils.repoExists(node.path, (err, initialized) => { - if (err) { return cb(err) } - node.initialized = initialized - cb() - }), - (cb) => options.init - ? node.init(cb) - : cb(), - (cb) => options.start - ? node.start(options.args, cb) - : cb() - ], callbackOnce) + daemonOptions.init && (cb => node.init(daemonOptions.initOptions, cb)), + daemonOptions.start && (cb => node.start(daemonOptions.args, cb)) + ].filter(Boolean), + (err) => { + if (err) { return callback(err) } + + callback(null, node) + }) } } diff --git a/src/ipfsd-client.js b/src/ipfsd-client.js index 57f6806f..ad3c388b 100644 --- a/src/ipfsd-client.js +++ b/src/ipfsd-client.js @@ -4,108 +4,88 @@ const request = require('superagent') const IpfsClient = require('ipfs-http-client') const multiaddr = require('multiaddr') -function createApi (apiAddr, gwAddr, IpfsClient) { - let api - if (apiAddr) { - api = IpfsClient(apiAddr) - api.apiHost = multiaddr(apiAddr).nodeAddress().address - api.apiPort = multiaddr(apiAddr).nodeAddress().port - } - - if (api && gwAddr) { - api.gatewayHost = multiaddr(gwAddr).nodeAddress().address - api.gatewayPort = multiaddr(gwAddr).nodeAddress().port - } - - return api -} - /** * Creates an instance of Client. * * @param {*} baseUrl * @param {*} _id * @param {*} initialized - * @param {*} apiAddr - * @param {*} gwAddrs * @param {*} options */ class Client { - constructor (baseUrl, _id, initialized, apiAddr, gwAddrs, options) { - this.options = options || {} + constructor (baseUrl, remoteState, options = {}) { + this.options = options this.baseUrl = baseUrl - this._id = _id - this._apiAddr = multiaddr(apiAddr) - this._gwAddr = multiaddr(gwAddrs) - this.initialized = initialized - this.started = false - this.api = createApi(apiAddr, gwAddrs, this.options.IpfsClient || IpfsClient) - } - - /** - * Get the address of connected IPFS API. - * - * @returns {Multiaddr} - */ - get apiAddr () { - return this._apiAddr + this._id = remoteState._id + this.initialized = remoteState.initialized + this.started = remoteState.started + this.clean = true + this.apiAddr = null + this.gatewayAddr = null + this.path = remoteState.path + this.api = null + + if (this.started) { + this.setApi(remoteState.apiAddr) + this.setGateway(remoteState.gatewayAddr) + } } - /** - * Set the address of connected IPFS API. - * - * @param {Multiaddr} addr - * @returns {void} - */ - set apiAddr (addr) { - this._apiAddr = addr + setApi (addr) { + if (addr) { + this.apiAddr = multiaddr(addr) + this.api = (this.options.IpfsClient || IpfsClient)(addr) + this.api.apiHost = this.apiAddr.nodeAddress().address + this.api.apiPort = this.apiAddr.nodeAddress().port + } } - /** - * Get the address of connected IPFS HTTP Gateway. - * - * @returns {Multiaddr} - */ - get gatewayAddr () { - return this._gwAddr + setGateway (addr) { + if (addr) { + this.gatewayAddr = multiaddr(addr) + this.api.gatewayHost = this.gatewayAddr.nodeAddress().address + this.api.gatewayPort = this.gatewayAddr.nodeAddress().port + } } /** - * Set the address of connected IPFS Gateway. + * Initialize a repo. * - * @param {Multiaddr} addr + * @param {Object} [initOptions={}] + * @param {number} [initOptions.keysize=2048] - The bit size of the identiy key. + * @param {string} [initOptions.directory=IPFS_PATH] - The location of the repo. + * @param {function (Error, Node)} callback * @returns {void} */ - set gatewayAddr (addr) { - this._gwAddr = addr - } + init (initOptions, callback) { + if (typeof initOptions === 'function') { + callback = initOptions + initOptions = null + } - /** - * Initialize a repo. - * - * @param {Object} [initOpts={}] - * @param {number} [initOpts.keysize=2048] - The bit size of the identiy key. - * @param {string} [initOpts.directory=IPFS_PATH] - The location of the repo. - * @param {function (Error, Node)} cb - * @returns {undefined} - */ - init (initOpts, cb) { - if (typeof initOpts === 'function') { - cb = initOpts - initOpts = {} + if (this.initialized && initOptions) { + return callback(new Error(`Repo already initialized can't use different options, ${JSON.stringify(initOptions)}`)) + } + + if (this.initialized) { + this.clean = false + return callback(null, this) } + initOptions = initOptions || {} + // TODO probably needs to change config like the other impl request .post(`${this.baseUrl}/init`) .query({ id: this._id }) - .send({ initOpts }) + .send({ initOptions }) .end((err, res) => { if (err) { - return cb(new Error(err.response ? err.response.body.message : err)) + return callback(new Error(err.response ? err.response.body.message : err)) } + this.clean = false this.initialized = res.body.initialized - cb(null, this) + callback(null, this) }) } @@ -115,13 +95,23 @@ class Client { * automatically when the process is exited. * * @param {function(Error)} cb - * @returns {undefined} + * @returns {void} */ cleanup (cb) { + if (this.clean) { + return cb() + } + request .post(`${this.baseUrl}/cleanup`) .query({ id: this._id }) - .end((err) => { cb(err) }) + .end((err) => { + if (err) { + return cb(err) + } + this.clean = true + cb(null, this) + }) } /** @@ -137,6 +127,10 @@ class Client { flags = [] } + if (this.started) { + return cb(null, this.api) + } + request .post(`${this.baseUrl}/start`) .query({ id: this._id }) @@ -148,10 +142,16 @@ class Client { this.started = true - const apiAddr = res.body.api ? res.body.api.apiAddr : '' - const gatewayAddr = res.body.api ? res.body.api.gatewayAddr : '' + const apiAddr = res.body ? res.body.apiAddr : '' + const gatewayAddr = res.body ? res.body.gatewayAddr : '' - this.api = createApi(apiAddr, gatewayAddr, this.options.IpfsClient || IpfsClient) + if (apiAddr) { + this.setApi(apiAddr) + } + + if (gatewayAddr) { + this.setGateway(gatewayAddr) + } return cb(null, this.api) }) } diff --git a/src/ipfsd-daemon.js b/src/ipfsd-daemon.js index b84d239b..0482a68d 100644 --- a/src/ipfsd-daemon.js +++ b/src/ipfsd-daemon.js @@ -12,19 +12,19 @@ const defaults = require('lodash.defaults') const debug = require('debug') const os = require('os') const hat = require('hat') -const log = debug('ipfsd-ctl:daemon') -const daemonLog = { - info: debug('ipfsd-ctl:daemon:stdout'), - err: debug('ipfsd-ctl:daemon:stderr') -} - const safeParse = require('safe-json-parse/callback') const safeStringify = require('safe-json-stringify') - +const log = debug('ipfsd-ctl:daemon') const tmpDir = require('./utils/tmp-dir') const findIpfsExecutable = require('./utils/find-ipfs-executable') const setConfigValue = require('./utils/set-config-value') const run = require('./utils/run') +const { checkForRunningApi, defaultRepo } = require('./utils/repo/nodejs') + +const daemonLog = { + info: debug('ipfsd-ctl:daemon:stdout'), + err: debug('ipfsd-ctl:daemon:stderr') +} // amount of ms to wait before sigkill const GRACE_PERIOD = 10500 @@ -40,17 +40,16 @@ const NON_DISPOSABLE_GRACE_PERIOD = 10500 * 3 * @param {Typedefs.SpawnOptions} [opts] */ class Daemon { - constructor (opts) { + constructor (opts = { type: 'go' }) { const rootPath = process.env.testpath ? process.env.testpath : __dirname - this.opts = opts || { type: 'go' } - const td = tmpDir(this.opts.type === 'js') - this.path = this.opts.disposable - ? td - : (this.opts.repoPath || td) + this.opts = opts this.disposable = this.opts.disposable + this.path = this.opts.disposable + ? tmpDir(this.opts.type === 'js') + : (this.opts.repoPath || defaultRepo(this.opts.type)) if (process.env.IPFS_EXEC) { log('WARNING: The use of IPFS_EXEC is deprecated, ' + @@ -66,49 +65,29 @@ class Daemon { } const envExec = this.opts.type === 'go' ? process.env.IPFS_GO_EXEC : process.env.IPFS_JS_EXEC this.exec = this.opts.exec || envExec || findIpfsExecutable(this.opts.type, rootPath) + this._env = Object.assign({}, process.env, this.opts.env) + this.bits = this.opts.initOptions ? this.opts.initOptions.bits : null this.subprocess = null + this.started = false this.initialized = fs.existsSync(this.path) this.clean = true - this._apiAddr = null - this._gatewayAddr = null - this._started = false - /** @member {IpfsClient} */ + /** @member {IpfsApi} */ this.api = null - this.bits = this.opts.initOptions ? this.opts.initOptions.bits : null - this._env = Object.assign({}, process.env, this.opts.env) - } - - /** - * Running node api - * @member {String} - */ - get runningNodeApi () { - let api - try { - api = fs.readFileSync(`${this.repoPath}/api`) - } catch (err) { - log(`Unable to open api file: ${err}`) - } - - return api ? api.toString() : null + this.apiAddr = null + this.gatewayAddr = null } - /** - * Address of connected IPFS API. - * - * @member {Multiaddr} - */ - get apiAddr () { - return this._apiAddr + setApi (addr) { + this.apiAddr = multiaddr(addr) + this.api = (this.opts.IpfsClient || IpfsClient)(addr) + this.api.apiHost = this.apiAddr.nodeAddress().address + this.api.apiPort = this.apiAddr.nodeAddress().port } - /** - * Address of connected IPFS HTTP Gateway. - * - * @member {Multiaddr} - */ - get gatewayAddr () { - return this._gatewayAddr + setGateway (addr) { + this.gatewayAddr = multiaddr(addr) + this.api.gatewayHost = this.gatewayAddr.nodeAddress().address + this.api.gatewayPort = this.gatewayAddr.nodeAddress().port } /** @@ -120,15 +99,6 @@ class Daemon { return this.path } - /** - * Is the node started - * - * @member {boolean} - */ - get started () { - return this._started - } - /** * Shell environment variables * @@ -155,7 +125,7 @@ class Daemon { } if (this.initialized && initOptions) { - callback(new Error(`Repo already initialized can't use different options, ${JSON.stringify(initOptions)}`)) + return callback(new Error(`Repo already initialized can't use different options, ${JSON.stringify(initOptions)}`)) } if (this.initialized) { @@ -234,23 +204,11 @@ class Daemon { callback = once(callback) - const setApiAddr = (addr) => { - this._apiAddr = multiaddr(addr) - this.api = (this.opts.IpfsClient || IpfsClient)(addr) - this.api.apiHost = this.apiAddr.nodeAddress().address - this.api.apiPort = this.apiAddr.nodeAddress().port - } - - const setGatewayAddr = (addr) => { - this._gatewayAddr = multiaddr(addr) - this.api.gatewayHost = this.gatewayAddr.nodeAddress().address - this.api.gatewayPort = this.gatewayAddr.nodeAddress().port - } - - const api = this.runningNodeApi + // Check if a daemon is already running + const api = checkForRunningApi(this.path) if (api) { - setApiAddr(api) - this._started = true + this.setApi(api) + this.started = true return callback(null, this.api) } @@ -273,21 +231,19 @@ class Daemon { } output += data - const apiMatch = output.trim().match(/API .*listening on:? (.*)/) const gwMatch = output.trim().match(/Gateway .*listening on:? (.*)/) - if (apiMatch && apiMatch.length > 0) { - setApiAddr(apiMatch[1]) + this.setApi(apiMatch[1]) } if (gwMatch && gwMatch.length > 0) { - setGatewayAddr(gwMatch[1]) + this.setGateway(gwMatch[1]) } if (output.match(/(?:daemon is running|Daemon is ready)/)) { // we're good - this._started = true + this.started = true callback(null, this.api) } } @@ -307,6 +263,7 @@ class Daemon { timeout = null } + // TODO this should call this.api.stop callback = callback || function noop () {} if (!this.subprocess) { @@ -352,7 +309,7 @@ class Daemon { log('killed', subprocess.pid) clearTimeout(grace) this.subprocess = null - this._started = false + this.started = false if (this.disposable) { return this.cleanup(callback) } diff --git a/src/ipfsd-in-proc.js b/src/ipfsd-in-proc.js index 206df25f..d81b15a1 100644 --- a/src/ipfsd-in-proc.js +++ b/src/ipfsd-in-proc.js @@ -1,16 +1,12 @@ 'use strict' const multiaddr = require('multiaddr') +const IpfsApi = require('ipfs-api') const defaultsDeep = require('lodash.defaultsdeep') const defaults = require('lodash.defaults') const waterfall = require('async/waterfall') -const debug = require('debug') -const EventEmitter = require('events') -const repoUtils = require('./utils/repo/nodejs') - -const log = debug('ipfsd-ctl:in-proc') - -let IPFS = null +const tmpDir = require('./utils/tmp-dir') +const { repoExists, removeRepo, checkForRunningApi, defaultRepo } = require('./utils/repo/nodejs') /** * ipfsd for a js-ipfs instance (aka in-process IPFS node) @@ -18,23 +14,23 @@ let IPFS = null * @param {Object} [opts] * @param {Object} [opts.env={}] - Additional environment settings, passed to executing shell. */ -class InProc extends EventEmitter { - constructor (opts) { - super() - this.opts = opts || {} - - IPFS = this.opts.exec +class InProc { + constructor (opts = {}) { + this.opts = opts this.opts.args = this.opts.args || [] - this.path = this.opts.repoPath || repoUtils.createTempRepoPath() + this.path = this.opts.disposable + ? tmpDir(this.opts.type === 'js') + : (this.opts.repoPath || defaultRepo(this.opts.type)) + this.bits = this.opts.initOptions ? this.opts.initOptions.bits : null this.disposable = this.opts.disposable + this.initialized = false + this.started = false this.clean = true - this._apiAddr = null - this._gatewayAddr = null - this._started = false + this.exec = null this.api = null - this.initialized = false - this.bits = this.opts.initOptions ? this.opts.initOptions.bits : null + this.apiAddr = null + this.gatewayAddr = null this.opts.EXPERIMENTAL = defaultsDeep({}, opts.EXPERIMENTAL, { pubsub: false, @@ -63,8 +59,14 @@ class InProc extends EventEmitter { throw new Error(`Unknown argument ${arg}`) } }) + } - this.exec = new IPFS({ + setExec (cb) { + if (this.api !== null) { + return setImmediate(() => cb(null, this)) + } + const IPFS = this.opts.exec + this.api = this.exec = new IPFS({ repo: this.path, init: false, start: false, @@ -73,29 +75,23 @@ class InProc extends EventEmitter { libp2p: this.opts.libp2p, config: this.opts.config }) - - // TODO: should this be wrapped in a process.nextTick(), for context: - // https://nodejs.org/en/docs/guides/event-loop-timers-and-nexttick/#why-use-process-nexttick - this.exec.once('error', err => this.emit('error', err)) - this.exec.once('ready', () => this.emit('ready')) + this.exec.once('error', cb) + this.exec.once('ready', () => cb(null, this)) } - /** - * Get the address of connected IPFS API. - * - * @member {Multiaddr} - */ - get apiAddr () { - return this._apiAddr + setApi (addr) { + this.apiAddr = multiaddr(addr) + this.api = (this.opts.IpfsApi || IpfsApi)(addr) + // TODO find out why we set this + this.api.apiHost = this.apiAddr.nodeAddress().address + this.api.apiPort = this.apiAddr.nodeAddress().port } - /** - * Get the address of connected IPFS HTTP Gateway. - * - * @member {Multiaddr} - */ - get gatewayAddr () { - return this._gatewayAddr + setGateway (addr) { + this.gatewayAddr = multiaddr(addr) + // TODO find out why we set this + this.api.gatewayHost = this.gatewayAddr.nodeAddress().address + this.api.gatewayPort = this.gatewayAddr.nodeAddress().port } /** @@ -107,15 +103,6 @@ class InProc extends EventEmitter { return this.path } - /** - * Is the node started - * - * @member {boolean} - */ - get started () { - return this._started - } - /** * Is the environment * @@ -132,36 +119,37 @@ class InProc extends EventEmitter { * @param {number} [initOptions.bits=2048] - The bit size of the identiy key. * @param {string} [initOptions.directory=IPFS_PATH] - The location of the repo. * @param {string} [initOptions.pass] - The passphrase of the keychain. - * @param {function (Error, InProc)} callback - * @returns {undefined} + * @param {function (Error, InProc): void} callback */ init (initOptions, callback) { if (typeof initOptions === 'function') { callback = initOptions - initOptions = {} + initOptions = null } - const bits = initOptions.keysize ? initOptions.bits : this.bits - // do not just set a default keysize, - // in case we decide to change it at - // the daemon level in the future - if (bits) { - initOptions.bits = bits - log(`initializing with keysize: ${bits}`) - } - this.exec.init(initOptions, (err) => { - if (err) { - return callback(err) + repoExists(this.path, (b, initialized) => { + if (initialized && initOptions) { + return callback(new Error(`Repo already initialized can't use different options, ${JSON.stringify(initOptions)}`)) } - const self = this + if (initialized) { + this.initialized = true + this.clean = false + return callback(null, this) + } + + // Repo not initialized + initOptions = initOptions || {} + waterfall([ - (cb) => this.getConfig(cb), + cb => this.setExec(cb), + (ipfsd, cb) => this.api.init(initOptions, cb), + (init, cb) => this.getConfig(cb), (conf, cb) => this.replaceConfig(defaults({}, this.opts.config, conf), cb) ], (err) => { if (err) { return callback(err) } - self.clean = false - self.initialized = true + this.clean = false + this.initialized = true return callback(null, this) }) }) @@ -180,7 +168,8 @@ class InProc extends EventEmitter { return callback() } - repoUtils.removeRepo(this.path, callback) + this.clean = true + removeRepo(this.path, callback) } /** @@ -196,26 +185,21 @@ class InProc extends EventEmitter { flags = undefined // not used } - this.exec.start((err) => { - if (err) { - return callback(err) - } - - this._started = true - this.api = this.exec - this.exec.config.get((err, conf) => { - if (err) { - return callback(err) - } - - this._apiAddr = conf.Addresses.API - this._gatewayAddr = conf.Addresses.Gateway + // Check if a daemon is already running + const api = checkForRunningApi(this.path) + if (api) { + this.setApi(api) + this.started = true + return callback(null, this.api) + } - this.api.apiHost = multiaddr(conf.Addresses.API).nodeAddress().host - this.api.apiPort = multiaddr(conf.Addresses.API).nodeAddress().port + waterfall([ + cb => this.setExec(cb), + (ipfsd, cb) => this.api.start(cb) + ], (err) => { + if (err) { return callback(err) } - callback(null, this.api) - }) + callback(null, this.api) }) } @@ -228,16 +212,16 @@ class InProc extends EventEmitter { stop (callback) { callback = callback || function noop () {} - if (!this.exec) { + if (!this.api) { return callback() } - this.exec.stop((err) => { + this.api.stop((err) => { if (err) { return callback(err) } - this._started = false + this.started = false if (this.disposable) { return this.cleanup(callback) } @@ -283,7 +267,7 @@ class InProc extends EventEmitter { key = undefined } - this.exec.config.get(key, callback) + this.api.config.get(key, callback) } /** @@ -292,10 +276,9 @@ class InProc extends EventEmitter { * @param {string} key * @param {string} value * @param {function(Error)} callback - * @returns {undefined} */ setConfig (key, value, callback) { - this.exec.config.set(key, value, callback) + this.api.config.set(key, value, callback) } /** @@ -303,20 +286,21 @@ class InProc extends EventEmitter { * * @param {Object} config * @param {function(Error)} callback - * @return {undefined} */ replaceConfig (config, callback) { - this.exec.config.replace(config, callback) + this.api.config.replace(config, callback) } /** * Get the version of ipfs * * @param {function(Error, string)} callback - * @returns {undefined} */ version (callback) { - this.exec.version(callback) + waterfall([ + cb => this.setExec(cb), + (ipfsd, cb) => this.api.version(cb) + ], callback) } } diff --git a/src/utils/repo/browser.js b/src/utils/repo/browser.js index bf57cfad..094b9291 100644 --- a/src/utils/repo/browser.js +++ b/src/utils/repo/browser.js @@ -1,14 +1,9 @@ /* global self */ 'use strict' -const hat = require('hat') const Dexie = require('dexie').default const setImmediate = require('async/setImmediate') -exports.createTempRepoPath = function createTempPathRepo () { - return '/ipfs-' + hat() -} - exports.removeRepo = function removeRepo (repoPath, callback) { Dexie.delete(repoPath) setImmediate(callback) @@ -21,6 +16,14 @@ exports.repoExists = function repoExists (repoPath, cb) { const table = store.table(repoPath) return table .count((cnt) => cb(null, cnt > 0)) - .catch(cb) - }).catch(cb) + .catch(e => cb(null, false)) + }).catch(e => cb(null, false)) +} + +exports.defaultRepo = function (type) { + return 'ipfs' +} + +exports.checkForRunningApi = function (path) { + return null } diff --git a/src/utils/repo/nodejs.js b/src/utils/repo/nodejs.js index 599b88d2..484fd932 100644 --- a/src/utils/repo/nodejs.js +++ b/src/utils/repo/nodejs.js @@ -1,10 +1,12 @@ 'use strict' -const os = require('os') -const path = require('path') -const hat = require('hat') const rimraf = require('rimraf') const fs = require('fs') +const path = require('path') +const os = require('os') +const debug = require('debug') + +const log = debug('ipfsd-ctl') exports.removeRepo = function removeRepo (dir, callback) { fs.access(dir, (err) => { @@ -17,13 +19,27 @@ exports.removeRepo = function removeRepo (dir, callback) { }) } -exports.createTempRepoPath = function createTempRepo () { - return path.join(os.tmpdir(), '/ipfs-test-' + hat()) -} - exports.repoExists = function (repoPath, cb) { fs.access(`${repoPath}/config`, (err) => { if (err) { return cb(null, false) } cb(null, true) }) } + +exports.defaultRepo = function (type) { + path.join( + os.homedir(), + type === 'js' ? '.jsipfs' : '.ipfs' + ) +} + +exports.checkForRunningApi = function (path) { + let api + try { + api = fs.readFileSync(`${path}/api`) + } catch (err) { + log(`Unable to open api file: ${err}`) + } + + return api ? api.toString() : null +} diff --git a/test/endpoint/client.js b/test/endpoint/client.js index 780839ef..5d6fb931 100644 --- a/test/endpoint/client.js +++ b/test/endpoint/client.js @@ -32,14 +32,13 @@ describe('client', () => { it('should handle valid request', (done) => { mock.post('http://localhost:9999/spawn', (req) => { - expect(req.body.options.opt1).to.equal('hello!') + expect(req.body.opt1).to.equal('hello!') return { body: { - id: hat(), - api: { - apiAddr: '/ip4/127.0.0.1/tcp/5001', - gatewayAddr: '/ip4/127.0.0.1/tcp/8080' - } + _id: hat(), + apiAddr: '/ip4/127.0.0.1/tcp/5001', + gatewayAddr: '/ip4/127.0.0.1/tcp/8080', + started: true } } }) @@ -60,7 +59,7 @@ describe('client', () => { mock.clearRoutes() }) - it('should handle valid request', (done) => { + it('should handle invalid request', (done) => { mock.post('http://localhost:9999/spawn', () => { const badReq = boom.badRequest() return { @@ -105,7 +104,8 @@ describe('client', () => { }) }) - describe('handle invalid', () => { + // TODO re-activate after stop re-using client + describe.skip('handle invalid', () => { after(() => { mock.clearRoutes() }) @@ -147,7 +147,8 @@ describe('client', () => { }) }) - describe('handle invalid', () => { + // TODO re-activate after stop re-using client + describe.skip('handle invalid', () => { after(() => { mock.clearRoutes() }) @@ -201,7 +202,8 @@ describe('client', () => { }) }) - describe('handle invalid', () => { + // TODO re-activate after stop re-using client + describe.skip('handle invalid', () => { after(() => { mock.clearRoutes() }) diff --git a/test/endpoint/routes.js b/test/endpoint/routes.js index a51c817c..2532a474 100644 --- a/test/endpoint/routes.js +++ b/test/endpoint/routes.js @@ -1,16 +1,15 @@ /* eslint-env mocha */ 'use strict' +const proxyquire = require('proxyquire') +const multiaddr = require('multiaddr') +const Hapi = require('hapi') const chai = require('chai') const dirtyChai = require('dirty-chai') + const expect = chai.expect chai.use(dirtyChai) -const proxyquire = require('proxyquire') -const multiaddr = require('multiaddr') - -const Hapi = require('hapi') - const routes = proxyquire( '../../src/endpoint/routes', { @@ -71,15 +70,14 @@ describe('routes', () => { it('should return 200', (done) => { server.inject({ method: 'POST', - url: '/spawn', - headers: { 'content-type': 'application/json' } + url: '/spawn' }, (res) => { expect(res.statusCode).to.equal(200) - expect(res.result.id).to.exist() - expect(res.result.api.apiAddr).to.exist() - expect(res.result.api.gatewayAddr).to.exist() + expect(res.result._id).to.exist() + expect(res.result.apiAddr).to.exist() + expect(res.result.gatewayAddr).to.exist() - id = res.result.id + id = res.result._id done() }) }) @@ -89,9 +87,7 @@ describe('routes', () => { it('should return 200', (done) => { server.inject({ method: 'GET', - url: `/api-addr?id=${id}`, - headers: { 'content-type': 'application/json' }, - payload: { id } + url: `/api-addr?id=${id}` }, (res) => { expect(res.statusCode).to.equal(200) expect(res.result.apiAddr).to.exist() @@ -102,8 +98,7 @@ describe('routes', () => { it('should return 400', (done) => { server.inject({ method: 'GET', - url: '/api-addr', - headers: { 'content-type': 'application/json' } + url: '/api-addr' }, (res) => { expect(res.statusCode).to.equal(400) done() @@ -115,9 +110,7 @@ describe('routes', () => { it('should return 200', (done) => { server.inject({ method: 'GET', - url: `/getaway-addr?id=${id}`, - headers: { 'content-type': 'application/json' }, - payload: { id } + url: `/getaway-addr?id=${id}` }, (res) => { expect(res.statusCode).to.equal(200) expect(res.result.getawayAddr).to.exist() @@ -128,8 +121,7 @@ describe('routes', () => { it('should return 400', (done) => { server.inject({ method: 'GET', - url: '/getaway-addr', - headers: { 'content-type': 'application/json' } + url: '/getaway-addr' }, (res) => { expect(res.statusCode).to.equal(400) done() @@ -141,9 +133,7 @@ describe('routes', () => { it('should return 200', (done) => { server.inject({ method: 'POST', - url: `/init?id=${id}`, - headers: { 'content-type': 'application/json' }, - payload: { id } + url: `/init?id=${id}` }, (res) => { expect(res.statusCode).to.equal(200) done() @@ -153,8 +143,7 @@ describe('routes', () => { it('should return 400', (done) => { server.inject({ method: 'POST', - url: '/init', - headers: { 'content-type': 'application/json' } + url: '/init' }, (res) => { expect(res.statusCode).to.equal(400) done() @@ -166,9 +155,7 @@ describe('routes', () => { it('should return 200', (done) => { server.inject({ method: 'POST', - url: `/cleanup?id=${id}`, - headers: { 'content-type': 'application/json' }, - payload: { id } + url: `/cleanup?id=${id}` }, (res) => { expect(res.statusCode).to.equal(200) done() @@ -178,8 +165,7 @@ describe('routes', () => { it('should return 400', (done) => { server.inject({ method: 'POST', - url: '/cleanup', - headers: { 'content-type': 'application/json' } + url: '/cleanup' }, (res) => { expect(res.statusCode).to.equal(400) done() @@ -191,9 +177,7 @@ describe('routes', () => { it('should return 200', (done) => { server.inject({ method: 'POST', - url: `/start?id=${id}`, - headers: { 'content-type': 'application/json' }, - payload: { id } + url: `/start?id=${id}` }, (res) => { expect(res.statusCode).to.equal(200) done() @@ -203,8 +187,7 @@ describe('routes', () => { it('should return 400', (done) => { server.inject({ method: 'POST', - url: '/start', - headers: { 'content-type': 'application/json' } + url: '/start' }, (res) => { expect(res.statusCode).to.equal(400) done() @@ -217,8 +200,7 @@ describe('routes', () => { server.inject({ method: 'POST', url: `/stop?id=${id}`, - headers: { 'content-type': 'application/json' }, - payload: { id } + payload: { timeout: 1000 } }, (res) => { expect(res.statusCode).to.equal(200) done() @@ -229,8 +211,7 @@ describe('routes', () => { server.inject({ method: 'POST', url: `/stop?id=${id}`, - headers: { 'content-type': 'application/json' }, - payload: { id, timeout: 1000 } + payload: { timeout: 1000 } }, (res) => { expect(res.statusCode).to.equal(200) done() @@ -240,8 +221,7 @@ describe('routes', () => { it('should return 400', (done) => { server.inject({ method: 'POST', - url: '/stop', - headers: { 'content-type': 'application/json' } + url: '/stop' }, (res) => { expect(res.statusCode).to.equal(400) done() @@ -254,8 +234,7 @@ describe('routes', () => { server.inject({ method: 'POST', url: `/kill?id=${id}`, - headers: { 'content-type': 'application/json' }, - payload: { id } + payload: { timeout: 1000 } }, (res) => { expect(res.statusCode).to.equal(200) done() @@ -266,8 +245,7 @@ describe('routes', () => { server.inject({ method: 'POST', url: `/kill?id=${id}`, - headers: { 'content-type': 'application/json' }, - payload: { id, timeout: 1000 } + payload: { timeout: 1000 } }, (res) => { expect(res.statusCode).to.equal(200) done() @@ -277,8 +255,7 @@ describe('routes', () => { it('should return 400', (done) => { server.inject({ method: 'POST', - url: '/kill', - headers: { 'content-type': 'application/json' } + url: '/kill' }, (res) => { expect(res.statusCode).to.equal(400) done() @@ -290,9 +267,7 @@ describe('routes', () => { it('should return 200', (done) => { server.inject({ method: 'GET', - url: `/pid?id=${id}`, - headers: { 'content-type': 'application/json' }, - payload: { id } + url: `/pid?id=${id}` }, (res) => { expect(res.statusCode).to.equal(200) done() @@ -302,8 +277,7 @@ describe('routes', () => { it('should return 400', (done) => { server.inject({ method: 'GET', - url: '/pid', - headers: { 'content-type': 'application/json' } + url: '/pid' }, (res) => { expect(res.statusCode).to.equal(400) done() @@ -315,9 +289,7 @@ describe('routes', () => { it('should return 200', (done) => { server.inject({ method: 'GET', - url: `/config?id=${id}`, - headers: { 'content-type': 'application/json' }, - payload: { id } + url: `/config?id=${id}` }, (res) => { expect(res.statusCode).to.equal(200) done() @@ -327,8 +299,7 @@ describe('routes', () => { it('should return 400', (done) => { server.inject({ method: 'GET', - url: '/config', - headers: { 'content-type': 'application/json' } + url: '/config' }, (res) => { expect(res.statusCode).to.equal(400) done() @@ -341,7 +312,6 @@ describe('routes', () => { server.inject({ method: 'PUT', url: `/config?id=${id}`, - headers: { 'content-type': 'application/json' }, payload: { key: 'foo', value: 'bar' } }, (res) => { expect(res.statusCode).to.equal(200) @@ -352,8 +322,7 @@ describe('routes', () => { it('should return 400', (done) => { server.inject({ method: 'PUT', - url: '/config', - headers: { 'content-type': 'application/json' } + url: '/config' }, (res) => { expect(res.statusCode).to.equal(400) done() diff --git a/test/non-disposable.spec.js b/test/non-disposable.spec.js index bc1ee8df..4a874b75 100644 --- a/test/non-disposable.spec.js +++ b/test/non-disposable.spec.js @@ -4,37 +4,37 @@ const chai = require('chai') const dirtyChai = require('dirty-chai') +const waterfall = require('async/waterfall') +const isNode = require('detect-node') const IPFSFactory = require('../src') -const tmpDir = require('../src/utils/tmp-dir') const expect = chai.expect chai.use(dirtyChai) const tests = [ { type: 'go', bits: 1024 }, - { type: 'js', bits: 512 } + { type: 'js', bits: 512 }, + { type: 'proc', exec: require('ipfs'), bits: 512 } ] tests.forEach((fOpts) => { - const config = Object.assign({}, {port: 25000}, fOpts) - describe(`non-disposable ${fOpts.type} daemon`, function () { this.timeout(40000) - let ipfsd = null - let repoPath = null + let daemon = null let id = null before(function (done) { - const f = IPFSFactory.create(fOpts) + // Start a go daemon for attach tests + const f = IPFSFactory.create({ type: 'go' }) - f.spawn({ initOptions: { bits: fOpts.bits } }, (err, _ipfsd) => { + f.spawn({ initOptions: { bits: 1024 } }, (err, _ipfsd) => { if (err) { - done(err) + return done(err) } - ipfsd = _ipfsd - repoPath = ipfsd.path - ipfsd.api.id() + daemon = _ipfsd + + daemon.api.id() .then(data => { id = data.id done() @@ -42,13 +42,16 @@ tests.forEach((fOpts) => { }) }) - after(done => ipfsd.stop(done)) + after(done => daemon.stop(done)) it('should fail when passing initOptions to a initialized repo', function (done) { - const df = IPFSFactory.create(config) + if (fOpts.type === 'proc' && !isNode) { + return this.skip() + } + const df = IPFSFactory.create(fOpts) df.spawn({ initOptions: { bits: fOpts.bits }, - repoPath: repoPath, + repoPath: daemon.path, disposable: false, init: true }, (err, ipfsd) => { @@ -58,80 +61,94 @@ tests.forEach((fOpts) => { }) it('should attach to initialized and running node', function (done) { - const df = IPFSFactory.create(config) + if (fOpts.type === 'proc' && !isNode) { + return this.skip() + } + const df = IPFSFactory.create(fOpts) df.spawn({ - repoPath: ipfsd.repoPath, + repoPath: daemon.path, disposable: false, init: true, start: true }, (err, ipfsd) => { if (err) { - done(err) + return done(err) } ipfsd.api.id() .then(data => { expect(data.id).to.be.eq(id) - ipfsd.stop(done) + done() }) .catch(done) }) }) - it('should attach to running node with manual start', function (done) { - const df = IPFSFactory.create(config) + it.only('should attach to running node with manual start', function (done) { + if (fOpts.type === 'proc' && !isNode) { + return this.skip() + } + const df = IPFSFactory.create(fOpts) df.spawn({ - repoPath: ipfsd.repoPath, - disposable: false - }, (err, daemon) => { + repoPath: daemon.path, + disposable: false, + init: true + }, (err, ipfsd) => { if (err) { - done(err) + return done(err) } - daemon.start((err, api) => { + ipfsd.start((err, api) => { if (err) { - done(err) + return done(err) } expect(api).to.exist() - expect(ipfsd.apiAddr).to.be.eql(daemon.apiAddr) - daemon.stop(done) + expect(daemon.apiAddr).to.be.eql(ipfsd.apiAddr) + done() }) }) }) it('should not init and start', function (done) { - const df = IPFSFactory.create(config) - df.spawn({ - initOptions: { bits: fOpts.bits }, - repoPath: tmpDir(fOpts.type === 'js'), - disposable: false - }, (err, ipfsd) => { + const df = IPFSFactory.create(fOpts) + + waterfall([ + cb => df.tmpDir(fOpts.type === 'js', cb), + (path, cb) => df.spawn({ + initOptions: { bits: fOpts.bits }, + repoPath: path, + disposable: false + }, cb) + ], (err, ipfsd) => { if (err) { - done(err) + return done(err) } - expect(ipfsd.api).to.not.exist() ipfsd.stop(done()) }) }) it('should init and start', function (done) { - const df = IPFSFactory.create(config) - df.spawn({ - initOptions: { bits: fOpts.bits }, - repoPath: tmpDir(fOpts.type === 'js'), - disposable: false, - start: true, - init: true - }, (err, ipfsd) => { + const df = IPFSFactory.create(fOpts) + + waterfall([ + cb => df.tmpDir(fOpts.type === 'js', cb), + (path, cb) => df.spawn({ + initOptions: { bits: fOpts.bits }, + repoPath: path, + disposable: false, + start: true, + init: true + }, cb) + ], (err, ipfsd) => { if (err) { - done(err) + return done(err) } - expect(ipfsd.api).to.exist() + ipfsd.stop(err => { if (err) { - done(err) + return done(err) } ipfsd.cleanup(done) }) @@ -139,50 +156,47 @@ tests.forEach((fOpts) => { }) it('should only init', function (done) { - const df = IPFSFactory.create(config) - df.spawn({ - initOptions: { bits: fOpts.bits }, - repoPath: tmpDir(fOpts.type === 'js'), - disposable: false, - init: true - }, (err, ipfsd) => { + const df = IPFSFactory.create(fOpts) + + waterfall([ + cb => df.tmpDir(fOpts.type === 'js', cb), + (path, cb) => df.spawn({ + initOptions: { bits: fOpts.bits }, + repoPath: path, + disposable: false, + init: true + }, cb) + ], (err, ipfsd) => { if (err) { - done(err) + return done(err) } expect(ipfsd.initialized).to.be.true() expect(ipfsd.started).to.be.false() - ipfsd.stop(err => { - if (err) { - done(err) - } - ipfsd.cleanup(done) - }) + ipfsd.cleanup(done) }) }) it('should only init manualy', function (done) { - const df = IPFSFactory.create(config) - df.spawn({ - initOptions: { bits: fOpts.bits }, - repoPath: tmpDir(fOpts.type === 'js'), - disposable: false, - init: true - }, (err, ipfsd) => { + const df = IPFSFactory.create(fOpts) + + waterfall([ + cb => df.tmpDir(fOpts.type === 'js', cb), + (path, cb) => df.spawn({ + initOptions: { bits: fOpts.bits }, + repoPath: path, + disposable: false + }, cb) + ], (err, ipfsd) => { if (err) { - done(err) + return done(err) } ipfsd.init((err) => { expect(err).to.not.exist() expect(ipfsd.initialized).to.be.true() expect(ipfsd.started).to.be.false() - ipfsd.stop(err => { - if (err) { - done(err) - } - ipfsd.cleanup(done) - }) + ipfsd.cleanup(done) }) }) }) diff --git a/test/spawn-options.spec.js b/test/spawn-options.spec.js index 1841a98f..0f1ce423 100644 --- a/test/spawn-options.spec.js +++ b/test/spawn-options.spec.js @@ -2,20 +2,19 @@ /* eslint max-nested-callbacks: ["error", 8] */ 'use strict' -const series = require('async/series') +const fs = require('fs') +const hat = require('hat') +const isNode = require('detect-node') +const JSIPFS = require('ipfs') const waterfall = require('async/waterfall') +const series = require('async/series') const chai = require('chai') const dirtyChai = require('dirty-chai') +const IPFSFactory = require('../src') + const expect = chai.expect chai.use(dirtyChai) -const fs = require('fs') -const isNode = require('detect-node') -const hat = require('hat') -const IPFSFactory = require('../src') -const JSIPFS = require('ipfs') -const once = require('once') - const tests = [ { type: 'go', bits: 1024 }, { type: 'js', bits: 512 }, @@ -308,35 +307,5 @@ describe('Spawn options', function () { }) }) }) - - describe(`don't callback twice on error`, () => { - if (fOpts.type !== 'proc') { return } - it('spawn with error', (done) => { - this.timeout(20 * 1000) - // `once.strict` should throw if its called more than once - const callback = once.strict((err, ipfsd) => { - if (err) { return done(err) } - - ipfsd.once('error', () => {}) // avoid EventEmitter throws - - // Do an operation, just to make sure we're working - ipfsd.api.id((err) => { - if (err) { - return done(err) - } - - // Do something to make stopping fail - ipfsd.exec._repo.close((err) => { - if (err) { return done(err) } - ipfsd.stop((err) => { - expect(err).to.exist() - done() - }) - }) - }) - }) - f.spawn(callback) - }) - }) })) }) From ea2a58c5a642a32eaf46b88fa4d5426c48ad308f Mon Sep 17 00:00:00 2001 From: Hugo Dias Date: Wed, 14 Nov 2018 11:47:56 +0000 Subject: [PATCH 08/11] fix: remove only from tests --- test/non-disposable.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/non-disposable.spec.js b/test/non-disposable.spec.js index 4a874b75..cb5188c1 100644 --- a/test/non-disposable.spec.js +++ b/test/non-disposable.spec.js @@ -84,7 +84,7 @@ tests.forEach((fOpts) => { }) }) - it.only('should attach to running node with manual start', function (done) { + it('should attach to running node with manual start', function (done) { if (fOpts.type === 'proc' && !isNode) { return this.skip() } From 82abc2d4f420858c2f8eb96f034882c578aa5efa Mon Sep 17 00:00:00 2001 From: Vasco Santos Date: Wed, 14 Nov 2018 15:42:28 +0000 Subject: [PATCH 09/11] chore: Update README.md Co-Authored-By: hugomrdias --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4c512eb6..d7742266 100644 --- a/README.md +++ b/README.md @@ -85,7 +85,7 @@ server.start((err) => { `ipfsd-ctl` can spawn `disposable` and `non-disposable` daemons. - `disposable`- Creates on a temporary repo which will be optionally initialized and started (the default), as well cleaned up on process exit. Great for tests. -- `non-disposable` - Non disposable daemons will by default attach to any nodes running on the default or the supplied repo. Requires the user to initialize and start the node, as well as stop and cleanup after wards. Additionally, a non-disposable will allow you to pass a custom repo using the `repoPath` option, if the `repoPath` is not defined, it will use the default repo for the node type (`$HOME/.ipfs` or `$HOME/.jsipfs`). The `repoPath` parameter is ignored for disposable nodes, as there is a risk of deleting a live repo. +- `non-disposable` - Non disposable daemons will by default attach to any nodes running on the default or the supplied repo. Requires the user to initialize and start the node, as well as stop and cleanup afterwards. Additionally, a non-disposable will allow you to pass a custom repo using the `repoPath` option, if the `repoPath` is not defined, it will use the default repo for the node type (`$HOME/.ipfs` or `$HOME/.jsipfs`). The `repoPath` parameter is ignored for disposable nodes, as there is a risk of deleting a live repo. ## Batteries not included. Bring your own IPFS executable. From f693cd058c60ce87cc0e5fe44da278568c13c006 Mon Sep 17 00:00:00 2001 From: Hugo Dias Date: Wed, 14 Nov 2018 16:02:43 +0000 Subject: [PATCH 10/11] fix: review changes --- src/ipfsd-in-proc.js | 7 +++---- test/non-disposable.spec.js | 1 + 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/ipfsd-in-proc.js b/src/ipfsd-in-proc.js index d81b15a1..f3e7d8e3 100644 --- a/src/ipfsd-in-proc.js +++ b/src/ipfsd-in-proc.js @@ -27,7 +27,6 @@ class InProc { this.initialized = false this.started = false this.clean = true - this.exec = null this.api = null this.apiAddr = null this.gatewayAddr = null @@ -66,7 +65,7 @@ class InProc { return setImmediate(() => cb(null, this)) } const IPFS = this.opts.exec - this.api = this.exec = new IPFS({ + this.api = new IPFS({ repo: this.path, init: false, start: false, @@ -75,8 +74,8 @@ class InProc { libp2p: this.opts.libp2p, config: this.opts.config }) - this.exec.once('error', cb) - this.exec.once('ready', () => cb(null, this)) + this.api.once('error', cb) + this.api.once('ready', () => cb(null, this)) } setApi (addr) { diff --git a/test/non-disposable.spec.js b/test/non-disposable.spec.js index cb5188c1..9e6b8aa9 100644 --- a/test/non-disposable.spec.js +++ b/test/non-disposable.spec.js @@ -192,6 +192,7 @@ tests.forEach((fOpts) => { return done(err) } + expect(ipfsd.initialized).to.be.false() ipfsd.init((err) => { expect(err).to.not.exist() expect(ipfsd.initialized).to.be.true() From 5bb0eb7c32044a8c93b5d12ac4eeb420d880db92 Mon Sep 17 00:00:00 2001 From: Hugo Dias Date: Tue, 4 Dec 2018 19:10:41 +0000 Subject: [PATCH 11/11] chore: fix ipfs-api stuff --- src/ipfsd-in-proc.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ipfsd-in-proc.js b/src/ipfsd-in-proc.js index f3e7d8e3..697a2b89 100644 --- a/src/ipfsd-in-proc.js +++ b/src/ipfsd-in-proc.js @@ -1,7 +1,7 @@ 'use strict' const multiaddr = require('multiaddr') -const IpfsApi = require('ipfs-api') +const IpfsClient = require('ipfs-http-client') const defaultsDeep = require('lodash.defaultsdeep') const defaults = require('lodash.defaults') const waterfall = require('async/waterfall') @@ -80,7 +80,7 @@ class InProc { setApi (addr) { this.apiAddr = multiaddr(addr) - this.api = (this.opts.IpfsApi || IpfsApi)(addr) + this.api = (this.opts.IpfsApi || IpfsClient)(addr) // TODO find out why we set this this.api.apiHost = this.apiAddr.nodeAddress().address this.api.apiPort = this.apiAddr.nodeAddress().port