diff --git a/README.md b/README.md index 3624e0e..114f060 100644 --- a/README.md +++ b/README.md @@ -158,6 +158,13 @@ It may contain any of the following: - `value` - the value that resulted from the get - `remainderPath` - If it didn't manage to successfully resolve the whole path through or if simply the `localResolve` option was passed. +### `.getMany(cids, callback)` + +> Retrieve several nodes at once + +`callback` should be a function with the signature `function (err, result)`, the result is an array with the nodes corresponding to the CIDs. + + ### `.getStream(cid [, path] [, options])` > Same as get, but returns a source pull-stream that is used to pass the fetched node. diff --git a/src/index.js b/src/index.js index ed5bbb3..9b1ab23 100644 --- a/src/index.js +++ b/src/index.js @@ -166,6 +166,39 @@ class IPLDResolver { return deferred } + /** + * Get multiple nodes back from an array of CIDs. + * + * @param {Array} cids + * @param {function(Error, Array)} callback + * @returns {void} + */ + getMany (cids, callback) { + if (!Array.isArray(cids)) { + return callback(new Error('Argument must be an array of CIDs')) + } + this.bs.getMany(cids, (err, blocks) => { + if (err) { + return callback(err) + } + map(blocks, (block, mapCallback) => { + const resolver = this.resolvers[block.cid.codec] + if (!resolver) { + return mapCallback( + new Error('No resolver found for codec "' + block.cid.codec + '"')) + } + + resolver.util.deserialize(block.data, (err, deserialized) => { + if (err) { + return mapCallback(err) + } + return mapCallback(null, deserialized) + }) + }, + callback) + }) + } + put (node, options, callback) { if (typeof options === 'function') { callback = options diff --git a/test/ipld-all.js b/test/ipld-all.js index a75a9c4..df2393e 100644 --- a/test/ipld-all.js +++ b/test/ipld-all.js @@ -111,4 +111,50 @@ describe('IPLD Resolver for dag-cbor + dag-pb', () => { done() }) }) + + describe('getMany', () => { + it('should return nodes correctly', (done) => { + resolver.getMany([cidCbor, cidPb], (err, result) => { + expect(err).to.not.exist() + expect(result.length).to.equal(2) + expect(result).to.deep.equal([nodeCbor, nodePb]) + done() + }) + }) + + it('should return nodes in input order', (done) => { + resolver.getMany([cidPb, cidCbor], (err, result) => { + expect(err).to.not.exist() + expect(result.length).to.equal(2) + expect(result).to.deep.equal([nodePb, nodeCbor]) + done() + }) + }) + + it('should return error on invalid CID', (done) => { + resolver.getMany([cidCbor, 'invalidcid'], (err, result) => { + expect(err.message).to.equal('Not a valid cid') + expect(result).to.be.undefined() + done() + }) + }) + + it('should return error on non-existent CID', (done) => { + const nonExistentCid = new CID( + 'Qma4hjFTnCasJ8PVp3mZbZK5g2vGDT4LByLJ7m8ciyRFZP') + resolver.getMany([cidCbor, nonExistentCid], (err, result) => { + expect(err.message).to.equal('Not Found') + expect(result).to.be.undefined() + done() + }) + }) + + it('should return error on invalid input', (done) => { + resolver.getMany('astring', (err, result) => { + expect(err.message).to.equal('Argument must be an array of CIDs') + expect(result).to.be.undefined() + done() + }) + }) + }) })