diff --git a/src/core/index.js b/src/core/index.js index 6b0c7f4e21..0290fa7ec8 100644 --- a/src/core/index.js +++ b/src/core/index.js @@ -1,416 +1,52 @@ 'use strict' const BlockService = require('ipfs-block-service') -const Block = require('ipfs-block') const mDAG = require('ipfs-merkle-dag') -const DAGNode = mDAG.DAGNode const DAGService = mDAG.DAGService -const peerId = require('peer-id') -const PeerInfo = require('peer-info') -const multiaddr = require('multiaddr') -const importer = require('ipfs-data-importing').import -const libp2p = require('libp2p-ipfs') const IPFSRepo = require('ipfs-repo') const PeerBook = require('peer-book') -const init = require('./init') const defaultRepo = require('./default-repo') -const utils = require('./utils') + +const load = require('./ipfs/load') +const version = require('./ipfs/version') +const id = require('./ipfs/id') +const repo = require('./ipfs/repo') +const init = require('./ipfs/init') +const bootstrap = require('./ipfs/bootstrap') +const config = require('./ipfs/config') +const block = require('./ipfs/block') +const object = require('./ipfs/object') +const libp2p = require('./ipfs/libp2p') +const files = require('./ipfs/files') exports = module.exports = IPFS -function IPFS (repo) { +function IPFS (repoInstance) { if (!(this instanceof IPFS)) { throw new Error('Must be instantiated with new') } - if (!(repo instanceof IPFSRepo)) { - repo = defaultRepo(repo) - } - - const blockS = new BlockService(repo) - const dagS = new DAGService(blockS) - var peerInfo - var libp2pNode - const peerInfoBook = new PeerBook() - - this.load = (callback) => { - utils.ifRepoExists(repo, (err) => { - if (err) { - throw err - } - - repo.config.get((err, config) => { - if (err) { - throw err - } - const pid = peerId.createFromPrivKey(config.Identity.PrivKey) - peerInfo = new PeerInfo(pid) - config.Addresses.Swarm.forEach((addr) => { - peerInfo.multiaddr.add(multiaddr(addr)) - }) - callback() - }) - }) - } - - this.version = (opts, callback) => { - if (typeof opts === 'function') { - callback = opts - opts = {} - } - - utils.ifRepoExists(repo, (err) => { - if (err) { - return callback(err) - } - - repo.config.get((err, config) => { - if (err) { - return callback(err) - } - - callback(null, config.Version.Current) - }) - }) - } - - this.id = (opts, callback) => { - if (typeof opts === 'function') { - callback = opts - opts = {} - } - if (!peerInfo) { // because of split second warmup - setTimeout(ready, 100) - } else { - ready() - } - function ready () { - callback(null, { - ID: peerInfo.id.toB58String(), - PublicKey: peerInfo.id.pubKey.toString('base64'), - Addresses: peerInfo.multiaddrs.map((ma) => { return ma.toString() }), - AgentVersion: 'js-ipfs', - ProtocolVersion: '9000' - }) - } - } - - this.repo = { - init: (bits, empty, callback) => { - // 1. check if repo already exists - }, - - version: (opts, callback) => { - if (typeof opts === 'function') { - callback = opts - opts = {} - } - - utils.ifRepoExists(repo, (err, res) => { - if (err) { - return callback(err) - } - - repo.version.get(callback) - }) - }, - - gc: function () {}, - - path: () => repo.path - } - - this.init = (opts, callback) => { init(repo, opts, callback) } - - this.bootstrap = { - list: (callback) => { - repo.config.get((err, config) => { - if (err) { return callback(err) } - callback(null, config.Bootstrap) - }) - }, - add: (multiaddr, callback) => { - repo.config.get((err, config) => { - if (err) { return callback(err) } - config.Bootstrap.push(multiaddr) - repo.config.set(config, (err) => { - if (err) { return callback(err) } - - callback() - }) - }) - }, - rm: (multiaddr, callback) => { - repo.config.get((err, config) => { - if (err) { return callback(err) } - config.Bootstrap = config.Bootstrap.filter((mh) => { - if (mh === multiaddr) { - return false - } else { return true } - }) - repo.config.set(config, (err) => { - if (err) { return callback(err) } - callback() - }) - }) - } - } - - this.config = { - // cli only feature built with show and replace - // edit: (callback) => {}, - replace: (config, callback) => { - repo.config.set(config, callback) - }, - show: (callback) => { - repo.config.get((err, config) => { - if (err) { return callback(err) } - callback(null, config) - }) - } - } - - this.block = { - get: (multihash, callback) => { - blockS.getBlock(multihash, callback) - }, - put: (block, callback) => { - blockS.addBlock(block, callback) - }, - del: (multihash, callback) => { - blockS.deleteBlock(multihash, callback) - }, - stat: (multihash, callback) => { - blockS.getBlock(multihash, (err, block) => { - if (err) { - return callback(err) - } - callback(null, { - Key: multihash, - Size: block.data.length - }) - }) - } - } - - this.object = { - new: (template, callback) => { - if (!callback) { - callback = template - } - var node = new DAGNode() - var block = new Block(node.marshal()) - blockS.addBlock(block, function (err) { - if (err) { - return callback(err) - } - callback(null, { - Hash: block.key, - Size: node.size(), - Name: '' - }) - }) - }, - patch: { - appendData: (multihash, data, callback) => { - this.object.get(multihash, (err, obj) => { - if (err) { - return callback(err) - } - obj.data = Buffer.concat([obj.data, data]) - dagS.add(obj, (err) => { - if (err) { - return callback(err) - } - callback(null, obj) - }) - }) - }, - addLink: (multihash, link, callback) => { - this.object.get(multihash, (err, obj) => { - if (err) { - return callback(err) - } - obj.addRawLink(link) - dagS.add(obj, (err) => { - if (err) { - return callback(err) - } - callback(null, obj) - }) - }) - }, - rmLink: (multihash, linkRef, callback) => { - this.object.get(multihash, (err, obj) => { - if (err) { - return callback(err) - } - obj.links = obj.links.filter((link) => { - // filter by name when linkRef is a string, or by hash otherwise - if (typeof linkRef === 'string') { - return link.name !== linkRef - } - return !link.hash.equals(linkRef) - }) - dagS.add(obj, (err) => { - if (err) { - return callback(err) - } - callback(null, obj) - }) - }) - }, - setData: (multihash, data, callback) => { - this.object.get(multihash, (err, obj) => { - if (err) { return callback(err) } - obj.data = data - dagS.add(obj, (err) => { - if (err) { - return callback(err) - } - callback(null, obj) - }) - }) - } - }, - data: (multihash, callback) => { - this.object.get(multihash, (err, obj) => { - if (err) { - return callback(err) - } - callback(null, obj.data) - }) - }, - links: (multihash, callback) => { - this.object.get(multihash, (err, obj) => { - if (err) { - return callback(err) - } - callback(null, obj.links) - }) - }, - get: (multihash, options, callback) => { - if (typeof options === 'function') { - callback = options - options = {} - } - dagS.get(multihash, callback) - }, - put: (dagNode, options, callback) => { - if (typeof options === 'function') { - callback = options - options = {} - } - dagS.add(dagNode, callback) - }, - stat: (multihash, options, callback) => { - if (typeof options === 'function') { - callback = options - options = {} - } - - this.object.get(multihash, (err, obj) => { - if (err) { - return callback(err) - } - var res = { - NumLinks: obj.links.length, - BlockSize: obj.marshal().length, - LinksSize: obj.links.reduce((prev, link) => { - return prev + link.size - }, 0), - DataSize: obj.data.length, - CumulativeSize: '' - } - callback(null, res) - }) - } - } - - const OFFLINE_ERROR = new Error('This command must be run in online mode. Try running \'ipfs daemon\' first.') - - this.libp2p = { - start: (callback) => { - libp2pNode = new libp2p.Node(peerInfo) - libp2pNode.start(() => { - // TODO connect to bootstrap nodes, it will get us more addrs - peerInfo.multiaddrs.forEach((ma) => { - console.log('Swarm listening on', ma.toString()) - }) - callback() - }) - }, - stop: (callback) => { - libp2pNode.swarm.close(callback) - }, - swarm: { - peers: (callback) => { - if (!libp2pNode) { - return callback(OFFLINE_ERROR) - } - - callback(null, peerInfoBook.getAll()) - }, - // all the addrs we know - addrs: (callback) => { - if (!libp2pNode) { - return callback(OFFLINE_ERROR) - } - // TODO - notImpl() - }, - localAddrs: (callback) => { - if (!libp2pNode) { - return callback(OFFLINE_ERROR) - } - - callback(null, peerInfo.multiaddrs) - }, - connect: (ma, callback) => { - if (!libp2pNode) { - return callback(OFFLINE_ERROR) - } - - const idStr = ma.toString().match(/\/ipfs\/(.*)/) - if (!idStr) { - return callback(new Error('invalid multiaddr')) - } - const id = peerId.createFromB58String(idStr[1]) - const peer = new PeerInfo(id) - - ma = ma.toString().replace(/\/ipfs\/(.*)/, '') // FIXME remove this when multiaddr supports ipfs - - peer.multiaddr.add(multiaddr(ma)) - peerInfoBook.put(peer) - - libp2pNode.swarm.dial(peer, (err) => { - callback(err, id) - }) - }, - disconnect: (callback) => { - if (!libp2pNode) { - return callback(OFFLINE_ERROR) - } - - notImpl() - }, - filters: notImpl // TODO - }, - routing: {}, - records: {}, - ping: notImpl - } - - this.files = { - add: (path, options, callback) => { - options.path = path - options.dagService = dagS - importer(options, callback) - } - } -} - -function notImpl () { - throw new Error('Not implemented yet') + if (!(repoInstance instanceof IPFSRepo)) { + repoInstance = defaultRepo(repoInstance) + } + + this._repo = repoInstance + this._blockS = new BlockService(this._repo) + this._dagS = new DAGService(this._blockS) + this._peerInfoBook = new PeerBook() + this._peerInfo = null + this._libp2pNode = null + + this.load = load(this) + this.version = version(this) + this.id = id(this) + this.repo = repo(this) + this.init = init(this) + this.bootstrap = bootstrap(this) + this.config = config(this) + this.block = block(this) + this.object = object(this) + this.libp2p = libp2p(this) + this.files = files(this) } diff --git a/src/core/init.js b/src/core/init.js deleted file mode 100644 index cdcfbf5bc7..0000000000 --- a/src/core/init.js +++ /dev/null @@ -1,86 +0,0 @@ -'use strict' - -const peerId = require('peer-id') -const BlockService = require('ipfs-block-service') -const DagService = require('ipfs-merkle-dag').DAGService -const path = require('path') - -module.exports = (repo, opts, callback) => { - opts = opts || {} - opts.emptyRepo = opts.emptyRepo || false - opts.bits = opts.bits || 2048 - - // Pre-set config values. - var config = require('../init-files/default-config.json') - - // Verify repo does not yet exist. - repo.exists((err, exists) => { - if (err) { - return callback(err) - } - - if (exists === true) { - return callback(new Error('repo already exists')) - } - - generateAndSetKeypair() - }) - - // Generate peer identity keypair + transform to desired format + add to config. - function generateAndSetKeypair () { - var keys = peerId.create({ - bits: opts.bits - }) - config.Identity = { - PeerID: keys.toB58String(), - PrivKey: keys.privKey.toString('base64') - } - - writeVersion() - } - - function writeVersion () { - const version = '3' - - repo.version.set(version, (err) => { - if (err) { return callback(err) } - - writeConfig() - }) - } - - // Write the config to the repo. - function writeConfig () { - repo.config.set(config, (err) => { - if (err) { return callback(err) } - - addDefaultAssets() - }) - } - - // Add the default assets to the repo. - function addDefaultAssets () { - // Skip this step on the browser, or if emptyRepo was supplied. - const isNode = !global.window - if (!isNode || opts.emptyRepo) { - return doneImport(null) - } - - const importer = require('ipfs-data-importing') - const blocks = new BlockService(repo) - const dag = new DagService(blocks) - - const initDocsPath = path.join(__dirname, '../init-files/init-docs') - - importer.import(initDocsPath, dag, { - recursive: true - }, doneImport) - - function doneImport (err, stat) { - if (err) { return callback(err) } - - // All finished! - callback(null, true) - } - } -} diff --git a/src/core/ipfs/block.js b/src/core/ipfs/block.js new file mode 100644 index 0000000000..0add8633ea --- /dev/null +++ b/src/core/ipfs/block.js @@ -0,0 +1,26 @@ +'use strict' + +module.exports = function block (self) { + return { + get: (multihash, callback) => { + self._blockS.getBlock(multihash, callback) + }, + put: (block, callback) => { + self._blockS.addBlock(block, callback) + }, + del: (multihash, callback) => { + self._blockS.deleteBlock(multihash, callback) + }, + stat: (multihash, callback) => { + self._blockS.getBlock(multihash, (err, block) => { + if (err) { + return callback(err) + } + callback(null, { + Key: multihash, + Size: block.data.length + }) + }) + } + } +} diff --git a/src/core/ipfs/bootstrap.js b/src/core/ipfs/bootstrap.js new file mode 100644 index 0000000000..b83eead83e --- /dev/null +++ b/src/core/ipfs/bootstrap.js @@ -0,0 +1,39 @@ +'use strict' + +module.exports = function bootstrap (self) { + return { + list: (callback) => { + self._repo.config.get((err, config) => { + if (err) { + return callback(err) + } + callback(null, config.Bootstrap) + }) + }, + add: (multiaddr, callback) => { + self._repo.config.get((err, config) => { + if (err) { + return callback(err) + } + config.Bootstrap.push(multiaddr) + self._repo.config.set(config, callback) + }) + }, + rm: (multiaddr, callback) => { + self._repo.config.get((err, config) => { + if (err) { + return callback(err) + } + + config.Bootstrap = config.Bootstrap.filter((mh) => { + if (mh === multiaddr) { + return false + } else { + return true + } + }) + self._repo.config.set(config, callback) + }) + } + } +} diff --git a/src/core/ipfs/config.js b/src/core/ipfs/config.js new file mode 100644 index 0000000000..2029d8c7a8 --- /dev/null +++ b/src/core/ipfs/config.js @@ -0,0 +1,14 @@ +'use strict' + +module.exports = function config (self) { + return { + // cli only feature built with show and replace + // edit: (callback) => {}, + replace: (config, callback) => { + self._repo.config.set(config, callback) + }, + show: (callback) => { + self._repo.config.get(callback) + } + } +} diff --git a/src/core/ipfs/files.js b/src/core/ipfs/files.js new file mode 100644 index 0000000000..b3a0cf705a --- /dev/null +++ b/src/core/ipfs/files.js @@ -0,0 +1,13 @@ +'use strict' + +const importer = require('ipfs-data-importing').import + +module.exports = function libp2p (self) { + return { + add: (path, options, callback) => { + options.path = path + options.dagService = self._dagS + importer(options, callback) + } + } +} diff --git a/src/core/ipfs/id.js b/src/core/ipfs/id.js new file mode 100644 index 0000000000..835fc79327 --- /dev/null +++ b/src/core/ipfs/id.js @@ -0,0 +1,25 @@ +'use strict' + +module.exports = function id (self) { + return (opts, callback) => { + if (typeof opts === 'function') { + callback = opts + opts = {} + } + if (!self._peerInfo) { // because of split second warmup + setTimeout(ready, 100) + } else { + ready() + } + + function ready () { + callback(null, { + ID: self._peerInfo.id.toB58String(), + PublicKey: self._peerInfo.id.pubKey.toString('base64'), + Addresses: self._peerInfo.multiaddrs.map((ma) => { return ma.toString() }), + AgentVersion: 'js-ipfs', + ProtocolVersion: '9000' + }) + } + } +} diff --git a/src/core/ipfs/init.js b/src/core/ipfs/init.js new file mode 100644 index 0000000000..1848e348c1 --- /dev/null +++ b/src/core/ipfs/init.js @@ -0,0 +1,88 @@ +'use strict' + +const peerId = require('peer-id') +const BlockService = require('ipfs-block-service') +const DagService = require('ipfs-merkle-dag').DAGService +const path = require('path') + +module.exports = function init (self) { + return (opts, callback) => { + opts = opts || {} + opts.emptyRepo = opts.emptyRepo || false + opts.bits = opts.bits || 2048 + + // Pre-set config values. + var config = require('../../init-files/default-config.json') + + // Verify repo does not yet exist. + self._repo.exists((err, exists) => { + if (err) { + return callback(err) + } + + if (exists === true) { + return callback(new Error('repo already exists')) + } + + generateAndSetKeypair() + }) + + // Generate peer identity keypair + transform to desired format + add to config. + function generateAndSetKeypair () { + var keys = peerId.create({ + bits: opts.bits + }) + config.Identity = { + PeerID: keys.toB58String(), + PrivKey: keys.privKey.toString('base64') + } + + writeVersion() + } + + function writeVersion () { + const version = '3' + + self._repo.version.set(version, (err) => { + if (err) { return callback(err) } + + writeConfig() + }) + } + + // Write the config to the repo. + function writeConfig () { + self._repo.config.set(config, (err) => { + if (err) { return callback(err) } + + addDefaultAssets() + }) + } + + // Add the default assets to the repo. + function addDefaultAssets () { + // Skip this step on the browser, or if emptyRepo was supplied. + const isNode = !global.window + if (!isNode || opts.emptyRepo) { + return doneImport(null) + } + + const importer = require('ipfs-data-importing') + const blocks = new BlockService(self._repo) + const dag = new DagService(blocks) + + const initDocsPath = path.join(__dirname, '../../init-files/init-docs') + + importer.import(initDocsPath, dag, { + recursive: true + }, doneImport) + + function doneImport (err, stat) { + if (err) { return callback(err) } + + // All finished! + callback(null, true) + } + } + } +} diff --git a/src/core/ipfs/libp2p.js b/src/core/ipfs/libp2p.js new file mode 100644 index 0000000000..7548438397 --- /dev/null +++ b/src/core/ipfs/libp2p.js @@ -0,0 +1,87 @@ +'use strict' + +const peerId = require('peer-id') +const PeerInfo = require('peer-info') +const multiaddr = require('multiaddr') +const Libp2pNode = require('libp2p-ipfs').Node + +module.exports = function libp2p (self) { + const OFFLINE_ERROR = new Error('This command must be run in online mode. Try running \'ipfs daemon\' first.') + + return { + start: (callback) => { + self._libp2pNode = new Libp2pNode(self._peerInfo) + self._libp2pNode.start(() => { + // TODO connect to bootstrap nodes, it will get us more addrs + self._peerInfo.multiaddrs.forEach((ma) => { + console.log('Swarm listening on', ma.toString()) + }) + callback() + }) + }, + stop: (callback) => { + self._libp2pNode.swarm.close(callback) + }, + swarm: { + peers: (callback) => { + if (!self._libp2pNode) { + return callback(OFFLINE_ERROR) + } + + callback(null, self._peerInfoBook.getAll()) + }, + // all the addrs we know + addrs: (callback) => { + if (!self._libp2pNode) { + return callback(OFFLINE_ERROR) + } + // TODO + throw new Error('Not implemented') + }, + localAddrs: (callback) => { + if (!self._libp2pNode) { + return callback(OFFLINE_ERROR) + } + + callback(null, self._peerInfo.multiaddrs) + }, + connect: (ma, callback) => { + if (!self._libp2pNode) { + return callback(OFFLINE_ERROR) + } + + const idStr = ma.toString().match(/\/ipfs\/(.*)/) + if (!idStr) { + return callback(new Error('invalid multiaddr')) + } + const id = peerId.createFromB58String(idStr[1]) + const peer = new PeerInfo(id) + + ma = ma.toString().replace(/\/ipfs\/(.*)/, '') // FIXME remove this when multiaddr supports ipfs + + peer.multiaddr.add(multiaddr(ma)) + self._peerInfoBook.put(peer) + + self._libp2pNode.swarm.dial(peer, (err) => { + callback(err, id) + }) + }, + disconnect: (callback) => { + if (!self._libp2pNode) { + return callback(OFFLINE_ERROR) + } + + throw new Error('Not implemented') + }, + filters: () => { + // TODO + throw new Error('Not implemented') + } + }, + routing: {}, + records: {}, + ping: () => { + throw new Error('Not implemented') + } + } +} diff --git a/src/core/ipfs/load.js b/src/core/ipfs/load.js new file mode 100644 index 0000000000..dc9cc0a506 --- /dev/null +++ b/src/core/ipfs/load.js @@ -0,0 +1,29 @@ +'use strict' + +const peerId = require('peer-id') +const PeerInfo = require('peer-info') +const multiaddr = require('multiaddr') + +const utils = require('../utils') + +module.exports = function load (self) { + return (callback) => { + utils.ifRepoExists(self._repo, (err) => { + if (err) { + throw err + } + + self._repo.config.get((err, config) => { + if (err) { + throw err + } + const pid = peerId.createFromPrivKey(config.Identity.PrivKey) + self._peerInfo = new PeerInfo(pid) + config.Addresses.Swarm.forEach((addr) => { + self._peerInfo.multiaddr.add(multiaddr(addr)) + }) + callback() + }) + }) + } +} diff --git a/src/core/ipfs/object.js b/src/core/ipfs/object.js new file mode 100644 index 0000000000..0db31c4158 --- /dev/null +++ b/src/core/ipfs/object.js @@ -0,0 +1,141 @@ +'use strict' + +const Block = require('ipfs-block') +const mDAG = require('ipfs-merkle-dag') +const DAGNode = mDAG.DAGNode + +module.exports = function object (self) { + return { + new: (template, callback) => { + if (!callback) { + callback = template + } + var node = new DAGNode() + var block = new Block(node.marshal()) + self._blockS.addBlock(block, function (err) { + if (err) { + return callback(err) + } + callback(null, { + Hash: block.key, + Size: node.size(), + Name: '' + }) + }) + }, + patch: { + appendData: (multihash, data, callback) => { + self.object.get(multihash, (err, obj) => { + if (err) { + return callback(err) + } + obj.data = Buffer.concat([obj.data, data]) + self._dagS.add(obj, (err) => { + if (err) { + return callback(err) + } + callback(null, obj) + }) + }) + }, + addLink: (multihash, link, callback) => { + self.object.get(multihash, (err, obj) => { + if (err) { + return callback(err) + } + obj.addRawLink(link) + self._dagS.add(obj, (err) => { + if (err) { + return callback(err) + } + callback(null, obj) + }) + }) + }, + rmLink: (multihash, linkRef, callback) => { + self.object.get(multihash, (err, obj) => { + if (err) { + return callback(err) + } + obj.links = obj.links.filter((link) => { + // filter by name when linkRef is a string, or by hash otherwise + if (typeof linkRef === 'string') { + return link.name !== linkRef + } + return !link.hash.equals(linkRef) + }) + self._dagS.add(obj, (err) => { + if (err) { + return callback(err) + } + callback(null, obj) + }) + }) + }, + setData: (multihash, data, callback) => { + self.object.get(multihash, (err, obj) => { + if (err) { return callback(err) } + obj.data = data + self._dagS.add(obj, (err) => { + if (err) { + return callback(err) + } + callback(null, obj) + }) + }) + } + }, + data: (multihash, callback) => { + self.object.get(multihash, (err, obj) => { + if (err) { + return callback(err) + } + callback(null, obj.data) + }) + }, + links: (multihash, callback) => { + self.object.get(multihash, (err, obj) => { + if (err) { + return callback(err) + } + callback(null, obj.links) + }) + }, + get: (multihash, options, callback) => { + if (typeof options === 'function') { + callback = options + options = {} + } + self._dagS.get(multihash, callback) + }, + put: (dagNode, options, callback) => { + if (typeof options === 'function') { + callback = options + options = {} + } + self._dagS.add(dagNode, callback) + }, + stat: (multihash, options, callback) => { + if (typeof options === 'function') { + callback = options + options = {} + } + + self.object.get(multihash, (err, obj) => { + if (err) { + return callback(err) + } + var res = { + NumLinks: obj.links.length, + BlockSize: obj.marshal().length, + LinksSize: obj.links.reduce((prev, link) => { + return prev + link.size + }, 0), + DataSize: obj.data.length, + CumulativeSize: '' + } + callback(null, res) + }) + } + } +} diff --git a/src/core/ipfs/repo.js b/src/core/ipfs/repo.js new file mode 100644 index 0000000000..ea635a5c9c --- /dev/null +++ b/src/core/ipfs/repo.js @@ -0,0 +1,30 @@ +'use strict' + +const utils = require('../utils') + +module.exports = function repo (self) { + return { + init: (bits, empty, callback) => { + // 1. check if repo already exists + }, + + version: (opts, callback) => { + if (typeof opts === 'function') { + callback = opts + opts = {} + } + + utils.ifRepoExists(self._repo, (err, res) => { + if (err) { + return callback(err) + } + + self._repo.version.get(callback) + }) + }, + + gc: function () {}, + + path: () => self._repo.path + } +} diff --git a/src/core/ipfs/version.js b/src/core/ipfs/version.js new file mode 100644 index 0000000000..4d8340c831 --- /dev/null +++ b/src/core/ipfs/version.js @@ -0,0 +1,26 @@ +'use strict' + +const utils = require('../utils') + +module.exports = function version (self) { + return (opts, callback) => { + if (typeof opts === 'function') { + callback = opts + opts = {} + } + + utils.ifRepoExists(self._repo, (err) => { + if (err) { + return callback(err) + } + + self._repo.config.get((err, config) => { + if (err) { + return callback(err) + } + + callback(null, config.Version.Current) + }) + }) + } +}