diff --git a/src/dag/index.js b/src/dag/index.js index bb6b1333c..36da97643 100644 --- a/src/dag/index.js +++ b/src/dag/index.js @@ -7,6 +7,7 @@ module.exports = (arg) => { return { get: require('./get')(send), - put: require('./put')(send) + put: require('./put')(send), + tree: require('./tree')(send) } } diff --git a/src/dag/tree.js b/src/dag/tree.js new file mode 100644 index 000000000..fb2f9e894 --- /dev/null +++ b/src/dag/tree.js @@ -0,0 +1,37 @@ +'use strict' +const promisify = require('promisify-es6') +const block = require('../block') + +const DAGFormats = { + 'dag-cbor': require('ipld-dag-cbor'), + 'dag-pb': require('ipld-dag-pb') +} + +module.exports = (send) => { + return promisify((cid, path, options, callback) => { + if (typeof path === 'function') { + callback = path + path = undefined + } + + if (typeof options === 'function') { + callback = options + options = {} + } + + options = options || {} + path = path || '' + + // FIXME: handle case when options.recursive is true + block(send).get(cid, options, (err, ipfsBlock) => { + if (err) return callback(err) + + const codec = ipfsBlock.cid.codec + if (codec in DAGFormats) { + DAGFormats[codec].resolver.tree(ipfsBlock.data, callback) + } else { + callback(new Error(`codec ${codec} is not valid`)) + } + }) + }) +} diff --git a/test/dag.spec.js b/test/dag.spec.js new file mode 100644 index 000000000..643cc76bc --- /dev/null +++ b/test/dag.spec.js @@ -0,0 +1,89 @@ +/* eslint-env mocha */ +/* eslint max-nested-callbacks: ["error", 8] */ +'use strict' + +const CID = require('cids') +const chai = require('chai') +const dirtyChai = require('dirty-chai') +const expect = chai.expect +chai.use(dirtyChai) + +const IPFSApi = require('../src') +const f = require('./utils/factory') + +describe('.dag', function () { + this.timeout(50 * 1000) // slow CI + + let ipfs + let ipfsd + + const obj = { + a: 1, + b: [1, 2, 3], + c: { + ca: [5, 6, 7], + cb: 'foo' + } + } + + before((done) => { + f.spawn({ initOptions: { bits: 1024 } }, (err, _ipfsd) => { + expect(err).to.not.exist() + ipfsd = _ipfsd + ipfs = IPFSApi(_ipfsd.apiAddr) + done() + }) + }) + + after((done) => { + if (!ipfsd) return done() + ipfsd.stop(done) + }) + + describe('.dag.tree', () => { + it('should return all the paths', (done) => { + const expectedPaths = [ + 'a', 'b', 'b/0', 'b/1', 'b/2', 'c', 'c/ca', + 'c/ca/0', 'c/ca/1', 'c/ca/2', 'c/cb' + ] + ipfs.dag.put(obj, (err, cid) => { + expect(err).to.not.exist() + ipfs.dag.tree(cid, (err, paths) => { + expect(err).to.not.exist() + expect(paths).deep.equal(expectedPaths) + done() + }) + }) + }) + + it('should return error when codec for cid is invalid', (done) => { + let cid = new CID('zdpuArMWc9Ee3B7zUDucRjvA1bDgYpWt8rpUXXjY3tbmBw619') + cid.codec = 'invalid-codec' + ipfs.dag.tree(cid, (err, paths) => { + expect(err).to.exist() + done() + }) + }) + }) + + it('.dag.put', (done) => { + let expectedCidStr = 'zdpuArMWc9Ee3B7zUDucRjvA1bDgYpWt8rpUXXjY3tbmBw619' + ipfs.dag.put(obj, (err, cid) => { + expect(err).to.not.exist() + let cidStr = cid.toBaseEncodedString() + expect(cidStr).to.be.equal(expectedCidStr) + done() + }) + }) + + it('.dag.get', (done) => { + ipfs.dag.put(obj, (err, cid) => { + expect(err).to.not.exist() + ipfs.dag.get(cid, (err, data) => { + expect(err).to.not.exist() + expect(data.value).deep.equal(obj) + done() + }) + }) + }) +})