This repository has been archived by the owner on Feb 12, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add support for ipns and recursive to ipfs resolve
This PR add IPNS support to resolve, makes the recursive option true by default and reworks the tests. Jsdocs were add to the resolve methods. Two interface-core config profile tests needed to be skipped because js-ipfs doesn't support them yet needs: ipfs-inactive/interface-js-ipfs-core#504
- Loading branch information
1 parent
4661f83
commit 8b55e6b
Showing
6 changed files
with
62 additions
and
144 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,64 +1,82 @@ | ||
'use strict' | ||
|
||
const promisify = require('promisify-es6') | ||
const isIpfs = require('is-ipfs') | ||
const setImmediate = require('async/setImmediate') | ||
const CID = require('cids') | ||
const nodeify = require('promise-nodeify') | ||
const { cidToString } = require('../../utils/cid') | ||
|
||
module.exports = (self) => { | ||
return promisify(async (name, opts, cb) => { | ||
if (typeof opts === 'function') { | ||
cb = opts | ||
opts = {} | ||
} | ||
/** | ||
* @typedef { import("../index") } IPFS | ||
*/ | ||
|
||
opts = opts || {} | ||
/** | ||
* @typedef {Object} ResolveOptions | ||
* @prop {string} cidBase - Multibase codec name the CID in the resolved path will be encoded with | ||
* @prop {boolean} [recursive=true] - Resolve until the result is an IPFS name | ||
* | ||
*/ | ||
|
||
/** @typedef {(err: Error, path: string) => void} ResolveCallback */ | ||
|
||
/** | ||
* @callback ResolveWrapper - This wrapper adds support for callbacks and promises | ||
* @param {string} name - Path to resolve | ||
* @param {ResolveOptions} opts - Options for resolve | ||
* @param {ResolveCallback} [cb] - Optional callback function | ||
* @returns {Promise<string> | void} - When callback is provided nothing is returned | ||
*/ | ||
|
||
/** | ||
* IPFS Resolve factory | ||
* | ||
* @param {IPFS} ipfs | ||
* @returns {ResolveWrapper} | ||
*/ | ||
module.exports = (ipfs) => { | ||
/** | ||
* IPFS Resolve - Resolve the value of names to IPFS | ||
* | ||
* @param {String} name | ||
* @param {ResolveOptions} [opts={}] | ||
* @returns {Promise<string>} | ||
*/ | ||
const resolve = async (name, opts = {}) => { | ||
if (!isIpfs.path(name)) { | ||
return setImmediate(() => cb(new Error('invalid argument ' + name))) | ||
throw new Error('invalid argument ' + name) | ||
} | ||
|
||
// TODO remove this and update subsequent code when IPNS is implemented | ||
if (!isIpfs.ipfsPath(name)) { | ||
return setImmediate(() => cb(new Error('resolve non-IPFS names is not implemented'))) | ||
if (isIpfs.ipnsPath(name)) { | ||
name = await ipfs.name.resolve(name, opts) | ||
} | ||
|
||
const split = name.split('/') // ['', 'ipfs', 'hash', ...path] | ||
const cid = new CID(split[2]) | ||
const [, , hash, ...rest] = name.split('/') // ['', 'ipfs', 'hash', ...path] | ||
const cid = new CID(hash) | ||
|
||
if (split.length === 3) { | ||
return setImmediate(() => cb(null, `/ipfs/${cidToString(cid, { base: opts.cidBase })}`)) | ||
// nothing to resolve return the input | ||
if (rest.length === 0) { | ||
return `/ipfs/${cidToString(cid, { base: opts.cidBase })}` | ||
} | ||
|
||
const path = split.slice(3).join('/') | ||
|
||
const results = self._ipld.resolve(cid, path) | ||
const path = rest.join('/') | ||
const results = ipfs._ipld.resolve(cid, path) | ||
let value = cid | ||
let remainderPath = path | ||
try { | ||
for await (const result of results) { | ||
if (result.remainderPath === '') { | ||
// Use values from previous iteration if the value isn't a CID | ||
if (CID.isCID(result.value)) { | ||
value = result.value | ||
remainderPath = '' | ||
} | ||
|
||
if (result.value && CID.isCID(result.value.Hash)) { | ||
value = result.value.Hash | ||
remainderPath = '' | ||
} | ||
|
||
break | ||
} | ||
|
||
for await (const result of results) { | ||
if (CID.isCID(result.value)) { | ||
value = result.value | ||
remainderPath = result.remainderPath | ||
} | ||
} catch (error) { | ||
return cb(error) | ||
} | ||
return cb(null, `/ipfs/${cidToString(value, { base: opts.cidBase })}${remainderPath ? '/' + remainderPath : ''}`) | ||
}) | ||
|
||
return `/ipfs/${cidToString(value, { base: opts.cidBase })}${remainderPath ? '/' + remainderPath : ''}` | ||
} | ||
|
||
return (name, opts = {}, cb) => { | ||
if (typeof opts === 'function') { | ||
cb = opts | ||
opts = {} | ||
} | ||
return nodeify(resolve(name, opts), cb) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters