diff --git a/package.json b/package.json index 591719ff..0d5c6ad3 100644 --- a/package.json +++ b/package.json @@ -76,6 +76,7 @@ "peerDependencies": { "go-ipfs": "*", "ipfs": "*", + "ipfs-client": "*", "ipfs-http-client": "*" }, "repository": { diff --git a/src/config.js b/src/config.js index b5c9aa31..da3fd550 100644 --- a/src/config.js +++ b/src/config.js @@ -29,7 +29,8 @@ module.exports = ({ type }) => { Addresses: { Swarm: swarm, API: '/ip4/127.0.0.1/tcp/0', - Gateway: '/ip4/127.0.0.1/tcp/0' + Gateway: '/ip4/127.0.0.1/tcp/0', + RPC: '/ip4/127.0.0.1/tcp/0' } } } diff --git a/src/endpoint/routes.js b/src/endpoint/routes.js index cd909c51..f12d54f3 100644 --- a/src/endpoint/routes.js +++ b/src/endpoint/routes.js @@ -75,6 +75,7 @@ module.exports = (server, createFactory) => { id: id, apiAddr: nodes[id].apiAddr ? nodes[id].apiAddr.toString() : '', gatewayAddr: nodes[id].gatewayAddr ? nodes[id].gatewayAddr.toString() : '', + grpcAddr: nodes[id].grpcAddr ? nodes[id].grpcAddr.toString() : '', initialized: nodes[id].initialized, started: nodes[id].started, disposable: nodes[id].disposable, @@ -125,7 +126,8 @@ module.exports = (server, createFactory) => { return { apiAddr: nodes[id].apiAddr ? nodes[id].apiAddr.toString() : '', - gatewayAddr: nodes[id].gatewayAddr ? nodes[id].gatewayAddr.toString() : '' + gatewayAddr: nodes[id].gatewayAddr ? nodes[id].gatewayAddr.toString() : '', + grpcAddr: nodes[id].grpcAddr ? nodes[id].grpcAddr.toString() : '' } } catch (err) { badRequest(err) diff --git a/src/ipfsd-client.js b/src/ipfsd-client.js index 1e94762a..40a14dc1 100644 --- a/src/ipfsd-client.js +++ b/src/ipfsd-client.js @@ -37,6 +37,8 @@ class Client { this._setApi(remoteState.apiAddr) this._setGateway(remoteState.gatewayAddr) + this._setGrpc(remoteState.grpcAddr) + this._createApi() } /** @@ -46,9 +48,6 @@ class Client { _setApi (addr) { if (addr) { this.apiAddr = multiaddr(addr) - this.api = this.opts.ipfsHttpModule(addr) - this.api.apiHost = this.apiAddr.nodeAddress().address - this.api.apiPort = this.apiAddr.nodeAddress().port } } @@ -59,8 +58,47 @@ class Client { _setGateway (addr) { if (addr) { this.gatewayAddr = multiaddr(addr) - this.api.gatewayHost = this.gatewayAddr.nodeAddress().address - this.api.gatewayPort = this.gatewayAddr.nodeAddress().port + } + } + + /** + * @private + * @param {string} addr + */ + _setGrpc (addr) { + if (addr) { + this.grpcAddr = multiaddr(addr) + } + } + + /** + * @private + */ + _createApi () { + if (this.opts.ipfsClientModule && this.grpcAddr && this.apiAddr) { + this.api = this.opts.ipfsClientModule({ + grpc: this.grpcAddr, + http: this.apiAddr + }) + } else if (this.apiAddr) { + this.api = this.opts.ipfsHttpModule(this.apiAddr) + } + + if (this.api) { + if (this.apiAddr) { + this.api.apiHost = this.apiAddr.nodeAddress().address + this.api.apiPort = this.apiAddr.nodeAddress().port + } + + if (this.gatewayAddr) { + this.api.gatewayHost = this.gatewayAddr.nodeAddress().address + this.api.gatewayPort = this.gatewayAddr.nodeAddress().port + } + + if (this.grpcAddr) { + this.api.grpcHost = this.grpcAddr.nodeAddress().address + this.api.grpcPort = this.grpcAddr.nodeAddress().port + } } } @@ -133,6 +171,8 @@ class Client { this._setApi(res.apiAddr) this._setGateway(res.gatewayAddr) + this._setGrpc(res.grpcAddr) + this._createApi() this.started = true } diff --git a/src/ipfsd-daemon.js b/src/ipfsd-daemon.js index 79347468..37ad558e 100644 --- a/src/ipfsd-daemon.js +++ b/src/ipfsd-daemon.js @@ -48,6 +48,7 @@ class Daemon { this.started = false this.clean = true this.apiAddr = null + this.grpcAddr = null this.gatewayAddr = null this.api = null } @@ -58,9 +59,14 @@ class Daemon { */ _setApi (addr) { this.apiAddr = multiaddr(addr) - this.api = this.opts.ipfsHttpModule(addr) - this.api.apiHost = this.apiAddr.nodeAddress().address - this.api.apiPort = this.apiAddr.nodeAddress().port + } + + /** + * @private + * @param {string} addr + */ + _setGrpc (addr) { + this.grpcAddr = multiaddr(addr) } /** @@ -69,8 +75,36 @@ class Daemon { */ _setGateway (addr) { this.gatewayAddr = multiaddr(addr) - this.api.gatewayHost = this.gatewayAddr.nodeAddress().address - this.api.gatewayPort = this.gatewayAddr.nodeAddress().port + } + + _createApi () { + if (this.opts.ipfsClientModule && this.grpcAddr) { + this.api = this.opts.ipfsClientModule({ + grpc: this.grpcAddr, + http: this.apiAddr + }) + } else if (this.apiAddr) { + this.api = this.opts.ipfsHttpModule(this.apiAddr) + } + + if (!this.api) { + throw new Error(`Could not create API from http '${this.apiAddr}' and/or gRPC '${this.grpcAddr}'`) + } + + if (this.apiAddr) { + this.api.apiHost = this.apiAddr.nodeAddress().address + this.api.apiPort = this.apiAddr.nodeAddress().port + } + + if (this.gatewayAddr) { + this.api.gatewayHost = this.gatewayAddr.nodeAddress().address + this.api.gatewayPort = this.gatewayAddr.nodeAddress().port + } + + if (this.grpcAddr) { + this.api.grpcHost = this.grpcAddr.nodeAddress().address + this.api.grpcPort = this.grpcAddr.nodeAddress().port + } } /** @@ -150,6 +184,7 @@ class Daemon { if (api) { this._setApi(api) + this._createApi() } else if (!this.exec) { throw new Error('No executable specified') } else { @@ -168,6 +203,7 @@ class Daemon { output += data.toString() const apiMatch = output.trim().match(/API .*listening on:? (.*)/) const gwMatch = output.trim().match(/Gateway .*listening on:? (.*)/) + const grpcMatch = output.trim().match(/gRPC .*listening on:? (.*)/) if (apiMatch && apiMatch.length > 0) { this._setApi(apiMatch[1]) @@ -177,8 +213,13 @@ class Daemon { this._setGateway(gwMatch[1]) } + if (grpcMatch && grpcMatch.length > 0) { + this._setGrpc(grpcMatch[1]) + } + if (output.match(/(?:daemon is running|Daemon is ready)/)) { // we're good + this._createApi() this.started = true this.subprocess.stdout.off('data', readyHandler) resolve(this.api) diff --git a/test/create.spec.js b/test/create.spec.js index 1c76189e..0a8fe31d 100644 --- a/test/create.spec.js +++ b/test/create.spec.js @@ -56,6 +56,57 @@ describe('`createController` should return the correct class', () => { expect(f).to.be.instanceOf(Client) }) + + it.skip('should use ipfs-client if passed', async () => { + let clientCreated = false + let httpCreated = false + + await createController({ + type: 'js', + disposable: false, + ipfsModule: require('ipfs'), + ipfsClientModule: (opts) => { + clientCreated = true + + return require('ipfs-client')(opts) + }, + ipfsHttpModule: (opts) => { + httpCreated = true + + return require('ipfs-http-client')(opts) + }, + ipfsBin: pathJoin(__dirname, '../node_modules/ipfs/src/cli/bin.js') + }) + + expect(clientCreated).to.be.true() + expect(httpCreated).to.be.false() + }) + + it.skip('should use ipfs-client for remote if passed', async () => { + let clientCreated = false + let httpCreated = false + + const f = await createController({ + remote: true, + disposable: false, + ipfsModule: require('ipfs'), + ipfsClientModule: (opts) => { + clientCreated = true + + return require('ipfs-client')(opts) + }, + ipfsHttpModule: (opts) => { + httpCreated = true + + return require('ipfs-http-client')(opts) + }, + ipfsBin: pathJoin(__dirname, '../node_modules/ipfs/src/cli/bin.js') + }) + + expect(f).to.be.instanceOf(Client) + expect(clientCreated).to.be.true() + expect(httpCreated).to.be.false() + }) }) const defaultOps = {