From 3f6f094688d385525d8205237e3e035ee6052ba1 Mon Sep 17 00:00:00 2001 From: David Dias Date: Fri, 20 Jul 2018 11:38:48 +0100 Subject: [PATCH] fix: add support for resolving links by name (#78) License: MIT Signed-off-by: Alan Shaw --- .gitignore | 1 + src/resolver.js | 30 +++++++++++++++++++++++++----- test/resolver.spec.js | 38 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 64 insertions(+), 5 deletions(-) diff --git a/.gitignore b/.gitignore index 6292faf..eca58f9 100644 --- a/.gitignore +++ b/.gitignore @@ -19,6 +19,7 @@ lib-cov # Coverage directory used by tools like istanbul coverage +.nyc_output # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) .grunt diff --git a/src/resolver.js b/src/resolver.js index a07986d..a2b964b 100644 --- a/src/resolver.js +++ b/src/resolver.js @@ -46,15 +46,11 @@ exports.resolve = (binaryBlob, path, callback) => { // for the resolver node.links.forEach((l, i) => { const link = l.toJSON() - values[i] = { + values[i] = values[link.name] = { hash: link.multihash, name: link.name, size: link.size } - // TODO by enabling something to resolve through link name, we are - // applying a transformation (a view) to the data, confirm if this - // is exactly what we want - values[link.name] = link.multihash }) let value = values[split[1]] @@ -74,6 +70,30 @@ exports.resolve = (binaryBlob, path, callback) => { } else if (split[0] === 'Data') { cb(null, { value: node.data, remainderPath: '' }) } else { + // If split[0] is not 'Data' or 'Links' then we might be trying to refer + // to a named link from the Links array. This is because go-ipfs and + // js-ipfs have historically supported the ability to do + // `ipfs dag get CID/a` where a is a named link in a dag-pb. + const values = {} + + node.links.forEach((l, i) => { + const link = l.toJSON() + values[link.name] = { + hash: link.multihash, + name: link.name, + size: link.size + } + }) + + const value = values[split[0]] + + if (value) { + return cb(null, { + value: { '/': value.hash }, + remainderPath: split.slice(1).join('/') + }) + } + cb(new Error('path not available')) } } diff --git a/test/resolver.spec.js b/test/resolver.spec.js index 6329a15..a20133c 100644 --- a/test/resolver.spec.js +++ b/test/resolver.spec.js @@ -146,6 +146,23 @@ describe('IPLD Format resolver (local)', () => { }) }) + it('links by name', (done) => { + resolver.resolve(linksNodeBlob, 'named link', (err, result) => { + expect(err).to.not.exist() + expect(result.value['/']).to.eql(links[1].multihash) + expect(result.remainderPath).to.eql('') + done() + }) + }) + + it('missing link by name', (done) => { + resolver.resolve(linksNodeBlob, 'missing link', (err, result) => { + expect(err).to.exist() + expect(err.message).to.equal('path not available') + done() + }) + }) + it('yield remainderPath if impossible to resolve through (a)', (done) => { resolver.resolve(linksNodeBlob, 'Links/1/Hash/Data', (err, result) => { expect(err).to.not.exist() @@ -166,6 +183,27 @@ describe('IPLD Format resolver (local)', () => { done() }) }) + + it('yield remainderPath if impossible to resolve through named link (a)', (done) => { + resolver.resolve(linksNodeBlob, 'named link/Data', (err, result) => { + expect(err).to.not.exist() + expect(result.value['/']).to.exist() + expect(result.value['/']).to.equal('QmXg9Pp2ytZ14xgmQjYEiHjVjMFXzCVVEcRTWJBmLgR39V') + expect(result.remainderPath).to.equal('Data') + done() + }) + }) + + it('yield remainderPath if impossible to resolve through named link (b)', (done) => { + resolver.resolve(linksNodeBlob, 'named link/Links/0/Hash/Data', (err, result) => { + expect(err).to.not.exist() + expect(result.value['/']) + .to.equal('QmXg9Pp2ytZ14xgmQjYEiHjVjMFXzCVVEcRTWJBmLgR39V') + + expect(result.remainderPath).to.equal('Links/0/Hash/Data') + done() + }) + }) }) it('resolver.tree', (done) => {