Skip to content
This repository was archived by the owner on Mar 10, 2020. It is now read-only.

Commit f3081ab

Browse files
authored
test: add tests and docs for ipfs.resolve (#332)
License: MIT Signed-off-by: Alan Shaw <[email protected]>
1 parent 99f74f5 commit f3081ab

File tree

3 files changed

+186
-1
lines changed

3 files changed

+186
-1
lines changed

SPEC/MISCELLANEOUS.md

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
* [ping](#ping)
88
* [pingPullStream](#pingpullstream)
99
* [pingReadableStream](#pingreadablestream)
10+
* [resolve](#resolve)
1011

1112
#### `id`
1213

@@ -242,6 +243,76 @@ stream.on('data', (res) => {
242243

243244
A great source of [examples][] can be found in the tests for this API.
244245

246+
#### `resolve`
247+
248+
> Resolve the value of names to IPFS
249+
250+
There are a number of mutable name protocols that can link among themselves and into IPNS. For example IPNS references can (currently) point at an IPFS object, and DNS links can point at other DNS links, IPNS entries, or IPFS objects. This command accepts any of these identifiers and resolves them to the referenced item.
251+
252+
##### `Go` **WIP**
253+
254+
##### `JavaScript` - ipfs.resolve(name, [options], [callback])
255+
256+
Where:
257+
258+
- `name` (string): The name to resolve
259+
- `options` is an optional object that might include the following properties:
260+
- `recursive` (boolean, default false): Resolve until the result is an IPFS name
261+
262+
`callback` must follow `function (err, res) {}` signature, where `err` is an error if the operation was not successful. `res` is a string, the resolved name.
263+
264+
If no `callback` is passed, a promise is returned.
265+
266+
**Examples:**
267+
268+
Resolve the value of your identity:
269+
270+
```JavaScript
271+
const name = '/ipns/QmatmE9msSfkKxoffpHwNLNKgwZG8eT9Bud6YoPab52vpy'
272+
273+
ipfs.resolve(name, (err, res) => {
274+
if (err) {
275+
throw err
276+
}
277+
console.log(res) // /ipfs/Qmcqtw8FfrVSBaRmbWwHxt3AuySBhJLcvmFYi3Lbc4xnwj
278+
})
279+
```
280+
281+
Resolve the value of another name recursively:
282+
283+
```JavaScript
284+
const name = '/ipns/QmbCMUZw6JFeZ7Wp9jkzbye3Fzp2GGcPgC3nmeUjfVF87n'
285+
286+
// Where:
287+
// /ipns/QmbCMUZw6JFeZ7Wp9jkzbye3Fzp2GGcPgC3nmeUjfVF87n
288+
// ...resolves to:
289+
// /ipns/QmatmE9msSfkKxoffpHwNLNKgwZG8eT9Bud6YoPab52vpy
290+
// ...which in turn resolves to:
291+
// /ipfs/Qmcqtw8FfrVSBaRmbWwHxt3AuySBhJLcvmFYi3Lbc4xnwj
292+
293+
ipfs.resolve(name, { recursive: true }, (err, res) => {
294+
if (err) {
295+
throw err
296+
}
297+
console.log(res) // /ipfs/Qmcqtw8FfrVSBaRmbWwHxt3AuySBhJLcvmFYi3Lbc4xnwj
298+
})
299+
```
300+
301+
Resolve the value of an IPFS path:
302+
303+
```JavaScript
304+
const name = '/ipfs/QmeZy1fGbwgVSrqbfh9fKQrAWgeyRnj7h8fsHS1oy3k99x/beep/boop'
305+
306+
ipfs.resolve(name, (err, res) => {
307+
if (err) {
308+
throw err
309+
}
310+
console.log(res) // /ipfs/QmYRMjyvAiHKN9UTi8Bzt1HUspmSRD8T8DwxfSMzLgBon1
311+
})
312+
```
313+
314+
A great source of [examples][] can be found in the tests for this API.
315+
245316
[examples]: https://github.com/ipfs/interface-ipfs-core/blob/master/js/src/miscellaneous
246317
[rs]: https://www.npmjs.com/package/readable-stream
247318
[ps]: https://www.npmjs.com/package/pull-stream

js/src/miscellaneous/index.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ const tests = {
55
id: require('./id'),
66
version: require('./version'),
77
dns: require('./dns'),
8-
stop: require('./stop')
8+
stop: require('./stop'),
9+
resolve: require('./resolve')
910
}
1011

1112
module.exports = createSuite(tests)

js/src/miscellaneous/resolve.js

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
/* eslint-env mocha */
2+
'use strict'
3+
4+
const isIpfs = require('is-ipfs')
5+
const loadFixture = require('aegir/fixtures')
6+
const hat = require('hat')
7+
const { getDescribe, getIt, expect } = require('../utils/mocha')
8+
9+
module.exports = (createCommon, options) => {
10+
const describe = getDescribe(options)
11+
const it = getIt(options)
12+
const common = createCommon()
13+
14+
describe('.resolve', () => {
15+
let ipfs
16+
17+
before(function (done) {
18+
// CI takes longer to instantiate the daemon, so we need to increase the
19+
// timeout for the before step
20+
this.timeout(60 * 1000)
21+
22+
common.setup((err, factory) => {
23+
expect(err).to.not.exist()
24+
factory.spawnNode((err, node) => {
25+
expect(err).to.not.exist()
26+
ipfs = node
27+
done()
28+
})
29+
})
30+
})
31+
32+
after((done) => {
33+
common.teardown(done)
34+
})
35+
36+
it('should resolve an IPFS hash', (done) => {
37+
const content = loadFixture('js/test/fixtures/testfile.txt', 'interface-ipfs-core')
38+
39+
ipfs.files.add(content, (err, res) => {
40+
expect(err).to.not.exist()
41+
expect(isIpfs.cid(res[0].hash)).to.be.true()
42+
43+
ipfs.resolve(`/ipfs/${res[0].hash}`, (err, path) => {
44+
expect(err).to.not.exist()
45+
expect(path).to.equal(`/ipfs/${res[0].hash}`)
46+
done()
47+
})
48+
})
49+
})
50+
51+
// Test resolve turns /ipfs/QmRootHash/path/to/file into /ipfs/QmFileHash
52+
it('should resolve an IPFS path link', (done) => {
53+
const path = '/path/to/testfile.txt'
54+
const content = loadFixture('js/test/fixtures/testfile.txt', 'interface-ipfs-core')
55+
56+
ipfs.files.add([{ path, content }], { wrapWithDirectory: true }, (err, res) => {
57+
expect(err).to.not.exist()
58+
59+
const rootHash = res.find(r => r.path === '').hash
60+
const fileHash = res.find(r => r.path === path).hash
61+
62+
ipfs.resolve(`/ipfs/${rootHash}${path}`, (err, path) => {
63+
expect(err).to.not.exist()
64+
expect(path).to.equal(`/ipfs/${fileHash}`)
65+
done()
66+
})
67+
})
68+
})
69+
70+
it('should not resolve an IPFS path non-link', (done) => {
71+
const content = { path: { to: { file: hat() } } }
72+
const options = { format: 'dag-cbor', hashAlg: 'sha2-256' }
73+
74+
ipfs.dag.put(content, options, (err, cid) => {
75+
expect(err).to.not.exist()
76+
77+
const path = `/ipfs/${cid.toBaseEncodedString()}/path/to/file`
78+
ipfs.resolve(path, (err, path) => {
79+
expect(err).to.exist()
80+
expect(err.message).to.equal('found non-link at given path')
81+
done()
82+
})
83+
})
84+
})
85+
86+
// Test resolve turns /ipns/domain.com into /ipfs/QmHash
87+
it('should resolve an IPNS DNS link', function (done) {
88+
this.timeout(20 * 1000)
89+
90+
ipfs.resolve('/ipns/ipfs.io', (err, path) => {
91+
expect(err).to.not.exist()
92+
expect(isIpfs.ipfsPath(path)).to.be.true()
93+
done()
94+
})
95+
})
96+
97+
// Test resolve turns /ipns/QmPeerHash into /ipns/domain.com into /ipfs/QmHash
98+
it('should resolve IPNS link recursively', function (done) {
99+
this.timeout(2 * 60 * 1000)
100+
101+
ipfs.name.publish('/ipns/ipfs.io', { resolve: false }, (err, res) => {
102+
expect(err).to.not.exist()
103+
104+
ipfs.resolve(`/ipns/${res.name}`, { recursive: true }, (err, res) => {
105+
expect(err).to.not.exist()
106+
expect(res).to.not.equal('/ipns/ipfs.io')
107+
expect(isIpfs.ipfsPath(res)).to.be.true()
108+
done()
109+
})
110+
})
111+
})
112+
})
113+
}

0 commit comments

Comments
 (0)