UNPKG

ipfsd-ctl

Version:
261 lines (227 loc) 5.74 kB
import { multiaddr } from '@multiformats/multiaddr' import http from 'ipfs-utils/src/http.js' import mergeOptions from 'merge-options' import { logger } from '@libp2p/logger' const merge = mergeOptions.bind({ ignoreUndefined: true }) const daemonLog = { info: logger('ipfsd-ctl:client:stdout'), err: logger('ipfsd-ctl:client:stderr') } /** * @typedef {import('./index').ControllerOptions} ControllerOptions * @typedef {import('@multiformats/multiaddr').Multiaddr} Multiaddr */ /** * Controller for remote nodes * * @class */ class Client { /** * @class * @param {string} baseUrl * @param {import('./types').RemoteState} remoteState * @param {ControllerOptions} options */ constructor (baseUrl, remoteState, options) { this.opts = options this.baseUrl = baseUrl this.id = remoteState.id this.path = remoteState.path this.initialized = remoteState.initialized this.started = remoteState.started this.disposable = remoteState.disposable this.clean = remoteState.clean this.api = null /** @type {import('./types').Subprocess | null} */ this.subprocess = null /** @type {Multiaddr} */ this.apiAddr // eslint-disable-line no-unused-expressions this._setApi(remoteState.apiAddr) this._setGateway(remoteState.gatewayAddr) this._setGrpc(remoteState.grpcAddr) this._createApi() /** @type {import('./types').PeerData | null} */ this._peerId = null } get peer () { if (this._peerId == null) { throw new Error('Not started') } return this._peerId } /** * @private * @param {string} addr */ _setApi (addr) { if (addr) { this.apiAddr = multiaddr(addr) } } /** * @private * @param {string} addr */ _setGateway (addr) { if (addr) { this.gatewayAddr = multiaddr(addr) } } /** * @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.create({ grpc: this.grpcAddr, http: this.apiAddr }) } else if (this.apiAddr) { this.api = this.opts.ipfsHttpModule.create(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 } } } /** * Initialize a repo. * * @param {import('./types').InitOptions} [initOptions] * @returns {Promise<Client>} */ async init (initOptions = {}) { if (this.initialized) { return this } let ipfsOptions = {} if (this.opts.ipfsOptions != null && this.opts.ipfsOptions.init != null && !(typeof this.opts.ipfsOptions.init === 'boolean')) { ipfsOptions = this.opts.ipfsOptions.init } const opts = merge( { emptyRepo: false, profiles: this.opts.test ? ['test'] : [] }, ipfsOptions, typeof initOptions === 'boolean' ? {} : initOptions ) const req = await http.post( `${this.baseUrl}/init`, { searchParams: new URLSearchParams({ id: this.id }), json: opts } ) const rsp = await req.json() this.initialized = rsp.initialized this.clean = false return this } /** * Delete the repo that was being used. * If the node was marked as `disposable` this will be called * automatically when the process is exited. * * @returns {Promise<Client>} */ async cleanup () { if (this.clean) { return this } await http.post( `${this.baseUrl}/cleanup`, { searchParams: new URLSearchParams({ id: this.id }) } ) this.clean = true return this } /** * Start the daemon. * * @returns {Promise<Client>} */ async start () { if (!this.started) { const req = await http.post( `${this.baseUrl}/start`, { searchParams: new URLSearchParams({ id: this.id }) } ) const res = await req.json() this._setApi(res.apiAddr) this._setGateway(res.gatewayAddr) this._setGrpc(res.grpcAddr) this._createApi() this.started = true } // Add `peerId` const id = await this.api.id() this._peerId = id daemonLog.info(id) return this } /** * Stop the daemon */ async stop () { if (!this.started) { return this } await http.post( `${this.baseUrl}/stop`, { searchParams: new URLSearchParams({ id: this.id }) } ) this.started = false if (this.disposable) { await this.cleanup() } return this } /** * Get the pid of the `ipfs daemon` process. * * @returns {Promise<number>} */ async pid () { const req = await http.get( `${this.baseUrl}/pid`, { searchParams: new URLSearchParams({ id: this.id }) } ) const res = await req.json() return res.pid } /** * Get the version of ipfs * * @returns {Promise<string>} */ async version () { const req = await http.get( `${this.baseUrl}/version`, { searchParams: new URLSearchParams({ id: this.id }) } ) const res = await req.json() return res.version } } export default Client