From 8cb8c73037e44894d756b70f344b3282463206f9 Mon Sep 17 00:00:00 2001 From: Alex Potsides Date: Thu, 2 Jul 2020 14:47:25 +0100 Subject: [PATCH] fix: optional arguments go in the options object (#3118) We have a few older APIs that take multiple optional arguments, which makes our code more complicated as it has to guess the users' intent, sometimes by inspecting properties on the passed args to see if they happen to correspond with properties on the actual options object. The options object was recently added to all API calls and is the right place for optional arguments to go, so the change here is to move all optional arguments into the options object, except where the presence of an optional argument dramatically changes the behaviour of the call (`ipfs.bootstrap` I'm mostly looking at you), in which case the methods are split out into multiple versions that do distinct things. Only the programatic API is affected, the CLI and HTTP APIs do not change. BREAKING CHANGES: - `ipfs.bitswap.wantlist([peer], [options])` is split into: - `ipfs.bitswap.wantlist([options])` - `ipfs.bitswap.wantlistForPeer(peer, [options])` - `ipfs.bootstrap.add([addr], [options])` is split into: - `ipfs.bootstrap.add(addr, [options])` - add a bootstrap node - `ipfs.bootstrap.reset()` - restore the default list of bootstrap nodes - `ipfs.bootstrap.rm([addr], [options])` is split into: - `ipfs.bootstrap.rm(addr, [options])` - remove a bootstrap node - `ipfs.bootstrap.clear([options])` - empty the bootstrap list - `ipfs.dag.get(cid, [path], [options])` becomes `ipfs.dag.get(cid, [options])` - `path` is moved into the `options` object - `ipfs.dag.tree(cid, [path], [options])` becomes `ipfs.dag.tree(cid, [options])` - `path` is moved into the `options` object - `ipfs.dag.resolve(cid, [path], [options])` becomes `ipfs.dag.resolve(cid, [options])` - `path` is moved into the `options` object - `ipfs.files.flush([path], [options])` becomes `ipfs.files.flush(path, [options])` - `ipfs.files.ls([path], [options])` becomes `ipfs.files.ls(path, [options])` - `ipfs.object.new([template], [options])` becomes `ipfs.object.new([options])` - `template` is moved into the `options` object - `ipfs.pin.ls([paths], [options])` becomes `ipfs.pin.ls([options])` - `paths` is moved into the `options` object Co-authored-by: Hugo Dias --- docs/core-api/BITSWAP.md | 54 ++++++-- docs/core-api/BOOTSTRAP.md | 116 +++++++++++++++--- docs/core-api/DAG.md | 26 ++-- docs/core-api/FILES.md | 12 +- docs/core-api/OBJECT.md | 13 +- docs/core-api/PIN.md | 19 ++- .../get-path-accross-formats.js | 4 +- .../interface-ipfs-core/src/bitswap/index.js | 3 +- .../interface-ipfs-core/src/bitswap/utils.js | 16 ++- .../src/bitswap/wantlist-for-peer.js | 50 ++++++++ .../src/bitswap/wantlist.js | 7 -- packages/interface-ipfs-core/src/block/put.js | 2 +- .../interface-ipfs-core/src/bootstrap/add.js | 12 +- .../src/bootstrap/clear.js | 56 +++++++++ .../src/bootstrap/index.js | 2 + .../src/bootstrap/reset.js | 50 ++++++++ .../interface-ipfs-core/src/bootstrap/rm.js | 17 --- packages/interface-ipfs-core/src/dag/get.js | 33 +++-- packages/interface-ipfs-core/src/dag/tree.js | 16 ++- .../interface-ipfs-core/src/files/flush.js | 8 +- packages/interface-ipfs-core/src/files/ls.js | 10 +- .../interface-ipfs-core/src/object/new.js | 2 +- packages/interface-ipfs-core/src/pin/index.js | 4 +- packages/interface-ipfs-core/src/pin/ls.js | 28 ++++- packages/ipfs-core-utils/package.json | 1 + .../ipfs-core-utils/src/to-cid-and-path.js | 48 ++++++++ packages/ipfs-http-client/README.md | 2 +- .../ipfs-http-client/src/bitswap/index.js | 1 + .../src/bitswap/wantlist-for-peer.js | 23 ++++ .../ipfs-http-client/src/bitswap/wantlist.js | 11 +- .../ipfs-http-client/src/bootstrap/clear.js | 20 +++ .../ipfs-http-client/src/bootstrap/index.js | 2 + .../ipfs-http-client/src/bootstrap/reset.js | 20 +++ packages/ipfs-http-client/src/dag/get.js | 9 +- packages/ipfs-http-client/src/dag/resolve.js | 9 +- packages/ipfs-http-client/src/files/flush.js | 5 +- packages/ipfs-http-client/src/files/ls.js | 5 +- packages/ipfs-http-client/src/object/new.js | 9 +- packages/ipfs-http-client/src/pin/ls.js | 11 +- packages/ipfs/package.json | 2 +- .../ipfs/src/cli/commands/bitswap/wantlist.js | 15 ++- .../ipfs/src/cli/commands/bootstrap/add.js | 18 ++- .../ipfs/src/cli/commands/bootstrap/rm.js | 18 ++- packages/ipfs/src/cli/commands/dag/get.js | 16 +-- packages/ipfs/src/cli/commands/object/new.js | 3 +- packages/ipfs/src/cli/commands/pin/ls.js | 15 ++- .../components/bitswap/wantlist-for-peer.js | 12 ++ .../src/core/components/bitswap/wantlist.js | 13 +- .../ipfs/src/core/components/bootstrap/add.js | 17 ++- .../src/core/components/bootstrap/clear.js | 15 +++ .../src/core/components/bootstrap/reset.js | 17 +++ .../ipfs/src/core/components/bootstrap/rm.js | 23 +--- packages/ipfs/src/core/components/dag/get.js | 39 +++--- .../ipfs/src/core/components/dag/resolve.js | 15 ++- packages/ipfs/src/core/components/dag/tree.js | 15 ++- .../ipfs/src/core/components/dag/utils.js | 49 -------- .../ipfs/src/core/components/files/flush.js | 11 +- packages/ipfs/src/core/components/files/ls.js | 7 +- .../components/files/utils/to-mfs-path.js | 5 + packages/ipfs/src/core/components/index.js | 5 +- packages/ipfs/src/core/components/init.js | 3 +- .../ipfs/src/core/components/object/new.js | 17 +-- packages/ipfs/src/core/components/pin/ls.js | 17 +-- .../src/core/components/pin/pin-manager.js | 2 +- .../ipfs/src/core/components/pin/pin-set.js | 6 +- packages/ipfs/src/core/components/start.js | 5 +- packages/ipfs/src/core/components/stop.js | 5 +- packages/ipfs/src/core/utils.js | 1 + .../ipfs/src/http/api/resources/bitswap.js | 17 ++- .../ipfs/src/http/api/resources/bootstrap.js | 50 +++++--- packages/ipfs/src/http/api/resources/dag.js | 16 ++- .../ipfs/src/http/api/resources/object.js | 3 +- packages/ipfs/src/http/api/resources/pin.js | 19 ++- packages/ipfs/src/http/utils/joi.js | 15 +-- packages/ipfs/test/cli/bitswap.js | 21 +++- packages/ipfs/test/cli/bootstrap.js | 16 +-- packages/ipfs/test/cli/dag.js | 44 ++++++- packages/ipfs/test/cli/object.js | 12 +- packages/ipfs/test/cli/pin.js | 21 ++-- packages/ipfs/test/core/pin.js | 20 +-- packages/ipfs/test/core/preload.spec.js | 2 +- packages/ipfs/test/http-api/inject/bitswap.js | 30 ++++- .../ipfs/test/http-api/inject/bootstrap.js | 66 +++++++--- packages/ipfs/test/http-api/inject/dag.js | 72 ++++++++--- packages/ipfs/test/http-api/inject/object.js | 23 +++- packages/ipfs/test/http-api/inject/pin.js | 21 ++-- 86 files changed, 1088 insertions(+), 502 deletions(-) create mode 100644 packages/interface-ipfs-core/src/bitswap/wantlist-for-peer.js create mode 100644 packages/interface-ipfs-core/src/bootstrap/clear.js create mode 100644 packages/interface-ipfs-core/src/bootstrap/reset.js create mode 100644 packages/ipfs-core-utils/src/to-cid-and-path.js create mode 100644 packages/ipfs-http-client/src/bitswap/wantlist-for-peer.js create mode 100644 packages/ipfs-http-client/src/bootstrap/clear.js create mode 100644 packages/ipfs-http-client/src/bootstrap/reset.js create mode 100644 packages/ipfs/src/core/components/bitswap/wantlist-for-peer.js create mode 100644 packages/ipfs/src/core/components/bootstrap/clear.js create mode 100644 packages/ipfs/src/core/components/bootstrap/reset.js delete mode 100644 packages/ipfs/src/core/components/dag/utils.js diff --git a/docs/core-api/BITSWAP.md b/docs/core-api/BITSWAP.md index 9de51472ab..d903cfe94d 100644 --- a/docs/core-api/BITSWAP.md +++ b/docs/core-api/BITSWAP.md @@ -1,30 +1,33 @@ # Bitswap API -- [`ipfs.bitswap.wantlist([peerId,] [options])`](#ipfsbitswapwantlistpeerid-options) +- [`ipfs.bitswap.wantlist([options])`](#ipfsbitswapwantlistoptions) - [Parameters](#parameters) - [Options](#options) - [Returns](#returns) - [Example](#example) -- [`ipfs.bitswap.unwant(cids, [options])`](#ipfsbitswapunwantcids-options) +- [`ipfs.bitswap.wantlistForPeer(peerId, [options])`](#ipfsbitswapwantlistforpeerpeerid-options) - [Parameters](#parameters-1) - [Options](#options-1) - [Returns](#returns-1) - [Example](#example-1) -- [`ipfs.bitswap.stat([options])`](#ipfsbitswapstatoptions) +- [`ipfs.bitswap.unwant(cids, [options])`](#ipfsbitswapunwantcids-options) - [Parameters](#parameters-2) - [Options](#options-2) - [Returns](#returns-2) - [Example](#example-2) +- [`ipfs.bitswap.stat([options])`](#ipfsbitswapstatoptions) + - [Parameters](#parameters-3) + - [Options](#options-3) + - [Returns](#returns-3) + - [Example](#example-3) -## `ipfs.bitswap.wantlist([peerId,] [options])` +## `ipfs.bitswap.wantlist([options])` -> Returns the wantlist, optionally filtered by peer ID +> Returns the wantlist for your node ### Parameters -| Name | Type | Description | -| ---- | ---- | ----------- | -| peerId | [PeerId][], [CID][], `String` or `Buffer` | An optional peer ID to return the wantlist for | +None ### Options @@ -47,9 +50,40 @@ An optional object which may have the following keys: const list = await ipfs.bitswap.wantlist() console.log(list) // [ CID('QmHash') ] +``` + +A great source of [examples][] can be found in the tests for this API. + +## `ipfs.bitswap.wantlistForPeer(peerId, [options])` + +> Returns the wantlist for a connected peer + +### Parameters + +| Name | Type | Default | Description | +| ---- | ---- | ------- | ----------- | +| peerId | [PeerId][], [CID][], `String` or `Buffer` | A peer ID to return the wantlist for | + +### Options + +An optional object which may have the following keys: + +| Name | Type | Default | Description | +| ---- | ---- | ------- | ----------- | +| timeout | `Number` | `undefined` | A timeout in ms | +| signal | [AbortSignal][] | `undefined` | Can be used to cancel any long running requests started as a result of this call | + +### Returns + +| Type | Description | +| -------- | -------- | +| `Promise` | An array of [CID][]s currently in the wantlist | -const list2 = await ipfs.bitswap.wantlist(peerId) -console.log(list2) +### Example + +```JavaScript +const list = await ipfs.bitswap.wantlistForPeer(peerId) +console.log(list) // [ CID('QmHash') ] ``` diff --git a/docs/core-api/BOOTSTRAP.md b/docs/core-api/BOOTSTRAP.md index 1d1baa44b1..dca8cf600a 100644 --- a/docs/core-api/BOOTSTRAP.md +++ b/docs/core-api/BOOTSTRAP.md @@ -4,25 +4,35 @@ Warning: your node requires bootstrappers to join the network and find other peers. -If you edit this list, you may find you have reduced or no connectivity. If this is the case, please reset your node's bootstrapper list with `ipfs.bootstrap.add({ default: true })`. +If you edit this list, you may find you have reduced or no connectivity. If this is the case, please reset your node's bootstrapper list with `ipfs.bootstrap.reset()`. -- [`ipfs.bootstrap.add([addr,] [options])`](#ipfsbootstrapaddaddr-options) +- [`ipfs.bootstrap.add(addr, [options])`](#ipfsbootstrapaddaddr-options) - [Parameters](#parameters) - [Options](#options) - [Returns](#returns) - [Example](#example) -- [`ipfs.bootstrap.list([options])`](#ipfsbootstraplistoptions) +- [`ipfs.bootstrap.reset([options])`](#ipfsbootstrapresetoptions) - [Parameters](#parameters-1) - [Options](#options-1) - [Returns](#returns-1) - [Example](#example-1) -- [`ipfs.bootstrap.rm([addr,] [options])`](#ipfsbootstraprmaddr-options) +- [`ipfs.bootstrap.list([options])`](#ipfsbootstraplistoptions) - [Parameters](#parameters-2) - [Options](#options-2) - [Returns](#returns-2) - [Example](#example-2) - -## `ipfs.bootstrap.add([addr,] [options])` +- [`ipfs.bootstrap.rm(addr, [options])`](#ipfsbootstraprmaddr-options) + - [Parameters](#parameters-3) + - [Options](#options-3) + - [Returns](#returns-3) + - [Example](#example-3) +- [`ipfs.bootstrap.clear([options])`](#ipfsbootstrapclearoptions) + - [Parameters](#parameters-4) + - [Options](#options-4) + - [Returns](#returns-4) + - [Example](#example-4) + +## `ipfs.bootstrap.add(addr, [options])` > Add a peer address to the bootstrap list @@ -30,7 +40,7 @@ If you edit this list, you may find you have reduced or no connectivity. If thi | Name | Type | Description | | ---- | ---- | ----------- | -| addr | [MultiAddr][] | The address of a network peer. If omitted the `default` option must be passed as `true`. | +| addr | [MultiAddr][] | The address of a network peer | ### Options @@ -38,12 +48,9 @@ An optional object which may have the following keys: | Name | Type | Default | Description | | ---- | ---- | ------- | ----------- | -| default | `boolean` | `false` | If true, add the default peers to the list | | timeout | `Number` | `undefined` | A timeout in ms | | signal | [AbortSignal][] | `undefined` | Can be used to cancel any long running requests started as a result of this call | -Note: If passing the `default` option, `addr` is an optional parameter (may be `undefined`/`null`) and options may be passed as the first argument. i.e. `ipfs.bootstrap.add({ default: true })` - ### Returns | Type | Description | @@ -71,6 +78,48 @@ console.log(res.Peers) A great source of [examples][] can be found in the tests for this API. +## `ipfs.bootstrap.reset([options])` + +> Reset the bootstrap list to contain only the default bootstrap nodes + +### Parameters + +None. + +### Options + +An optional object which may have the following keys: + +| Name | Type | Default | Description | +| ---- | ---- | ------- | ----------- | +| timeout | `Number` | `undefined` | A timeout in ms | +| signal | [AbortSignal][] | `undefined` | Can be used to cancel any long running requests started as a result of this call | + +### Returns + +| Type | Description | +| -------- | -------- | +| `Promise<{ Peers: Array }>` | An object that contains an array with all the added addresses | + +example of the returned object: + +```JavaScript +{ + Peers: [address1, address2, ...] +} +``` + +### Example + +```JavaScript +const res = await ipfs.bootstrap.reset() +console.log(res.Peers) +// Logs: +// ['/ip4/104....9z'] +``` + +A great source of [examples][] can be found in the tests for this API. + ## `ipfs.bootstrap.list([options])` > List all peer addresses in the bootstrap list @@ -113,7 +162,7 @@ console.log(res.Peers) A great source of [examples][] can be found in the tests for this API. -## `ipfs.bootstrap.rm([addr,] [options])` +## `ipfs.bootstrap.rm(addr, [options])` > Remove a peer address from the bootstrap list @@ -121,7 +170,7 @@ A great source of [examples][] can be found in the tests for this API. | Name | Type | Description | | ---- | ---- | ----------- | -| addr | [MultiAddr][] | The address of a network peer. If omitted the `all` option must be passed as `true`. | +| addr | [MultiAddr][] | The address of a network peer | ### Options @@ -129,11 +178,48 @@ An optional object which may have the following keys: | Name | Type | Default | Description | | ---- | ---- | ------- | ----------- | -| all | `boolean` | `false` | If true, remove all peers from the bootstrap list | | timeout | `Number` | `undefined` | A timeout in ms | | signal | [AbortSignal][] | `undefined` | Can be used to cancel any long running requests started as a result of this call | -Note: If passing the `all` option, `addr` is an optional parameter (may be `undefined`/`null`) and options may be passed as the first argument. i.e. `ipfs.bootstrap.rm({ all: true })` +### Returns + +| Type | Description | +| -------- | -------- | +| `Promise<{ Peers: Array }>` | An object that contains an array with all the removed addresses | + +```JavaScript +{ + Peers: [address1, address2, ...] +} +``` + +### Example + +```JavaScript +const res = await ipfs.bootstrap.rm('address1') +console.log(res.Peers) +// Logs: +// [address1, ...] +``` + +A great source of [examples][] can be found in the tests for this API. + +## `ipfs.bootstrap.clear([options])` + +> Remove all peer addresses from the bootstrap list + +### Parameters + +None. + +### Options + +An optional object which may have the following keys: + +| Name | Type | Default | Description | +| ---- | ---- | ------- | ----------- | +| timeout | `Number` | `undefined` | A timeout in ms | +| signal | [AbortSignal][] | `undefined` | Can be used to cancel any long running requests started as a result of this call | ### Returns @@ -150,7 +236,7 @@ Note: If passing the `all` option, `addr` is an optional parameter (may be `unde ### Example ```JavaScript -const res = await ipfs.bootstrap.rm(null, { all: true }) +const res = await ipfs.bootstrap.clear() console.log(res.Peers) // Logs: // [address1, address2, ...] diff --git a/docs/core-api/DAG.md b/docs/core-api/DAG.md index 464d9d5478..4e6b441a60 100644 --- a/docs/core-api/DAG.md +++ b/docs/core-api/DAG.md @@ -7,12 +7,12 @@ - [Options](#options) - [Returns](#returns) - [Example](#example) -- [`ipfs.dag.get(cid, [path], [options])`](#ipfsdaggetcid-path-options) +- [`ipfs.dag.get(cid, [options])`](#ipfsdaggetcid-path-options) - [Parameters](#parameters-1) - [Options](#options-1) - [Returns](#returns-1) - [Example](#example-1) -- [`ipfs.dag.tree(cid, [path,] [options])`](#ipfsdagtreecid-path-options) +- [`ipfs.dag.tree(cid, [options])`](#ipfsdagtreecid-path-options) - [Parameters](#parameters-2) - [Options](#options-2) - [Returns](#returns-2) @@ -65,7 +65,7 @@ console.log(cid.toString()) A great source of [examples][] can be found in the tests for this API. -## `ipfs.dag.get(cid, [path], [options])` +## `ipfs.dag.get(cid, [options])` > Retrieve an IPLD format node @@ -73,8 +73,7 @@ A great source of [examples][] can be found in the tests for this API. | Name | Type | Description | | ---- | ---- | ----------- | -| cid | [CID][] | A DAG node that follows one of the supported IPLD formats | -| path | `String` | An optional path within the DAG to resolve | +| cid | [CID][] | A CID that resolves to a node to get | ### Options @@ -82,6 +81,7 @@ An optional object which may have the following keys: | Name | Type | Default | Description | | ---- | ---- | ------- | ----------- | +| path | `String` | An optional path within the DAG to resolve | | localResolve | `boolean` | `false` | If set to true, it will avoid resolving through different objects | | timeout | `Number` | `undefined` | A timeout in ms | | signal | [AbortSignal][] | `undefined` | Can be used to cancel any long running requests started as a result of this call | @@ -114,34 +114,34 @@ const cid = await ipfs.dag.put(obj, { format: 'dag-cbor', hashAlg: 'sha2-256' }) console.log(cid.toString()) // zdpuAmtur968yprkhG9N5Zxn6MFVoqAWBbhUAkNLJs2UtkTq5 -async function getAndLog(cidPath) { - const result = await ipfs.dag.get(cidPath) +async function getAndLog(cid, path) { + const result = await ipfs.dag.get(cid, { path }) console.log(result.value) } -await getAndLog('zdpuAmtur968yprkhG9N5Zxn6MFVoqAWBbhUAkNLJs2UtkTq5/a') +await getAndLog(cid, '/a') // Logs: // 1 -await getAndLog('zdpuAmtur968yprkhG9N5Zxn6MFVoqAWBbhUAkNLJs2UtkTq5/b') +await getAndLog(cid, '/b') // Logs: // [1, 2, 3] -await getAndLog('zdpuAmtur968yprkhG9N5Zxn6MFVoqAWBbhUAkNLJs2UtkTq5/c') +await getAndLog(cid, '/c') // Logs: // { // ca: [5, 6, 7], // cb: 'foo' // } -await getAndLog('zdpuAmtur968yprkhG9N5Zxn6MFVoqAWBbhUAkNLJs2UtkTq5/c/ca/1') +await getAndLog(cid, '/c/ca/1') // Logs: // 6 ``` A great source of [examples][] can be found in the tests for this API. -## `ipfs.dag.tree(cid, [path,] [options])` +## `ipfs.dag.tree(cid, [options])` > Enumerate all the entries in a graph @@ -150,7 +150,6 @@ A great source of [examples][] can be found in the tests for this API. | Name | Type | Description | | ---- | ---- | ----------- | | cid | [CID][] | A DAG node that follows one of the supported IPLD formats | -| path | `String` | An optional path within the DAG to resolve | ### Options @@ -158,6 +157,7 @@ An optional object which may have the following keys: | Name | Type | Default | Description | | ---- | ---- | ------- | ----------- | +| path | `String` | An optional path within the DAG to resolve | | recursive | `boolean` | `false` | If set to true, it will follow the links and continuously run tree on them, returning all the paths in the graph | | timeout | `Number` | `undefined` | A timeout in ms | | signal | [AbortSignal][] | `undefined` | Can be used to cancel any long running requests started as a result of this call | diff --git a/docs/core-api/FILES.md b/docs/core-api/FILES.md index 0698419a00..1e35c92002 100644 --- a/docs/core-api/FILES.md +++ b/docs/core-api/FILES.md @@ -72,11 +72,11 @@ _Explore the Mutable File System through interactive coding challenges in our [P - [Options](#options-12) - [Returns](#returns-11) - [Example](#example-8) - - [`ipfs.files.flush([path,] [options])`](#ipfsfilesflushpath-options) + - [`ipfs.files.flush(path, [options])`](#ipfsfilesflushpath-options) - [Parameters](#parameters-13) - [Options](#options-13) - [Returns](#returns-12) - - [`ipfs.files.ls([path], [options])`](#ipfsfileslspath-options) + - [`ipfs.files.ls(path, [options])`](#ipfsfileslspath-options) - [Parameters](#parameters-14) - [Options](#options-14) - [Returns](#returns-13) @@ -869,7 +869,7 @@ If `from` is an IPFS path and the content does not exist in your node's repo, on All values of `from` will be removed after the operation is complete unless they are an IPFS path. -### `ipfs.files.flush([path,] [options])` +### `ipfs.files.flush(path, [options])` > Flush a given path's data to the disk @@ -877,7 +877,7 @@ All values of `from` will be removed after the operation is complete unless they | Name | Type | Description | | ---- | ---- | ----------- | -| path | `String` | Optional [MFS path][] to flush, defaults to `'/'` | +| path | `String` | The [MFS path][] to flush | #### Options @@ -900,7 +900,7 @@ An optional object which may have the following keys: const cid = await ipfs.files.flush('/') ``` -### `ipfs.files.ls([path], [options])` +### `ipfs.files.ls(path, [options])` > List directories in the local mutable namespace @@ -908,7 +908,7 @@ const cid = await ipfs.files.flush('/') | Name | Type | Description | | ---- | ---- | ----------- | -| path | `String` | Optional [MFS path][] to list, defaults to `'/'` | +| path | `String` | The [MFS path][] to list | #### Options diff --git a/docs/core-api/OBJECT.md b/docs/core-api/OBJECT.md index 43395504ed..49664f22fb 100644 --- a/docs/core-api/OBJECT.md +++ b/docs/core-api/OBJECT.md @@ -1,6 +1,6 @@ # Object API -- [`ipfs.object.new([template,] [options])`](#ipfsobjectnewtemplate-options) +- [`ipfs.object.new([options])`](#ipfsobjectnewoptions) - [Parameters](#parameters) - [Options](#options) - [Returns](#returns) @@ -52,15 +52,13 @@ - [Returns](#returns-9) - [Example](#example-9) -## `ipfs.object.new([template,] [options])` +## `ipfs.object.new([options])` > Create a new MerkleDAG node, using a specific layout. Caveat: So far, only UnixFS object layouts are supported. ### Parameters -| Name | Type | Description | -| ---- | ---- | ----------- | -| template | `String` | If defined, must be a string `unixfs-dir` and if that is passed, the created node will be an empty unixfs style directory | +None. ### Options @@ -68,6 +66,7 @@ An optional object which may have the following keys: | Name | Type | Default | Description | | ---- | ---- | ------- | ----------- | +| template | `String` | If defined, must be a string `unixfs-dir` and if that is passed, the created node will be an empty unixfs style directory | | recursive | `boolean` | `false` | Resolve until the result is not an IPNS name | | nocache | `boolean` | `cache` | Do not use cached entries | | timeout | `Number` | `undefined` | A timeout in ms | @@ -82,7 +81,9 @@ An optional object which may have the following keys: ### Example ```JavaScript -const cid = await ipfs.object.new('unixfs-dir') +const cid = await ipfs.object.new({ + template: 'unixfs-dir' +}) console.log(cid.toString()) // Logs: // QmUNLLsPACCz1vLxQVkXqqLX5R1X345qqfHbsf67hvA3Nn diff --git a/docs/core-api/PIN.md b/docs/core-api/PIN.md index 14970ea841..2999b1cf10 100644 --- a/docs/core-api/PIN.md +++ b/docs/core-api/PIN.md @@ -5,7 +5,7 @@ - [Options](#options) - [Returns](#returns) - [Example](#example) -- [`ipfs.pin.ls([cid], [options])`](#ipfspinlscid-options) +- [`ipfs.pin.ls([options])`](#ipfspinlsoptions) - [Parameters](#parameters-1) - [Options](#options-1) - [Returns](#returns-1) @@ -61,15 +61,14 @@ console.log(pinset) A great source of [examples][] can be found in the tests for this API. -## `ipfs.pin.ls([cid], [options])` +## `ipfs.pin.ls([options])` -> List all the objects pinned to local storage or under a specific hash +> List all the objects pinned to local storage ### Parameters | Name | Type | Description | | ---- | ---- | ----------- | -| cid | [CID][] or `Array` | List these specific CIDs | ### Options @@ -77,6 +76,7 @@ An optional object which may have the following keys: | Name | Type | Default | Description | | ---- | ---- | ------- | ----------- | +| paths | [CID][] or `Array` or `String` or `Array` | CIDs or IPFS paths to search for in the pinset | | type | `String` | `undefined` | Filter by this type of pin ("recursive", "direct" or "indirect") | | timeout | `Number` | `undefined` | A timeout in ms | | signal | [AbortSignal][] | `undefined` | Can be used to cancel any long running requests started as a result of this call | @@ -98,6 +98,17 @@ for await (const { cid, type } of ipfs.pin.ls()) { // { cid: CID(QmSo73bmN47gBxMNqbdV6rZ4KJiqaArqJ1nu5TvFhqqj1R), type: 'indirect' } ``` +```JavaScript +for await (const { cid, type } of ipfs.pin.ls({ + paths: [ new CID('Qmc5..'), new CID('QmZb..'), new CID('QmSo..') ] +})) { + console.log({ cid, type }) +} +// { cid: CID(Qmc5XkteJdb337s7VwFBAGtiaoj2QCEzyxtNRy3iMudc3E), type: 'recursive' } +// { cid: CID(QmZbj5ruYneZb8FuR9wnLqJCpCXMQudhSdWhdhp5U1oPWJ), type: 'indirect' } +// { cid: CID(QmSo73bmN47gBxMNqbdV6rZ4KJiqaArqJ1nu5TvFhqqj1R), type: 'indirect' } +``` + A great source of [examples][] can be found in the tests for this API. ## `ipfs.pin.rm(cid, [options])` diff --git a/examples/traverse-ipld-graphs/get-path-accross-formats.js b/examples/traverse-ipld-graphs/get-path-accross-formats.js index ef843a1a74..051845e6a8 100644 --- a/examples/traverse-ipld-graphs/get-path-accross-formats.js +++ b/examples/traverse-ipld-graphs/get-path-accross-formats.js @@ -29,7 +29,9 @@ async function main () { hashAlg: 'sha3-512' }) - const result = await ipfs.dag.get(cborNodeCid, 'hobbies/0/Data') + const result = await ipfs.dag.get(cborNodeCid, { + path: 'hobbies/0/Data' + }) console.log(result.value.toString()) } diff --git a/packages/interface-ipfs-core/src/bitswap/index.js b/packages/interface-ipfs-core/src/bitswap/index.js index 34949a7e1f..e2b78a1a9d 100644 --- a/packages/interface-ipfs-core/src/bitswap/index.js +++ b/packages/interface-ipfs-core/src/bitswap/index.js @@ -3,7 +3,8 @@ const { createSuite } = require('../utils/suite') const tests = { stat: require('./stat'), - wantlist: require('./wantlist') + wantlist: require('./wantlist'), + wantlistForPeer: require('./wantlist-for-peer') } module.exports = createSuite(tests) diff --git a/packages/interface-ipfs-core/src/bitswap/utils.js b/packages/interface-ipfs-core/src/bitswap/utils.js index 90439d3cf4..b0ee8fb62b 100644 --- a/packages/interface-ipfs-core/src/bitswap/utils.js +++ b/packages/interface-ipfs-core/src/bitswap/utils.js @@ -9,7 +9,13 @@ async function waitForWantlistKey (ipfs, key, opts = {}) { const end = Date.now() + opts.timeout while (Date.now() < end) { - const list = await ipfs.bitswap.wantlist(opts.peerId) + let list + + if (opts.peerId) { + list = await ipfs.bitswap.wantlistForPeer(opts.peerId) + } else { + list = await ipfs.bitswap.wantlist() + } if (list.some(cid => cid.toString() === key)) { return @@ -28,7 +34,13 @@ async function waitForWantlistKeyToBeRemoved (ipfs, key, opts = {}) { const end = Date.now() + opts.timeout while (Date.now() < end) { - const list = await ipfs.bitswap.wantlist(opts.peerId) + let list + + if (opts.peerId) { + list = await ipfs.bitswap.wantlistForPeer(opts.peerId) + } else { + list = await ipfs.bitswap.wantlist() + } if (list.some(cid => cid.toString() === key)) { await delay(opts.interval) diff --git a/packages/interface-ipfs-core/src/bitswap/wantlist-for-peer.js b/packages/interface-ipfs-core/src/bitswap/wantlist-for-peer.js new file mode 100644 index 0000000000..e65321f16a --- /dev/null +++ b/packages/interface-ipfs-core/src/bitswap/wantlist-for-peer.js @@ -0,0 +1,50 @@ +/* eslint-env mocha */ +'use strict' + +const { getDescribe, getIt } = require('../utils/mocha') +const { waitForWantlistKey } = require('./utils') +const { isWebWorker } = require('ipfs-utils/src/env') +const testTimeout = require('../utils/test-timeout') + +/** @typedef { import("ipfsd-ctl/src/factory") } Factory */ +/** + * @param {Factory} common + * @param {Object} options + */ +module.exports = (common, options) => { + const describe = getDescribe(options) + const it = getIt(options) + + describe('.bitswap.wantlistForPeer', function () { + this.timeout(60 * 1000) + + let ipfsA + let ipfsB + const key = 'QmUBdnXXPyoDFXj3Hj39dNJ5VkN3QFRskXxcGaYFBB8CNR' + + before(async () => { + ipfsA = (await common.spawn()).api + // webworkers are not dialable because webrtc is not available + ipfsB = (await common.spawn({ type: isWebWorker ? 'go' : undefined })).api + // Add key to the wantlist for ipfsB + ipfsB.block.get(key).catch(() => { /* is ok, expected on teardown */ }) + + await ipfsA.swarm.connect(ipfsB.peerId.addresses[0]) + }) + + after(() => common.clean()) + + it('should respect timeout option when getting bitswap wantlist by peer', () => { + return testTimeout(() => ipfsA.bitswap.wantlistForPeer(ipfsB.peerId.id, { + timeout: 1 + })) + }) + + it('should get the wantlist by peer ID for a different node', function () { + return waitForWantlistKey(ipfsA, key, { + peerId: ipfsB.peerId.id, + timeout: 60 * 1000 + }) + }) + }) +} diff --git a/packages/interface-ipfs-core/src/bitswap/wantlist.js b/packages/interface-ipfs-core/src/bitswap/wantlist.js index d35deb6948..f22581b32c 100644 --- a/packages/interface-ipfs-core/src/bitswap/wantlist.js +++ b/packages/interface-ipfs-core/src/bitswap/wantlist.js @@ -47,13 +47,6 @@ module.exports = (common, options) => { return waitForWantlistKey(ipfsB, key) }) - it('should get the wantlist by peer ID for a different node', function () { - return waitForWantlistKey(ipfsA, key, { - peerId: ipfsB.peerId.id, - timeout: 60 * 1000 - }) - }) - it('should not get the wantlist when offline', async () => { const node = await common.spawn() await node.stop() diff --git a/packages/interface-ipfs-core/src/block/put.js b/packages/interface-ipfs-core/src/block/put.js index e0eaee8f29..475054fa2e 100644 --- a/packages/interface-ipfs-core/src/block/put.js +++ b/packages/interface-ipfs-core/src/block/put.js @@ -78,7 +78,7 @@ module.exports = (common, options) => { expect(block.cid.version).to.equal(1) expect(block.cid.codec).to.equal('raw') expect(multihash.decode(block.cid.multihash).name).to.equal('sha2-512') - expect(await all(ipfs.pin.ls(block.cid))).to.have.lengthOf(1) + expect(await all(ipfs.pin.ls({ paths: block.cid }))).to.have.lengthOf(1) }) it('should put a Block instance', async () => { diff --git a/packages/interface-ipfs-core/src/bootstrap/add.js b/packages/interface-ipfs-core/src/bootstrap/add.js index 83f0626eea..6531eb3b8d 100644 --- a/packages/interface-ipfs-core/src/bootstrap/add.js +++ b/packages/interface-ipfs-core/src/bootstrap/add.js @@ -28,8 +28,7 @@ module.exports = (common, options) => { after(() => common.clean()) it('should respect timeout option when adding bootstrap nodes', () => { - return testTimeout(() => ipfs.bootstrap.add(null, { - default: true, + return testTimeout(() => ipfs.bootstrap.add(validIp4, { timeout: 1 })) }) @@ -47,15 +46,8 @@ module.exports = (common, options) => { expect(peers).to.have.property('length').that.is.equal(1) }) - it('should return a list of bootstrap peers when called with the default option', async () => { - const res = await ipfs.bootstrap.add(null, { default: true }) - - const peers = res.Peers - expect(peers).to.have.property('length').that.is.gt(1) - }) - it('should prevent duplicate inserts of bootstrap peers', async () => { - await ipfs.bootstrap.rm(null, { all: true }) + await ipfs.bootstrap.clear() const added = await ipfs.bootstrap.add(validIp4) expect(added).to.have.property('Peers').that.deep.equals([validIp4]) diff --git a/packages/interface-ipfs-core/src/bootstrap/clear.js b/packages/interface-ipfs-core/src/bootstrap/clear.js new file mode 100644 index 0000000000..2d65561b9c --- /dev/null +++ b/packages/interface-ipfs-core/src/bootstrap/clear.js @@ -0,0 +1,56 @@ +/* eslint-env mocha */ +'use strict' + +const { getDescribe, getIt, expect } = require('../utils/mocha') +const testTimeout = require('../utils/test-timeout') + +/** @typedef { import("ipfsd-ctl/src/factory") } Factory */ +/** + * @param {Factory} common + * @param {Object} options + */ +module.exports = (common, options) => { + const describe = getDescribe(options) + const it = getIt(options) + + const validIp4 = '/ip4/104.236.176.52/tcp/4001/p2p/QmSoLnSGccFuZQJzRadHn95W2CrSFmZuTdDWP8HXaHca9z' + + describe('.bootstrap.clear', function () { + this.timeout(100 * 1000) + + let ipfs + + before(async () => { ipfs = (await common.spawn()).api }) + + after(() => common.clean()) + + it('should respect timeout option when removing bootstrap nodes', () => { + return testTimeout(() => ipfs.bootstrap.clear({ + timeout: 1 + })) + }) + + it('should return a list containing the peer removed when called with a valid arg (ip4)', async () => { + await ipfs.bootstrap.clear() + + const addRes = await ipfs.bootstrap.add(validIp4) + expect(addRes).to.be.eql({ Peers: [validIp4] }) + + const rmRes = await ipfs.bootstrap.clear() + expect(rmRes).to.be.eql({ Peers: [validIp4] }) + + const peers = rmRes.Peers + expect(peers).to.have.property('length').that.is.equal(1) + }) + + it('should return a list of all peers removed when all option is passed', async () => { + const addRes = await ipfs.bootstrap.reset() + const addedPeers = addRes.Peers + + const rmRes = await ipfs.bootstrap.clear() + const removedPeers = rmRes.Peers + + expect(removedPeers.sort()).to.deep.equal(addedPeers.sort()) + }) + }) +} diff --git a/packages/interface-ipfs-core/src/bootstrap/index.js b/packages/interface-ipfs-core/src/bootstrap/index.js index 858d977475..b8276573df 100644 --- a/packages/interface-ipfs-core/src/bootstrap/index.js +++ b/packages/interface-ipfs-core/src/bootstrap/index.js @@ -3,7 +3,9 @@ const { createSuite } = require('../utils/suite') const tests = { add: require('./add'), + clear: require('./clear'), list: require('./list'), + reset: require('./reset'), rm: require('./rm') } diff --git a/packages/interface-ipfs-core/src/bootstrap/reset.js b/packages/interface-ipfs-core/src/bootstrap/reset.js new file mode 100644 index 0000000000..0f34242f85 --- /dev/null +++ b/packages/interface-ipfs-core/src/bootstrap/reset.js @@ -0,0 +1,50 @@ +/* eslint-env mocha */ +'use strict' + +const { getDescribe, getIt, expect } = require('../utils/mocha') +const testTimeout = require('../utils/test-timeout') + +/** @typedef { import("ipfsd-ctl/src/factory") } Factory */ +/** + * @param {Factory} common + * @param {Object} options + */ +module.exports = (common, options) => { + const describe = getDescribe(options) + const it = getIt(options) + + describe('.bootstrap.reset', function () { + this.timeout(100 * 1000) + + let ipfs + + before(async () => { + ipfs = (await common.spawn()).api + }) + + after(() => common.clean()) + + it('should respect timeout option when resetting the bootstrap nodes', () => { + return testTimeout(() => ipfs.bootstrap.reset({ + timeout: 1 + })) + }) + + it('should return a list of bootstrap peers when resetting the bootstrap nodes', async () => { + const res = await ipfs.bootstrap.reset() + + const peers = res.Peers + expect(peers).to.have.property('length').that.is.gt(1) + }) + + it('should return a list of all peers removed when all option is passed', async () => { + const addRes = await ipfs.bootstrap.reset() + const addedPeers = addRes.Peers + + const rmRes = await ipfs.bootstrap.clear() + const removedPeers = rmRes.Peers + + expect(removedPeers.sort()).to.deep.equal(addedPeers.sort()) + }) + }) +} diff --git a/packages/interface-ipfs-core/src/bootstrap/rm.js b/packages/interface-ipfs-core/src/bootstrap/rm.js index d4f43e0318..db4240f5bc 100644 --- a/packages/interface-ipfs-core/src/bootstrap/rm.js +++ b/packages/interface-ipfs-core/src/bootstrap/rm.js @@ -36,13 +36,6 @@ module.exports = (common, options) => { .and.be.an.instanceOf(Error) }) - it('should return an empty list because no peers removed when called without an arg or options', async () => { - const res = await ipfs.bootstrap.rm(null) - - const peers = res.Peers - expect(peers).to.have.property('length').that.is.equal(0) - }) - it('should return a list containing the peer removed when called with a valid arg (ip4)', async () => { const addRes = await ipfs.bootstrap.add(validIp4) expect(addRes).to.be.eql({ Peers: [validIp4] }) @@ -53,15 +46,5 @@ module.exports = (common, options) => { const peers = rmRes.Peers expect(peers).to.have.property('length').that.is.equal(1) }) - - it('should return a list of all peers removed when all option is passed', async () => { - const addRes = await ipfs.bootstrap.add(null, { default: true }) - const addedPeers = addRes.Peers - - const rmRes = await ipfs.bootstrap.rm(null, { all: true }) - const removedPeers = rmRes.Peers - - expect(removedPeers.sort()).to.deep.equal(addedPeers.sort()) - }) }) } diff --git a/packages/interface-ipfs-core/src/dag/get.js b/packages/interface-ipfs-core/src/dag/get.js index b88a6fa729..9003706336 100644 --- a/packages/interface-ipfs-core/src/dag/get.js +++ b/packages/interface-ipfs-core/src/dag/get.js @@ -85,7 +85,9 @@ module.exports = (common, options) => { }) it('should get a dag-pb node with path', async () => { - const result = await ipfs.dag.get(cidPb, '/') + const result = await ipfs.dag.get(cidPb, { + path: '/' + }) const node = result.value @@ -94,7 +96,9 @@ module.exports = (common, options) => { }) it('should get a dag-pb node local value', async function () { - const result = await ipfs.dag.get(cidPb, 'Data') + const result = await ipfs.dag.get(cidPb, { + path: 'Data' + }) expect(result.value).to.eql(Buffer.from('I am inside a Protobuf')) }) @@ -102,7 +106,9 @@ module.exports = (common, options) => { it.skip('should get a dag-pb node value two levels deep', (done) => {}) it('should get a dag-cbor node with path', async () => { - const result = await ipfs.dag.get(cidCbor, '/') + const result = await ipfs.dag.get(cidCbor, { + path: '/' + }) const node = result.value @@ -111,7 +117,9 @@ module.exports = (common, options) => { }) it('should get a dag-cbor node local value', async () => { - const result = await ipfs.dag.get(cidCbor, 'someData') + const result = await ipfs.dag.get(cidCbor, { + path: 'someData' + }) expect(result.value).to.eql('I am inside a Cbor object') }) @@ -120,7 +128,9 @@ module.exports = (common, options) => { it.skip('should get dag-cbor value via dag-pb node', (done) => {}) it('should get dag-pb value via dag-cbor node', async function () { - const result = await ipfs.dag.get(cidCbor, 'pb/Data') + const result = await ipfs.dag.get(cidCbor, { + path: 'pb/Data' + }) expect(result.value).to.eql(Buffer.from('I am inside a Protobuf')) }) @@ -143,7 +153,10 @@ module.exports = (common, options) => { }) it('should get only a CID, due to resolving locally only', async function () { - const result = await ipfs.dag.get(cidCbor, 'pb/Data', { localResolve: true }) + const result = await ipfs.dag.get(cidCbor, { + path: 'pb/Data', + localResolve: true + }) expect(result.value.equals(cidPb)).to.be.true() }) @@ -193,7 +206,9 @@ module.exports = (common, options) => { cid = cid.toBaseEncodedString('base32') expect(cid).to.equal('bafyreic6f672hnponukaacmk2mmt7vs324zkagvu4hcww6yba6kby25zce') - const result = await ipfs.dag.get(cid, 'foo') + const result = await ipfs.dag.get(cid, { + path: 'foo' + }) expect(result.value).to.equal('dag-cbor-bar') }) @@ -207,7 +222,9 @@ module.exports = (common, options) => { const cid2 = await ipfs.dag.put(cbor2, { format: 'dag-cbor', hashAlg: 'sha2-256' }) - const result = await ipfs.dag.get(cid2, 'other/foo') + const result = await ipfs.dag.get(cid2, { + path: 'other/foo' + }) expect(result.value).to.equal('dag-cbor-bar') }) diff --git a/packages/interface-ipfs-core/src/dag/tree.js b/packages/interface-ipfs-core/src/dag/tree.js index ada763b097..ce1393da6b 100644 --- a/packages/interface-ipfs-core/src/dag/tree.js +++ b/packages/interface-ipfs-core/src/dag/tree.js @@ -61,14 +61,9 @@ module.exports = (common, options) => { }) it('should get tree with CID and path', async () => { - const paths = await all(ipfs.dag.tree(cidCbor, 'someData')) - expect(paths).to.eql([]) - }) - - it('should get tree with CID and path as String', async () => { - const cidCborStr = cidCbor.toBaseEncodedString() - - const paths = await all(ipfs.dag.tree(cidCborStr + '/someData')) + const paths = await all(ipfs.dag.tree(cidCbor, { + path: 'someData' + })) expect(paths).to.eql([]) }) @@ -83,7 +78,10 @@ module.exports = (common, options) => { }) it('should get tree with CID and path recursive', async () => { - const paths = await all(ipfs.dag.tree(cidCbor, 'pb', { recursive: true })) + const paths = await all(ipfs.dag.tree(cidCbor, { + path: 'pb', + recursive: true + })) expect(paths).to.have.members([ 'Links', 'Data' diff --git a/packages/interface-ipfs-core/src/files/flush.js b/packages/interface-ipfs-core/src/files/flush.js index 479307d5eb..1487aaee2a 100644 --- a/packages/interface-ipfs-core/src/files/flush.js +++ b/packages/interface-ipfs-core/src/files/flush.js @@ -33,9 +33,13 @@ module.exports = (common, options) => { } }) + it('should require a path', () => { + expect(ipfs.files.flush()).to.eventually.be.rejected() + }) + it('should flush root', async () => { const root = await ipfs.files.stat('/') - const flushed = await ipfs.files.flush() + const flushed = await ipfs.files.flush('/') expect(root.cid.toString()).to.equal(flushed.toString()) }) @@ -52,7 +56,7 @@ module.exports = (common, options) => { }) it('should respect timeout option when flushing changes', async () => { - await testTimeout(() => ipfs.files.flush({ + await testTimeout(() => ipfs.files.flush('/', { timeout: 1 })) }) diff --git a/packages/interface-ipfs-core/src/files/ls.js b/packages/interface-ipfs-core/src/files/ls.js index 21ed098554..1fc930eb3c 100644 --- a/packages/interface-ipfs-core/src/files/ls.js +++ b/packages/interface-ipfs-core/src/files/ls.js @@ -35,7 +35,11 @@ module.exports = (common, options) => { after(() => common.clean()) - it('lists the root directory by default', async () => { + it('should require a path', () => { + expect(all(ipfs.files.ls())).to.eventually.be.rejected() + }) + + it('lists the root directory', async () => { const fileName = `small-file-${Math.random()}.txt` const content = Buffer.from('Hello world') @@ -43,7 +47,7 @@ module.exports = (common, options) => { create: true }) - const files = await all(ipfs.files.ls()) + const files = await all(ipfs.files.ls('/')) expect(files).to.have.lengthOf(1).and.to.containSubset([{ cid: new CID('Qmetpc7cZmN25Wcc6R27cGCAvCDqCS5GjHG4v7xABEfpmJ'), @@ -201,7 +205,7 @@ module.exports = (common, options) => { }) it('should respect timeout option when listing files', async () => { - await testTimeout(() => drain(ipfs.files.ls({ + await testTimeout(() => drain(ipfs.files.ls('/', { timeout: 1 }))) }) diff --git a/packages/interface-ipfs-core/src/object/new.js b/packages/interface-ipfs-core/src/object/new.js index 5c40b84c78..9788218d01 100644 --- a/packages/interface-ipfs-core/src/object/new.js +++ b/packages/interface-ipfs-core/src/object/new.js @@ -36,7 +36,7 @@ module.exports = (common, options) => { }) it('should create a new object with unixfs-dir template', async () => { - const cid = await ipfs.object.new('unixfs-dir') + const cid = await ipfs.object.new({ template: 'unixfs-dir' }) expect(cid.toBaseEncodedString()).to.equal('QmUNLLsPACCz1vLxQVkXqqLX5R1X345qqfHbsf67hvA3Nn') }) }) diff --git a/packages/interface-ipfs-core/src/pin/index.js b/packages/interface-ipfs-core/src/pin/index.js index b3723d07c5..15f55419d3 100644 --- a/packages/interface-ipfs-core/src/pin/index.js +++ b/packages/interface-ipfs-core/src/pin/index.js @@ -2,9 +2,9 @@ const { createSuite } = require('../utils/suite') const tests = { + add: require('./add'), ls: require('./ls'), - rm: require('./rm'), - add: require('./add') + rm: require('./rm') } module.exports = createSuite(tests) diff --git a/packages/interface-ipfs-core/src/pin/ls.js b/packages/interface-ipfs-core/src/pin/ls.js index 5aa9048f97..7ca8f1c565 100644 --- a/packages/interface-ipfs-core/src/pin/ls.js +++ b/packages/interface-ipfs-core/src/pin/ls.js @@ -119,7 +119,9 @@ module.exports = (common, options) => { }) it('should list pins for a specific hash', async () => { - const pinset = await all(ipfs.pin.ls(fixtures.files[0].cid)) + const pinset = await all(ipfs.pin.ls({ + paths: fixtures.files[0].cid + })) expect(pinset).to.have.lengthOf(1) expect(pinset[0].type).to.equal('recursive') expect(pinset[0].cid.toString()).to.equal(fixtures.files[0].cid) @@ -127,35 +129,49 @@ module.exports = (common, options) => { it('should throw an error on missing direct pins for existing path', () => { // ipfs.txt is an indirect pin, so lookup for direct one should throw an error - return expect(all(ipfs.pin.ls(`/ipfs/${fixtures.directory.cid}/files/ipfs.txt`, { type: 'direct' }))) + return expect(all(ipfs.pin.ls({ + paths: `/ipfs/${fixtures.directory.cid}/files/ipfs.txt`, + type: 'direct' + }))) .to.eventually.be.rejected .and.be.an.instanceOf(Error) .and.to.have.property('message', `path '/ipfs/${fixtures.directory.cid}/files/ipfs.txt' is not pinned`) }) it('should throw an error on missing link for a specific path', () => { - return expect(all(ipfs.pin.ls(`/ipfs/${fixtures.directory.cid}/I-DONT-EXIST.txt`, { type: 'direct' }))) + return expect(all(ipfs.pin.ls({ + paths: `/ipfs/${fixtures.directory.cid}/I-DONT-EXIST.txt`, + type: 'direct' + }))) .to.eventually.be.rejected .and.be.an.instanceOf(Error) .and.to.have.property('message', `no link named "I-DONT-EXIST.txt" under ${fixtures.directory.cid}`) }) it('should list indirect pins for a specific path', async () => { - const pinset = await all(ipfs.pin.ls(`/ipfs/${fixtures.directory.cid}/files/ipfs.txt`, { type: 'indirect' })) + const pinset = await all(ipfs.pin.ls({ + paths: `/ipfs/${fixtures.directory.cid}/files/ipfs.txt`, + type: 'indirect' + })) expect(pinset).to.have.lengthOf(1) expect(pinset[0].type).to.equal(`indirect through ${fixtures.directory.cid}`) expect(pinset[0].cid.toString()).to.equal(fixtures.directory.files[1].cid) }) it('should list recursive pins for a specific hash', async () => { - const pinset = await all(ipfs.pin.ls(fixtures.files[0].cid, { type: 'recursive' })) + const pinset = await all(ipfs.pin.ls({ + paths: fixtures.files[0].cid, + type: 'recursive' + })) expect(pinset).to.have.lengthOf(1) expect(pinset[0].type).to.equal('recursive') expect(pinset[0].cid.toString()).to.equal(fixtures.files[0].cid) }) it('should list pins for multiple CIDs', async () => { - const pinset = await all(ipfs.pin.ls([fixtures.files[0].cid, fixtures.files[1].cid])) + const pinset = await all(ipfs.pin.ls({ + paths: [fixtures.files[0].cid, fixtures.files[1].cid] + })) const cids = pinset.map(p => p.cid.toString()) expect(cids).to.include(fixtures.files[0].cid) expect(cids).to.include(fixtures.files[1].cid) diff --git a/packages/ipfs-core-utils/package.json b/packages/ipfs-core-utils/package.json index bf675a47a5..a2d4d249d5 100644 --- a/packages/ipfs-core-utils/package.json +++ b/packages/ipfs-core-utils/package.json @@ -29,6 +29,7 @@ "license": "MIT", "dependencies": { "buffer": "^5.6.0", + "cids": "^0.8.0", "err-code": "^2.0.0", "ipfs-utils": "^2.2.2" }, diff --git a/packages/ipfs-core-utils/src/to-cid-and-path.js b/packages/ipfs-core-utils/src/to-cid-and-path.js new file mode 100644 index 0000000000..ab15475850 --- /dev/null +++ b/packages/ipfs-core-utils/src/to-cid-and-path.js @@ -0,0 +1,48 @@ +'use strict' + +const CID = require('cids') +const errCode = require('err-code') + +const IPFS_PREFIX = '/ipfs/' + +const toCidAndPath = (string) => { + if (Buffer.isBuffer(string)) { + try { + string = new CID(string) + } catch (err) { + throw errCode(err, 'ERR_INVALID_CID') + } + } + + if (CID.isCID(string)) { + return { + cid: string, + path: undefined + } + } + + if (string.startsWith(IPFS_PREFIX)) { + string = string.substring(IPFS_PREFIX.length) + } + + const parts = string.split('/') + let cid + let path + + try { + cid = new CID(parts.shift()) + } catch (err) { + throw errCode(err, 'ERR_INVALID_CID') + } + + if (parts.length) { + path = `/${parts.join('/')}` + } + + return { + cid, + path + } +} + +module.exports = toCidAndPath diff --git a/packages/ipfs-http-client/README.md b/packages/ipfs-http-client/README.md index 01e5ecc8a9..1a9b837ff9 100644 --- a/packages/ipfs-http-client/README.md +++ b/packages/ipfs-http-client/README.md @@ -280,7 +280,7 @@ const ipfs = ipfsClient({ host: '1.1.1.1', port: '80', apiPath: '/ipfs/api/v0' } ```javascript const bitswap = require('ipfs-http-client/src/bitswap')('/ip4/127.0.0.1/tcp/5001') -const list = await bitswap.wantlist(key) +const list = await bitswap.wantlist() // ... ``` diff --git a/packages/ipfs-http-client/src/bitswap/index.js b/packages/ipfs-http-client/src/bitswap/index.js index 5c8354498c..36d70b7db8 100644 --- a/packages/ipfs-http-client/src/bitswap/index.js +++ b/packages/ipfs-http-client/src/bitswap/index.js @@ -2,6 +2,7 @@ module.exports = config => ({ wantlist: require('./wantlist')(config), + wantlistForPeer: require('./wantlist-for-peer')(config), stat: require('./stat')(config), unwant: require('./unwant')(config) }) diff --git a/packages/ipfs-http-client/src/bitswap/wantlist-for-peer.js b/packages/ipfs-http-client/src/bitswap/wantlist-for-peer.js new file mode 100644 index 0000000000..b777ee7d6c --- /dev/null +++ b/packages/ipfs-http-client/src/bitswap/wantlist-for-peer.js @@ -0,0 +1,23 @@ +'use strict' + +const CID = require('cids') +const configure = require('../lib/configure') +const toUrlSearchParams = require('../lib/to-url-search-params') + +module.exports = configure(api => { + return async (peerId, options = {}) => { + peerId = typeof peerId === 'string' ? peerId : new CID(peerId).toString() + + const res = await (await api.post('bitswap/wantlist', { + timeout: options.timeout, + signal: options.signal, + searchParams: toUrlSearchParams({ + ...options, + peer: peerId + }), + headers: options.headers + })).json() + + return (res.Keys || []).map(k => new CID(k['/'])) + } +}) diff --git a/packages/ipfs-http-client/src/bitswap/wantlist.js b/packages/ipfs-http-client/src/bitswap/wantlist.js index d8357e7ac0..2599c7ed79 100644 --- a/packages/ipfs-http-client/src/bitswap/wantlist.js +++ b/packages/ipfs-http-client/src/bitswap/wantlist.js @@ -5,16 +5,7 @@ const configure = require('../lib/configure') const toUrlSearchParams = require('../lib/to-url-search-params') module.exports = configure(api => { - return async (peer, options = {}) => { - if (peer && (peer.timeout || peer.signal)) { - options = peer - peer = undefined - } - - if (peer) { - options.peer = typeof peer === 'string' ? peer : new CID(peer).toString() - } - + return async (options = {}) => { const res = await (await api.post('bitswap/wantlist', { timeout: options.timeout, signal: options.signal, diff --git a/packages/ipfs-http-client/src/bootstrap/clear.js b/packages/ipfs-http-client/src/bootstrap/clear.js new file mode 100644 index 0000000000..99d8091429 --- /dev/null +++ b/packages/ipfs-http-client/src/bootstrap/clear.js @@ -0,0 +1,20 @@ +'use strict' + +const configure = require('../lib/configure') +const toUrlSearchParams = require('../lib/to-url-search-params') + +module.exports = configure(api => { + return async (options = {}) => { + const res = await api.post('bootstrap/rm', { + timeout: options.timeout, + signal: options.signal, + searchParams: toUrlSearchParams({ + ...options, + all: true + }), + headers: options.headers + }) + + return res.json() + } +}) diff --git a/packages/ipfs-http-client/src/bootstrap/index.js b/packages/ipfs-http-client/src/bootstrap/index.js index 519a7161e0..3a1021d342 100644 --- a/packages/ipfs-http-client/src/bootstrap/index.js +++ b/packages/ipfs-http-client/src/bootstrap/index.js @@ -2,6 +2,8 @@ module.exports = config => ({ add: require('./add')(config), + clear: require('./clear')(config), rm: require('./rm')(config), + reset: require('./reset')(config), list: require('./list')(config) }) diff --git a/packages/ipfs-http-client/src/bootstrap/reset.js b/packages/ipfs-http-client/src/bootstrap/reset.js new file mode 100644 index 0000000000..9332aafc71 --- /dev/null +++ b/packages/ipfs-http-client/src/bootstrap/reset.js @@ -0,0 +1,20 @@ +'use strict' + +const configure = require('../lib/configure') +const toUrlSearchParams = require('../lib/to-url-search-params') + +module.exports = configure(api => { + return async (options = {}) => { + const res = await api.post('bootstrap/add', { + timeout: options.timeout, + signal: options.signal, + searchParams: toUrlSearchParams({ + ...options, + default: true + }), + headers: options.headers + }) + + return res.json() + } +}) diff --git a/packages/ipfs-http-client/src/dag/get.js b/packages/ipfs-http-client/src/dag/get.js index 2875aea8f6..cbc8e76f3d 100644 --- a/packages/ipfs-http-client/src/dag/get.js +++ b/packages/ipfs-http-client/src/dag/get.js @@ -15,13 +15,8 @@ module.exports = configure((api, options) => { const getBlock = require('../block/get')(options) const dagResolve = require('./resolve')(options) - return async (cid, path, options = {}) => { - if (path && typeof path === 'object') { - options = path - path = null - } - - const resolved = await dagResolve(cid, path, options) + return async (cid, options = {}) => { + const resolved = await dagResolve(cid, options) const block = await getBlock(resolved.cid, options) const dagResolver = resolvers[block.cid.codec] diff --git a/packages/ipfs-http-client/src/dag/resolve.js b/packages/ipfs-http-client/src/dag/resolve.js index acced6a42c..ba8c903846 100644 --- a/packages/ipfs-http-client/src/dag/resolve.js +++ b/packages/ipfs-http-client/src/dag/resolve.js @@ -5,17 +5,12 @@ const configure = require('../lib/configure') const toUrlSearchParams = require('../lib/to-url-search-params') module.exports = configure(api => { - return async (cid, path, options = {}) => { - if (path && typeof path === 'object') { - options = path - path = null - } - + return async (cid, options = {}) => { const res = await api.post('dag/resolve', { timeout: options.timeout, signal: options.signal, searchParams: toUrlSearchParams({ - arg: path ? [cid, path].join(path.startsWith('/') ? '' : '/') : `${cid}`, + arg: `${cid}${options.path ? `/${options.path}`.replace(/\/[/]+/g, '/') : ''}`, ...options }), headers: options.headers diff --git a/packages/ipfs-http-client/src/files/flush.js b/packages/ipfs-http-client/src/files/flush.js index cb97a6d98c..d9934be9ad 100644 --- a/packages/ipfs-http-client/src/files/flush.js +++ b/packages/ipfs-http-client/src/files/flush.js @@ -6,9 +6,8 @@ const toUrlSearchParams = require('../lib/to-url-search-params') module.exports = configure(api => { return async (path, options = {}) => { - if (typeof path !== 'string') { - options = path || {} - path = '/' + if (!path || typeof path !== 'string') { + throw new Error('ipfs.files.flush requires a path') } const res = await api.post('files/flush', { diff --git a/packages/ipfs-http-client/src/files/ls.js b/packages/ipfs-http-client/src/files/ls.js index 2e22ddcdb5..2420955e74 100644 --- a/packages/ipfs-http-client/src/files/ls.js +++ b/packages/ipfs-http-client/src/files/ls.js @@ -7,9 +7,8 @@ const toUrlSearchParams = require('../lib/to-url-search-params') module.exports = configure(api => { return async function * ls (path, options = {}) { - if (typeof path !== 'string') { - options = path || {} - path = '/' + if (!path || typeof path !== 'string') { + throw new Error('ipfs.files.ls requires a path') } const res = await api.post('files/ls', { diff --git a/packages/ipfs-http-client/src/object/new.js b/packages/ipfs-http-client/src/object/new.js index 6b3bb04ebc..f0ae4e5574 100644 --- a/packages/ipfs-http-client/src/object/new.js +++ b/packages/ipfs-http-client/src/object/new.js @@ -5,17 +5,12 @@ const configure = require('../lib/configure') const toUrlSearchParams = require('../lib/to-url-search-params') module.exports = configure(api => { - return async (template, options = {}) => { - if (typeof template !== 'string') { - options = template || {} - template = null - } - + return async (options = {}) => { const res = await api.post('object/new', { timeout: options.timeout, signal: options.signal, searchParams: toUrlSearchParams({ - arg: template, + arg: options.template, ...options }), headers: options.headers diff --git a/packages/ipfs-http-client/src/pin/ls.js b/packages/ipfs-http-client/src/pin/ls.js index 5fdc17386d..5133e3a568 100644 --- a/packages/ipfs-http-client/src/pin/ls.js +++ b/packages/ipfs-http-client/src/pin/ls.js @@ -5,20 +5,17 @@ const configure = require('../lib/configure') const toUrlSearchParams = require('../lib/to-url-search-params') module.exports = configure(api => { - return async function * ls (path, options = {}) { - if (path && (path.type || path.timeout)) { - options = path || {} - path = [] + return async function * ls (options = {}) { + if (options.paths) { + options.paths = Array.isArray(options.paths) ? options.paths : [options.paths] } - path = Array.isArray(path) ? path : [path] - const res = await api.post('pin/ls', { timeout: options.timeout, signal: options.signal, searchParams: toUrlSearchParams({ - arg: path.map(p => `${p}`), ...options, + arg: (options.paths || []).map(path => `${path}`), stream: true }), headers: options.headers diff --git a/packages/ipfs/package.json b/packages/ipfs/package.json index ed14eca677..54ec3d96db 100644 --- a/packages/ipfs/package.json +++ b/packages/ipfs/package.json @@ -117,6 +117,7 @@ "it-all": "^1.0.1", "it-concat": "^1.0.0", "it-drain": "^1.0.1", + "it-first": "^1.0.1", "it-glob": "0.0.8", "it-last": "^1.0.1", "it-map": "^1.0.0", @@ -182,7 +183,6 @@ "ipfs-interop": "^1.0.4", "ipfsd-ctl": "^4.1.1", "iso-random-stream": "^1.1.1", - "it-first": "^1.0.1", "it-to-buffer": "^1.0.0", "nanoid": "^3.0.2", "ncp": "^2.0.0", diff --git a/packages/ipfs/src/cli/commands/bitswap/wantlist.js b/packages/ipfs/src/cli/commands/bitswap/wantlist.js index 09991fea77..2f489eaf83 100644 --- a/packages/ipfs/src/cli/commands/bitswap/wantlist.js +++ b/packages/ipfs/src/cli/commands/bitswap/wantlist.js @@ -28,9 +28,18 @@ module.exports = { async handler ({ ctx, peer, cidBase, timeout }) { const { ipfs, print } = ctx - const list = await ipfs.bitswap.wantlist(peer, { - timeout - }) + let list + + if (peer) { + list = await ipfs.bitswap.wantlistForPeer(peer, { + timeout + }) + } else { + list = await ipfs.bitswap.wantlist({ + timeout + }) + } + list.forEach(cid => print(cidToString(cid, { base: cidBase, upgrade: false }))) } } diff --git a/packages/ipfs/src/cli/commands/bootstrap/add.js b/packages/ipfs/src/cli/commands/bootstrap/add.js index ec6c9a14e5..b43b45a298 100644 --- a/packages/ipfs/src/cli/commands/bootstrap/add.js +++ b/packages/ipfs/src/cli/commands/bootstrap/add.js @@ -20,10 +20,20 @@ module.exports = { }, async handler ({ ctx: { ipfs, print }, peer, default: defaultPeers, timeout }) { - const list = await ipfs.bootstrap.add(peer, { - default: defaultPeers, - timeout - }) + let list + + if (peer) { + list = await ipfs.bootstrap.add(peer, { + timeout + }) + } else if (defaultPeers) { + list = await ipfs.bootstrap.reset({ + timeout + }) + } else { + throw new Error('Please specify a peer or the --default flag') + } + list.Peers.forEach((peer) => print(peer)) } } diff --git a/packages/ipfs/src/cli/commands/bootstrap/rm.js b/packages/ipfs/src/cli/commands/bootstrap/rm.js index 60073504c4..ef9bab21e1 100644 --- a/packages/ipfs/src/cli/commands/bootstrap/rm.js +++ b/packages/ipfs/src/cli/commands/bootstrap/rm.js @@ -23,10 +23,20 @@ module.exports = { }, async handler ({ ctx: { ipfs, print }, all, peer, timeout }) { - const list = await ipfs.bootstrap.rm(peer, { - all, - timeout - }) + let list + + if (peer) { + list = await ipfs.bootstrap.rm(peer, { + timeout + }) + } else if (all) { + list = await ipfs.bootstrap.clear({ + timeout + }) + } else { + throw new Error('Please specify a peer or the --all flag') + } + list.Peers.forEach((peer) => print(peer)) } } diff --git a/packages/ipfs/src/cli/commands/dag/get.js b/packages/ipfs/src/cli/commands/dag/get.js index b2d3a5adc6..8506bd5a20 100644 --- a/packages/ipfs/src/cli/commands/dag/get.js +++ b/packages/ipfs/src/cli/commands/dag/get.js @@ -1,8 +1,8 @@ 'use strict' -const CID = require('cids') const parseDuration = require('parse-duration').default const { Buffer } = require('buffer') +const toCidAndPath = require('ipfs-core-utils/src/to-cid-and-path') module.exports = { command: 'get ', @@ -21,20 +21,22 @@ module.exports = { }, async handler ({ ctx: { ipfs, print }, cidpath, localResolve, timeout }) { - const refParts = cidpath.split('/') - const cidString = refParts[0] - const path = refParts.slice(1).join('/') - const cid = new CID(cidString) - const options = { localResolve, timeout } + const { + cid, path + } = toCidAndPath(cidpath) + let result try { - result = await ipfs.dag.get(cid, path, options) + result = await ipfs.dag.get(cid, { + ...options, + path + }) } catch (err) { return print(`dag get failed: ${err}`) } diff --git a/packages/ipfs/src/cli/commands/object/new.js b/packages/ipfs/src/cli/commands/object/new.js index db4b090fb4..7576448c76 100644 --- a/packages/ipfs/src/cli/commands/object/new.js +++ b/packages/ipfs/src/cli/commands/object/new.js @@ -22,7 +22,8 @@ module.exports = { }, async handler ({ ctx: { ipfs, print }, template, cidBase, timeout }) { - const cid = await ipfs.object.new(template, { + const cid = await ipfs.object.new({ + template, timeout }) print(cidToString(cid, { base: cidBase, upgrade: false })) diff --git a/packages/ipfs/src/cli/commands/pin/ls.js b/packages/ipfs/src/cli/commands/pin/ls.js index 3e31ff1b5f..5cf9147b76 100644 --- a/packages/ipfs/src/cli/commands/pin/ls.js +++ b/packages/ipfs/src/cli/commands/pin/ls.js @@ -43,8 +43,6 @@ module.exports = { }, async handler ({ ctx: { ipfs, print }, ipfsPath, type, quiet, cidBase, stream, timeout }) { - const paths = ipfsPath - const printPin = res => { let line = cidToString(res.cid, { base: cidBase }) if (!quiet) { @@ -54,11 +52,20 @@ module.exports = { } if (!stream) { - const pins = await all(ipfs.pin.ls(paths, { type, stream: false, timeout })) + const pins = await all(ipfs.pin.ls({ + paths: ipfsPath, + type, + stream: false, + timeout + })) return pins.forEach(printPin) } - for await (const res of ipfs.pin.ls(paths, { type, timeout })) { + for await (const res of ipfs.pin.ls({ + paths: ipfsPath, + type, + timeout + })) { printPin(res) } } diff --git a/packages/ipfs/src/core/components/bitswap/wantlist-for-peer.js b/packages/ipfs/src/core/components/bitswap/wantlist-for-peer.js new file mode 100644 index 0000000000..4eb4092cd3 --- /dev/null +++ b/packages/ipfs/src/core/components/bitswap/wantlist-for-peer.js @@ -0,0 +1,12 @@ +'use strict' + +const PeerId = require('peer-id') +const { withTimeoutOption } = require('../../utils') + +module.exports = ({ bitswap }) => { + return withTimeoutOption(async function wantlistForPeer (peerId, options = {}) { // eslint-disable-line require-await + const list = bitswap.wantlistForPeer(PeerId.createFromCID(peerId), options) + + return Array.from(list).map(e => e[1].cid) + }) +} diff --git a/packages/ipfs/src/core/components/bitswap/wantlist.js b/packages/ipfs/src/core/components/bitswap/wantlist.js index 44b366ef5b..13930dd166 100644 --- a/packages/ipfs/src/core/components/bitswap/wantlist.js +++ b/packages/ipfs/src/core/components/bitswap/wantlist.js @@ -1,19 +1,10 @@ 'use strict' -const PeerId = require('peer-id') -const CID = require('cids') const { withTimeoutOption } = require('../../utils') module.exports = ({ bitswap }) => { - return withTimeoutOption(async function wantlist (peerId, options = {}) { // eslint-disable-line require-await - if (peerId && !CID.isCID(peerId) && typeof peerId !== 'string' && !Buffer.isBuffer(peerId) && !PeerId.isPeerId(peerId)) { - options = peerId - peerId = null - } - - const list = peerId - ? bitswap.wantlistForPeer(PeerId.createFromCID(peerId)) - : bitswap.getWantlist(options) + return withTimeoutOption(async function wantlist (options = {}) { // eslint-disable-line require-await + const list = bitswap.getWantlist(options) return Array.from(list).map(e => e[1].cid) }) diff --git a/packages/ipfs/src/core/components/bootstrap/add.js b/packages/ipfs/src/core/components/bootstrap/add.js index 855c5b3698..e3fc4b914d 100644 --- a/packages/ipfs/src/core/components/bootstrap/add.js +++ b/packages/ipfs/src/core/components/bootstrap/add.js @@ -1,27 +1,24 @@ 'use strict' -const defaultConfig = require('../../runtime/config-nodejs.js') const { isValidMultiaddr } = require('./utils') const { withTimeoutOption } = require('../../utils') module.exports = ({ repo }) => { - return withTimeoutOption(async function add (multiaddr, options) { - options = options || {} - - if (multiaddr && !isValidMultiaddr(multiaddr)) { + return withTimeoutOption(async function add (multiaddr, options = {}) { + if (!isValidMultiaddr(multiaddr)) { throw new Error(`${multiaddr} is not a valid Multiaddr`) } - const config = await repo.config.getAll() - if (options.default) { - config.Bootstrap = defaultConfig().Bootstrap - } else if (multiaddr && config.Bootstrap.indexOf(multiaddr) === -1) { + const config = await repo.config.getAll(options) + + if (config.Bootstrap.indexOf(multiaddr) === -1) { config.Bootstrap.push(multiaddr) } + await repo.config.set(config) return { - Peers: options.default ? defaultConfig().Bootstrap : [multiaddr] + Peers: [multiaddr] } }) } diff --git a/packages/ipfs/src/core/components/bootstrap/clear.js b/packages/ipfs/src/core/components/bootstrap/clear.js new file mode 100644 index 0000000000..100e01964a --- /dev/null +++ b/packages/ipfs/src/core/components/bootstrap/clear.js @@ -0,0 +1,15 @@ +'use strict' + +const { withTimeoutOption } = require('../../utils') + +module.exports = ({ repo }) => { + return withTimeoutOption(async function clear (options = {}) { + const config = await repo.config.getAll(options) + const removed = config.Bootstrap || [] + config.Bootstrap = [] + + await repo.config.set(config) + + return { Peers: removed } + }) +} diff --git a/packages/ipfs/src/core/components/bootstrap/reset.js b/packages/ipfs/src/core/components/bootstrap/reset.js new file mode 100644 index 0000000000..23d4134965 --- /dev/null +++ b/packages/ipfs/src/core/components/bootstrap/reset.js @@ -0,0 +1,17 @@ +'use strict' + +const defaultConfig = require('../../runtime/config-nodejs.js') +const { withTimeoutOption } = require('../../utils') + +module.exports = ({ repo }) => { + return withTimeoutOption(async function reset (options = {}) { + const config = await repo.config.getAll(options) + config.Bootstrap = defaultConfig().Bootstrap + + await repo.config.set(config) + + return { + Peers: defaultConfig().Bootstrap + } + }) +} diff --git a/packages/ipfs/src/core/components/bootstrap/rm.js b/packages/ipfs/src/core/components/bootstrap/rm.js index c8a9b80fe0..63a135858c 100644 --- a/packages/ipfs/src/core/components/bootstrap/rm.js +++ b/packages/ipfs/src/core/components/bootstrap/rm.js @@ -4,29 +4,16 @@ const { isValidMultiaddr } = require('./utils') const { withTimeoutOption } = require('../../utils') module.exports = ({ repo }) => { - return withTimeoutOption(async function rm (multiaddr, options) { - options = options || {} - - if (multiaddr && !isValidMultiaddr(multiaddr)) { + return withTimeoutOption(async function rm (multiaddr, options = {}) { + if (!isValidMultiaddr(multiaddr)) { throw new Error(`${multiaddr} is not a valid Multiaddr`) } - let res = [] - const config = await repo.config.getAll() - - if (options.all) { - res = config.Bootstrap || [] - config.Bootstrap = [] - } else { - config.Bootstrap = (config.Bootstrap || []).filter(ma => ma !== multiaddr) - } + const config = await repo.config.getAll(options) + config.Bootstrap = (config.Bootstrap || []).filter(ma => ma !== multiaddr) await repo.config.set(config) - if (!options.all && multiaddr) { - res.push(multiaddr) - } - - return { Peers: res } + return { Peers: [multiaddr] } }) } diff --git a/packages/ipfs/src/core/components/dag/get.js b/packages/ipfs/src/core/components/dag/get.js index d4a11598d4..e3d1adf7d0 100644 --- a/packages/ipfs/src/core/components/dag/get.js +++ b/packages/ipfs/src/core/components/dag/get.js @@ -1,35 +1,36 @@ 'use strict' -const { parseArgs } = require('./utils') const { withTimeoutOption } = require('../../utils') +const first = require('it-first') +const last = require('it-last') +const toCidAndPath = require('ipfs-core-utils/src/to-cid-and-path') module.exports = ({ ipld, preload }) => { - return withTimeoutOption(async function get (cid, path, options) { - [cid, path, options] = parseArgs(cid, path, options) + return withTimeoutOption(async function get (ipfsPath, options = {}) { + const { + cid, + path + } = toCidAndPath(ipfsPath) + + if (path) { + options.path = path + } if (options.preload !== false) { preload(cid) } - if (path == null || path === '/') { - const value = await ipld.get(cid, options) - - return { - value, - remainderPath: '' + if (options.path) { + if (options.localResolve) { + return first(ipld.resolve(cid, options.path)) } - } else { - let result - - for await (const entry of ipld.resolve(cid, path)) { - if (options.localResolve) { - return entry - } - result = entry - } + return last(ipld.resolve(cid, options.path)) + } - return result + return { + value: await ipld.get(cid, options), + remainderPath: '' } }) } diff --git a/packages/ipfs/src/core/components/dag/resolve.js b/packages/ipfs/src/core/components/dag/resolve.js index dd863dd111..5c8e747084 100644 --- a/packages/ipfs/src/core/components/dag/resolve.js +++ b/packages/ipfs/src/core/components/dag/resolve.js @@ -1,16 +1,23 @@ 'use strict' -const { parseArgs } = require('./utils') const { withTimeoutOption } = require('../../utils') +const toCidAndPath = require('ipfs-core-utils/src/to-cid-and-path') module.exports = ({ ipld, preload }) => { - return withTimeoutOption(async function * resolve (cid, path, options) { // eslint-disable-line require-await - [cid, path, options] = parseArgs(cid, path, options) + return withTimeoutOption(async function * resolve (ipfsPath, options) { // eslint-disable-line require-await + const { + cid, + path + } = toCidAndPath(ipfsPath) + + if (path) { + options.path = path + } if (options.preload !== false) { preload(cid) } - yield * ipld.resolve(cid, path, { signal: options.signal }) + yield * ipld.resolve(cid, options.path, { signal: options.signal }) }) } diff --git a/packages/ipfs/src/core/components/dag/tree.js b/packages/ipfs/src/core/components/dag/tree.js index bab3380ece..0f0c223df1 100644 --- a/packages/ipfs/src/core/components/dag/tree.js +++ b/packages/ipfs/src/core/components/dag/tree.js @@ -1,16 +1,23 @@ 'use strict' -const { parseArgs } = require('./utils') const { withTimeoutOption } = require('../../utils') +const toCidAndPath = require('ipfs-core-utils/src/to-cid-and-path') module.exports = ({ ipld, preload }) => { - return withTimeoutOption(async function * tree (cid, path, options) { // eslint-disable-line require-await - [cid, path, options] = parseArgs(cid, path, options) + return withTimeoutOption(async function * tree (ipfsPath, options = {}) { // eslint-disable-line require-await + const { + cid, + path + } = toCidAndPath(ipfsPath) + + if (path) { + options.path = path + } if (options.preload !== false) { preload(cid) } - yield * ipld.tree(cid, path, options) + yield * ipld.tree(cid, options.path, options) }) } diff --git a/packages/ipfs/src/core/components/dag/utils.js b/packages/ipfs/src/core/components/dag/utils.js deleted file mode 100644 index 7f417223db..0000000000 --- a/packages/ipfs/src/core/components/dag/utils.js +++ /dev/null @@ -1,49 +0,0 @@ -'use strict' - -const CID = require('cids') -const errCode = require('err-code') -const { Buffer } = require('buffer') - -exports.parseArgs = (cid, path, options) => { - options = options || {} - - // Allow options in path position - if (path !== undefined && typeof path !== 'string') { - options = path - path = undefined - } - - if (typeof cid === 'string') { - if (cid.startsWith('/ipfs/')) { - cid = cid.substring(6) - } - - const split = cid.split('/') - - try { - cid = new CID(split[0]) - } catch (err) { - throw errCode(err, 'ERR_INVALID_CID') - } - - split.shift() - - if (split.length > 0) { - path = split.join('/') - } else { - path = path || '/' - } - } else if (Buffer.isBuffer(cid)) { - try { - cid = new CID(cid) - } catch (err) { - throw errCode(err, 'ERR_INVALID_CID') - } - } - - return [ - cid, - path, - options - ] -} diff --git a/packages/ipfs/src/core/components/files/flush.js b/packages/ipfs/src/core/components/files/flush.js index 899e3d9711..f3c5798cc2 100644 --- a/packages/ipfs/src/core/components/files/flush.js +++ b/packages/ipfs/src/core/components/files/flush.js @@ -9,16 +9,11 @@ const defaultOptions = { } module.exports = (context) => { - return withTimeoutOption(async function mfsFlush (path = '/', options = defaultOptions) { - if (path && typeof path !== 'string') { - options = path - path = '/' - } - + return withTimeoutOption(async function mfsFlush (path, options = {}) { options = applyDefaultOptions(options, defaultOptions) - const result = await stat(context)(path, options) + const { cid } = await stat(context)(path, options) - return result.cid + return cid }) } diff --git a/packages/ipfs/src/core/components/files/ls.js b/packages/ipfs/src/core/components/files/ls.js index 73f63fdb6d..0792efddf0 100644 --- a/packages/ipfs/src/core/components/files/ls.js +++ b/packages/ipfs/src/core/components/files/ls.js @@ -39,12 +39,7 @@ const toOutput = (fsEntry) => { } module.exports = (context) => { - return withTimeoutOption(async function * mfsLs (path = '/', options = {}) { - if (typeof path === 'object' && !(path instanceof String)) { - options = path - path = '/' - } - + return withTimeoutOption(async function * mfsLs (path, options = {}) { const mfsPath = await toMfsPath(context, path, options) const fsDir = await exporter(mfsPath.mfsPath, context.ipld) diff --git a/packages/ipfs/src/core/components/files/utils/to-mfs-path.js b/packages/ipfs/src/core/components/files/utils/to-mfs-path.js index ca218febfa..c5a23828af 100644 --- a/packages/ipfs/src/core/components/files/utils/to-mfs-path.js +++ b/packages/ipfs/src/core/components/files/utils/to-mfs-path.js @@ -4,6 +4,7 @@ const loadMfsRoot = require('./with-mfs-root') const toPathComponents = require('./to-path-components') const exporter = require('ipfs-unixfs-exporter') const errCode = require('err-code') +const CID = require('cids') const IPFS_PREFIX = 'ipfs' @@ -13,6 +14,10 @@ const toMfsPath = async (context, path, options) => { const root = await loadMfsRoot(context, options) paths = paths.map(path => { + if (CID.isCID(path)) { + path = `/ipfs/${path}` + } + path = (path || '').trim() path = path.replace(/(\/\/+)/g, '/') diff --git a/packages/ipfs/src/core/components/index.js b/packages/ipfs/src/core/components/index.js index 41f7d971f3..6b59eaf151 100644 --- a/packages/ipfs/src/core/components/index.js +++ b/packages/ipfs/src/core/components/index.js @@ -10,11 +10,14 @@ exports.block = { exports.bitswap = { stat: require('./bitswap/stat'), unwant: require('./bitswap/unwant'), - wantlist: require('./bitswap/wantlist') + wantlist: require('./bitswap/wantlist'), + wantlistForPeer: require('./bitswap/wantlist-for-peer') } exports.bootstrap = { add: require('./bootstrap/add'), + clear: require('./bootstrap/clear'), list: require('./bootstrap/list'), + reset: require('./bootstrap/reset'), rm: require('./bootstrap/rm') } exports.cat = require('./cat') diff --git a/packages/ipfs/src/core/components/init.js b/packages/ipfs/src/core/components/init.js index 7a0213eaea..40dc7c2363 100644 --- a/packages/ipfs/src/core/components/init.js +++ b/packages/ipfs/src/core/components/init.js @@ -323,7 +323,8 @@ function createApi ({ bitswap: { stat: notStarted, unwant: notStarted, - wantlist: notStarted + wantlist: notStarted, + wantlistForPeer: notStarted }, bootstrap: { add: Components.bootstrap.add({ repo }), diff --git a/packages/ipfs/src/core/components/object/new.js b/packages/ipfs/src/core/components/object/new.js index 935de73dbc..4c0ebaedee 100644 --- a/packages/ipfs/src/core/components/object/new.js +++ b/packages/ipfs/src/core/components/object/new.js @@ -8,19 +8,11 @@ const { withTimeoutOption } = require('../../utils') const { Buffer } = require('buffer') module.exports = ({ ipld, preload }) => { - return withTimeoutOption(async function _new (template, options) { - options = options || {} - - // allow options in the template position - if (template && typeof template !== 'string') { - options = template - template = null - } - + return withTimeoutOption(async function _new (options = {}) { let data - if (template) { - if (template === 'unixfs-dir') { + if (options.template) { + if (options.template === 'unixfs-dir') { data = (new Unixfs('directory')).marshal() } else { throw new Error('unknown template') @@ -33,7 +25,8 @@ module.exports = ({ ipld, preload }) => { const cid = await ipld.put(node, multicodec.DAG_PB, { cidVersion: 0, - hashAlg: multicodec.SHA2_256 + hashAlg: multicodec.SHA2_256, + signal: options.signal }) if (options.preload !== false) { diff --git a/packages/ipfs/src/core/components/pin/ls.js b/packages/ipfs/src/core/components/pin/ls.js index 11d4f89bb1..7240a1ac35 100644 --- a/packages/ipfs/src/core/components/pin/ls.js +++ b/packages/ipfs/src/core/components/pin/ls.js @@ -11,16 +11,9 @@ const { withTimeoutOption } = require('../../utils') const PIN_LS_CONCURRENCY = 8 module.exports = ({ pinManager, dag }) => { - return withTimeoutOption(async function * ls (paths, options) { - options = options || {} - + return withTimeoutOption(async function * ls (options = {}) { let type = PinTypes.all - if (paths && !Array.isArray(paths) && !CID.isCID(paths) && typeof paths !== 'string') { - options = paths - paths = null - } - if (options.type) { type = options.type if (typeof options.type === 'string') { @@ -32,17 +25,17 @@ module.exports = ({ pinManager, dag }) => { } } - if (paths) { - paths = Array.isArray(paths) ? paths : [paths] + if (options.paths) { + options.paths = Array.isArray(options.paths) ? options.paths : [options.paths] // check the pinned state of specific hashes - const cids = await resolvePath(dag, paths) + const cids = await resolvePath(dag, options.paths) yield * parallelMap(PIN_LS_CONCURRENCY, async cid => { const { reason, pinned } = await pinManager.isPinnedWithType(cid, type) if (!pinned) { - throw new Error(`path '${paths[cids.indexOf(cid)]}' is not pinned`) + throw new Error(`path '${options.paths[cids.indexOf(cid)]}' is not pinned`) } if (reason === PinTypes.direct || reason === PinTypes.recursive) { diff --git a/packages/ipfs/src/core/components/pin/pin-manager.js b/packages/ipfs/src/core/components/pin/pin-manager.js index d2e4cb961a..edcc887dcd 100644 --- a/packages/ipfs/src/core/components/pin/pin-manager.js +++ b/packages/ipfs/src/core/components/pin/pin-manager.js @@ -154,7 +154,7 @@ class PinManager { } const mh = await this.repo.datastore.get(PIN_DS_KEY) - const pinRoot = await this.dag.get(new CID(mh), '', { preload: false }) + const pinRoot = await this.dag.get(new CID(mh), { preload: false }) const [ rKeys, dKeys diff --git a/packages/ipfs/src/core/components/pin/pin-set.js b/packages/ipfs/src/core/components/pin/pin-set.js index 77a54ccc07..8f1e17a7a8 100644 --- a/packages/ipfs/src/core/components/pin/pin-set.js +++ b/packages/ipfs/src/core/components/pin/pin-set.js @@ -261,7 +261,7 @@ exports = module.exports = function (dag) { throw new Error('No link found with name ' + name) } - const res = await dag.get(link.Hash, '', { preload: false }) + const res = await dag.get(link.Hash, { preload: false }) const keys = [] const stepPin = link => keys.push(link.Hash) @@ -284,7 +284,7 @@ exports = module.exports = function (dag) { stepBin(link, idx, pbh.data) // walk the links of this fanout bin - const res = await dag.get(linkHash, '', { preload: false }) + const res = await dag.get(link.Hash, { preload: false }) await pinSet.walkItems(res.value, { stepPin, stepBin }) } @@ -305,7 +305,7 @@ exports = module.exports = function (dag) { for (const topLevelLink of rootNode.Links) { cids.push(topLevelLink.Hash) - const res = await dag.get(topLevelLink.Hash, '', { preload: false }) + const res = await dag.get(topLevelLink.Hash, { preload: false }) await pinSet.walkItems(res.value, { stepBin }) } diff --git a/packages/ipfs/src/core/components/start.js b/packages/ipfs/src/core/components/start.js index 54b31f2842..215e19e0b6 100644 --- a/packages/ipfs/src/core/components/start.js +++ b/packages/ipfs/src/core/components/start.js @@ -240,12 +240,15 @@ function createApi ({ bitswap: { stat: Components.bitswap.stat({ bitswap }), unwant: Components.bitswap.unwant({ bitswap }), - wantlist: Components.bitswap.wantlist({ bitswap }) + wantlist: Components.bitswap.wantlist({ bitswap }), + wantlistForPeer: Components.bitswap.wantlistForPeer({ bitswap }) }, block, bootstrap: { add: Components.bootstrap.add({ repo }), + clear: Components.bootstrap.clear({ repo }), list: Components.bootstrap.list({ repo }), + reset: Components.bootstrap.reset({ repo }), rm: Components.bootstrap.rm({ repo }) }, cat: Components.cat({ ipld, preload }), diff --git a/packages/ipfs/src/core/components/stop.js b/packages/ipfs/src/core/components/stop.js index fdd9756637..5463a160c0 100644 --- a/packages/ipfs/src/core/components/stop.js +++ b/packages/ipfs/src/core/components/stop.js @@ -127,12 +127,15 @@ function createApi ({ bitswap: { stat: notStarted, unwant: notStarted, - wantlist: notStarted + wantlist: notStarted, + wantlistForPeer: notStarted }, block, bootstrap: { add: Components.bootstrap.add({ repo }), + clear: Components.bootstrap.clear({ repo }), list: Components.bootstrap.list({ repo }), + reset: Components.bootstrap.reset({ repo }), rm: Components.bootstrap.rm({ repo }) }, cat: Components.cat({ ipld, preload }), diff --git a/packages/ipfs/src/core/utils.js b/packages/ipfs/src/core/utils.js index 03ee734996..8e2e4507ae 100644 --- a/packages/ipfs/src/core/utils.js +++ b/packages/ipfs/src/core/utils.js @@ -10,6 +10,7 @@ const Key = require('interface-datastore').Key const { TimeoutError } = require('./errors') const ERR_BAD_PATH = 'ERR_BAD_PATH' + exports.OFFLINE_ERROR = 'This command must be run in online mode. Try running \'ipfs daemon\' first.' exports.MFS_FILE_TYPES = { diff --git a/packages/ipfs/src/http/api/resources/bitswap.js b/packages/ipfs/src/http/api/resources/bitswap.js index 3df56a791f..8d5bbba9dd 100644 --- a/packages/ipfs/src/http/api/resources/bitswap.js +++ b/packages/ipfs/src/http/api/resources/bitswap.js @@ -38,10 +38,19 @@ exports.wantlist = { } } = request - const list = await ipfs.bitswap.wantlist(peer, { - signal, - timeout - }) + let list + + if (peer) { + list = await ipfs.bitswap.wantlistForPeer(peer, { + signal, + timeout + }) + } else { + list = await ipfs.bitswap.wantlist({ + signal, + timeout + }) + } return h.response({ Keys: list.map(cid => ({ diff --git a/packages/ipfs/src/http/api/resources/bootstrap.js b/packages/ipfs/src/http/api/resources/bootstrap.js index 9021943b65..541f6d9a2b 100644 --- a/packages/ipfs/src/http/api/resources/bootstrap.js +++ b/packages/ipfs/src/http/api/resources/bootstrap.js @@ -1,5 +1,6 @@ 'use strict' +const Boom = require('@hapi/boom') const Joi = require('../../utils/joi') exports.list = { @@ -72,11 +73,22 @@ exports.add = { } } = request - const list = await ipfs.bootstrap.add(addr, { - default: def || !addr, - signal, - timeout - }) + let list + + if (def) { + list = await ipfs.bootstrap.reset({ + signal, + timeout + }) + } else if (addr) { + list = await ipfs.bootstrap.add(addr, { + signal, + timeout + }) + } else { + throw Boom.badRequest('arg is required') + } + return h.response(list) } } @@ -108,8 +120,7 @@ exports.addDefault = { } } = request - const list = await ipfs.bootstrap.add(null, { - default: true, + const list = await ipfs.bootstrap.reset({ signal, timeout }) @@ -152,11 +163,22 @@ exports.rm = { } } = request - const list = await ipfs.bootstrap.rm(addr, { - all: all || !addr, - signal, - timeout - }) + let list + + if (all) { + list = await ipfs.bootstrap.clear({ + signal, + timeout + }) + } else if (addr) { + list = await ipfs.bootstrap.rm(addr, { + signal, + timeout + }) + } else { + throw Boom.badRequest('arg is required') + } + return h.response(list) } } @@ -188,11 +210,11 @@ exports.rmAll = { } } = request - const list = await ipfs.bootstrap.rm(null, { - all: true, + const list = await ipfs.bootstrap.clear({ signal, timeout }) + return h.response(list) } } diff --git a/packages/ipfs/src/http/api/resources/dag.js b/packages/ipfs/src/http/api/resources/dag.js index 7bf05cfb88..4faaf9f728 100644 --- a/packages/ipfs/src/http/api/resources/dag.js +++ b/packages/ipfs/src/http/api/resources/dag.js @@ -125,7 +125,8 @@ exports.get = { let result try { - result = await ipfs.dag.get(cid, path, { + result = await ipfs.dag.get(cid, { + path, signal, timeout }) @@ -296,7 +297,8 @@ exports.resolve = { query: Joi.object().keys({ arg: Joi.cidAndPath().required(), cidBase: Joi.cidBase(), - timeout: Joi.timeout() + timeout: Joi.timeout(), + path: Joi.string() }) .rename('cid-base', 'cidBase', { override: true, @@ -320,7 +322,8 @@ exports.resolve = { path }, cidBase, - timeout + timeout, + path: queryPath } } = request @@ -328,10 +331,11 @@ exports.resolve = { // along with the path inside that node as the remainder path try { let lastCid = cid - let lastRemainderPath = path + let lastRemainderPath = path || queryPath - if (path) { - for await (const { value, remainderPath } of ipfs.dag.resolve(lastCid, path, { + if (lastRemainderPath) { + for await (const { value, remainderPath } of ipfs.dag.resolve(lastCid, { + path: lastRemainderPath, signal, timeout })) { diff --git a/packages/ipfs/src/http/api/resources/object.js b/packages/ipfs/src/http/api/resources/object.js index 506aa4c6e2..4b2067234d 100644 --- a/packages/ipfs/src/http/api/resources/object.js +++ b/packages/ipfs/src/http/api/resources/object.js @@ -87,7 +87,8 @@ exports.new = { let cid, node try { - cid = await ipfs.object.new(template, { + cid = await ipfs.object.new({ + template, signal, timeout }) diff --git a/packages/ipfs/src/http/api/resources/pin.js b/packages/ipfs/src/http/api/resources/pin.js index eadfc45ebb..b97ce5e8a5 100644 --- a/packages/ipfs/src/http/api/resources/pin.js +++ b/packages/ipfs/src/http/api/resources/pin.js @@ -52,13 +52,16 @@ exports.ls = { } } = request + const source = ipfs.pin.ls({ + paths, + type, + signal, + timeout + }) + if (!stream) { const res = await pipe( - ipfs.pin.ls(paths, { - type, - signal, - timeout - }), + source, reduce((res, { type, cid }) => { res.Keys[cidToString(cid, { base: cidBase })] = { Type: type } return res @@ -69,11 +72,7 @@ exports.ls = { } return streamResponse(request, h, () => pipe( - ipfs.pin.ls(paths, { - type, - signal, - timeout - }), + source, map(({ type, cid }) => ({ Type: type, Cid: cidToString(cid, { base: cidBase }) })), ndjson.stringify )) diff --git a/packages/ipfs/src/http/utils/joi.js b/packages/ipfs/src/http/utils/joi.js index e0384b85e3..360b402cb6 100644 --- a/packages/ipfs/src/http/utils/joi.js +++ b/packages/ipfs/src/http/utils/joi.js @@ -5,6 +5,7 @@ const CID = require('cids') const parseDuration = require('parse-duration').default const multiaddr = require('multiaddr') const multibase = require('multibase') +const toCidAndPath = require('ipfs-core-utils/src/to-cid-and-path') const toIpfsPath = (value) => { if (!value) { @@ -112,19 +113,7 @@ module.exports = Joi return } - value = value.toString() - - if (!value.startsWith('/ipfs/')) { - value = `/ipfs/${value}` - } - - // section after /ipfs/ should be a valid CID - const parts = value.split('/') - - return { - cid: new CID(parts[2]), - path: parts.slice(3).join('/') - } + return toCidAndPath(value) } } }, diff --git a/packages/ipfs/test/cli/bitswap.js b/packages/ipfs/test/cli/bitswap.js index a366ac7ba3..e8b48bd630 100644 --- a/packages/ipfs/test/cli/bitswap.js +++ b/packages/ipfs/test/cli/bitswap.js @@ -18,6 +18,7 @@ describe('bitswap', () => { ipfs = { bitswap: { wantlist: sinon.stub(), + wantlistForPeer: sinon.stub(), stat: sinon.stub(), unwant: sinon.stub() } @@ -30,7 +31,7 @@ describe('bitswap', () => { } it('should return the wantlist', async () => { - ipfs.bitswap.wantlist.withArgs(undefined, defaultOptions).resolves([ + ipfs.bitswap.wantlist.withArgs(defaultOptions).resolves([ new CID(key0), new CID(key1) ]) @@ -41,7 +42,9 @@ describe('bitswap', () => { }) it('should get wantlist with CIDs encoded in specified base', async () => { - ipfs.bitswap.wantlist.withArgs(undefined, defaultOptions).resolves([ + ipfs.bitswap.wantlist.withArgs({ + ...defaultOptions + }).resolves([ new CID(key0), new CID(key1) ]) @@ -51,14 +54,24 @@ describe('bitswap', () => { }) it('wantlist peerid', async () => { - ipfs.bitswap.wantlist.withArgs(peerId, defaultOptions).resolves([]) + ipfs.bitswap.wantlistForPeer.withArgs(peerId, defaultOptions).resolves([]) const out = await cli(`bitswap wantlist ${peerId}`, { ipfs }) expect(out).to.eql('') }) it('wantlist with a timeout', async () => { - ipfs.bitswap.wantlist.withArgs(peerId, { + ipfs.bitswap.wantlist.withArgs({ + ...defaultOptions, + timeout: 1000 + }).resolves([]) + + const out = await cli('bitswap wantlist --timeout=1s', { ipfs }) + expect(out).to.eql('') + }) + + it('wantlist for peer with a timeout', async () => { + ipfs.bitswap.wantlistForPeer.withArgs(peerId, { ...defaultOptions, timeout: 1000 }).resolves([]) diff --git a/packages/ipfs/test/cli/bootstrap.js b/packages/ipfs/test/cli/bootstrap.js index b0a72da840..0d1ba24951 100644 --- a/packages/ipfs/test/cli/bootstrap.js +++ b/packages/ipfs/test/cli/bootstrap.js @@ -14,7 +14,9 @@ describe('bootstrap', () => { bootstrap: { add: sinon.stub(), list: sinon.stub(), - rm: sinon.stub() + rm: sinon.stub(), + clear: sinon.stub(), + reset: sinon.stub() } } }) @@ -45,15 +47,11 @@ describe('bootstrap', () => { describe('add', () => { const defaultOptions = { - default: false, timeout: undefined } it('add default', async () => { - ipfs.bootstrap.add.withArgs(undefined, { - ...defaultOptions, - default: true - }).returns({ + ipfs.bootstrap.reset.withArgs(defaultOptions).returns({ Peers: defaultList }) @@ -112,7 +110,6 @@ describe('bootstrap', () => { describe('rm', () => { const defaultOptions = { - all: false, timeout: undefined } @@ -128,10 +125,7 @@ describe('bootstrap', () => { }) it('should remove all bootstrap nodes', async () => { - ipfs.bootstrap.rm.withArgs(undefined, { - ...defaultOptions, - all: true - }).returns({ + ipfs.bootstrap.clear.withArgs(defaultOptions).returns({ Peers: defaultList }) diff --git a/packages/ipfs/test/cli/dag.js b/packages/ipfs/test/cli/dag.js index 899a4a1c71..7a9694363d 100644 --- a/packages/ipfs/test/cli/dag.js +++ b/packages/ipfs/test/cli/dag.js @@ -26,18 +26,50 @@ describe('dag', () => { describe('get', () => { const defaultOptions = { localResolve: false, - timeout: undefined + timeout: undefined, + path: undefined } it('should get a node', async () => { - const path = 'parentHash' const result = { value: Buffer.from('hello world') } - ipfs.dag.get.withArgs(cid, path, defaultOptions).returns(result) + ipfs.dag.get.withArgs(cid, defaultOptions).returns(result) + + const out = await cli(`dag get ${cid}`, { ipfs }) + + expect(out).to.be.eql('0x' + result.value.toString('hex') + '\n') + }) + + it('should get a node with a deep path', async () => { + const path = '/parentHash' + const result = { + value: Buffer.from('hello world') + } + + ipfs.dag.get.withArgs(cid, { + ...defaultOptions, + path + }).returns(result) + + const out = await cli(`dag get ${cid}${path}`, { ipfs }) + + expect(out).to.be.eql('0x' + result.value.toString('hex') + '\n') + }) + + it('should get a node with a deep path and an ipfs prefix', async () => { + const path = '/parentHash' + const result = { + value: Buffer.from('hello world') + } + + ipfs.dag.get.withArgs(cid, { + ...defaultOptions, + path + }).returns(result) - const out = await cli(`dag get ${cid}/${path}`, { ipfs }) + const out = await cli(`dag get /ipfs/${cid}${path}`, { ipfs }) expect(out).to.be.eql('0x' + result.value.toString('hex') + '\n') }) @@ -47,7 +79,7 @@ describe('dag', () => { value: Buffer.from('hello world') } - ipfs.dag.get.withArgs(cid, '', { + ipfs.dag.get.withArgs(cid, { ...defaultOptions, localResolve: true }).returns(result) @@ -64,7 +96,7 @@ describe('dag', () => { value: Buffer.from('hello world') } - ipfs.dag.get.withArgs(cid, '', { + ipfs.dag.get.withArgs(cid, { ...defaultOptions, timeout: 1000 }).returns(result) diff --git a/packages/ipfs/test/cli/object.js b/packages/ipfs/test/cli/object.js index 051009c03c..a52339df9b 100644 --- a/packages/ipfs/test/cli/object.js +++ b/packages/ipfs/test/cli/object.js @@ -39,25 +39,29 @@ describe('object', () => { describe('new', () => { const defaultOptions = { + template: undefined, timeout: undefined } it('should create a new object', async () => { - ipfs.object.new.withArgs(undefined, defaultOptions).resolves(cid) + ipfs.object.new.withArgs(defaultOptions).resolves(cid) const out = await cli('object new', { ipfs }) expect(out).to.equal(`${cid}\n`) }) it('new unixfs-dir', async () => { - ipfs.object.new.withArgs('unixfs-dir', defaultOptions).resolves(cid) + ipfs.object.new.withArgs({ + ...defaultOptions, + template: 'unixfs-dir' + }).resolves(cid) const out = await cli('object new unixfs-dir', { ipfs }) expect(out).to.equal(`${cid}\n`) }) it('new with a timeout', async () => { - ipfs.object.new.withArgs(undefined, { + ipfs.object.new.withArgs({ ...defaultOptions, timeout: 1000 }).resolves(cid) @@ -67,7 +71,7 @@ describe('object', () => { }) it('should new and print CID encoded in specified base', async () => { - ipfs.object.new.withArgs(undefined, defaultOptions).resolves(cid.toV1()) + ipfs.object.new.withArgs(defaultOptions).resolves(cid.toV1()) const out = await cli('object new --cid-base=base64', { ipfs }) expect(out).to.equal( diff --git a/packages/ipfs/test/cli/pin.js b/packages/ipfs/test/cli/pin.js index 864805976d..3e74992abe 100644 --- a/packages/ipfs/test/cli/pin.js +++ b/packages/ipfs/test/cli/pin.js @@ -26,7 +26,8 @@ describe('pin', () => { pin: { rm: sinon.stub(), add: sinon.stub(), - ls: sinon.stub() + ls: sinon.stub(), + query: sinon.stub() } } }) @@ -159,11 +160,12 @@ describe('pin', () => { const defaultOptions = { type: 'all', stream: false, - timeout: undefined + timeout: undefined, + paths: undefined } it('lists all pins when no hash is passed', async () => { - ipfs.pin.ls.withArgs(undefined, defaultOptions).returns([{ + ipfs.pin.ls.withArgs(defaultOptions).returns([{ cid: new CID(pins.root), type: 'recursive' }]) @@ -173,7 +175,10 @@ describe('pin', () => { }) it('handles multiple hashes', async () => { - ipfs.pin.ls.withArgs([pins.root, pins.solarWiki], defaultOptions).returns([{ + ipfs.pin.ls.withArgs({ + ...defaultOptions, + paths: [pins.root, pins.solarWiki] + }).returns([{ cid: new CID(pins.root), type: 'recursive' }, { @@ -186,7 +191,7 @@ describe('pin', () => { }) it('can print quietly', async () => { - ipfs.pin.ls.withArgs(undefined, defaultOptions).returns([{ + ipfs.pin.ls.withArgs(defaultOptions).returns([{ cid: new CID(pins.root), type: 'recursive' }]) @@ -196,7 +201,7 @@ describe('pin', () => { }) it('can print quietly (short option)', async () => { - ipfs.pin.ls.withArgs(undefined, defaultOptions).returns([{ + ipfs.pin.ls.withArgs(defaultOptions).returns([{ cid: new CID(pins.root), type: 'recursive' }]) @@ -206,7 +211,7 @@ describe('pin', () => { }) it('should ls and print CIDs encoded in specified base', async () => { - ipfs.pin.ls.withArgs(undefined, defaultOptions).returns([{ + ipfs.pin.ls.withArgs(defaultOptions).returns([{ cid: new CID(pins.root).toV1(), type: 'recursive' }]) @@ -216,7 +221,7 @@ describe('pin', () => { }) it('lists all pins with a timeout', async () => { - ipfs.pin.ls.withArgs(undefined, { + ipfs.pin.ls.withArgs({ ...defaultOptions, timeout: 1000 }).returns([{ diff --git a/packages/ipfs/test/core/pin.js b/packages/ipfs/test/core/pin.js index e9c8ecda0c..01f45f30ad 100644 --- a/packages/ipfs/test/core/pin.js +++ b/packages/ipfs/test/core/pin.js @@ -46,7 +46,7 @@ describe('pin', function () { async function isPinnedWithType (path, type) { try { - for await (const _ of pin.ls(path, { type })) { // eslint-disable-line no-unused-vars + for await (const _ of pin.ls({ paths: path, type })) { // eslint-disable-line no-unused-vars return true } return false @@ -199,7 +199,7 @@ describe('pin', function () { }) it('should list pins of a particular CID', async () => { - const out = await all(pin.ls(pins.mercuryDir)) + const out = await all(pin.ls({ paths: pins.mercuryDir })) expect(out[0].cid.toString()).to.eql(pins.mercuryDir) }) @@ -274,7 +274,7 @@ describe('pin', function () { }) it('should list direct pins for CID', async () => { - const out = await all(pin.ls(pins.mercuryDir, { type: 'direct' })) + const out = await all(pin.ls({ paths: pins.mercuryDir, type: 'direct' })) expect(out).to.have.deep.members([ { @@ -285,7 +285,7 @@ describe('pin', function () { }) it('should list direct pins for path', async () => { - const out = await all(pin.ls(`/ipfs/${pins.root}/mercury/`, { type: 'direct' })) + const out = await all(pin.ls({ paths: `/ipfs/${pins.root}/mercury/`, type: 'direct' })) expect(out).to.have.deep.members([ { @@ -296,17 +296,17 @@ describe('pin', function () { }) it('should list direct pins for path (no match)', () => { - return expect(all(pin.ls(`/ipfs/${pins.root}/mercury/wiki.md`, { type: 'direct' }))) + return expect(all(pin.ls({ paths: `/ipfs/${pins.root}/mercury/wiki.md`, type: 'direct' }))) .to.eventually.be.rejected() }) it('should list direct pins for CID (no match)', () => { - return expect(all(pin.ls(pins.root, { type: 'direct' }))) + return expect(all(pin.ls({ paths: pins.root, type: 'direct' }))) .to.eventually.be.rejected() }) it('should list recursive pins for CID', async () => { - const out = await all(pin.ls(pins.root, { type: 'recursive' })) + const out = await all(pin.ls({ paths: pins.root, type: 'recursive' })) expect(out).to.have.deep.members([ { @@ -317,12 +317,12 @@ describe('pin', function () { }) it('should list recursive pins for CID (no match)', () => { - return expect(all(pin.ls(pins.mercuryDir, { type: 'recursive' }))) + return expect(all(pin.ls({ paths: pins.mercuryDir, type: 'recursive' }))) .to.eventually.be.rejected() }) it('should list indirect pins for CID', async () => { - const out = await all(pin.ls(pins.solarWiki, { type: 'indirect' })) + const out = await all(pin.ls({ paths: pins.solarWiki, type: 'indirect' })) expect(out).to.have.deep.members([ { @@ -333,7 +333,7 @@ describe('pin', function () { }) it('should list indirect pins for CID (no match)', () => { - return expect(all(pin.ls(pins.root, { type: 'indirect' }))) + return expect(all(pin.ls({ paths: pins.root, type: 'indirect' }))) .to.eventually.be.rejected() }) }) diff --git a/packages/ipfs/test/core/preload.spec.js b/packages/ipfs/test/core/preload.spec.js index a6c1308f5b..8e57233e81 100644 --- a/packages/ipfs/test/core/preload.spec.js +++ b/packages/ipfs/test/core/preload.spec.js @@ -201,7 +201,7 @@ describe('preload', () => { it('should preload content retrieved with object.get', async function () { this.timeout(50 * 1000) - const cid = await ipfs.object.new(null, { preload: false }) + const cid = await ipfs.object.new({ preload: false }) await ipfs.object.get(cid) await MockPreloadNode.waitForCids(cid) }) diff --git a/packages/ipfs/test/http-api/inject/bitswap.js b/packages/ipfs/test/http-api/inject/bitswap.js index 6c2716a896..e4e29d15ad 100644 --- a/packages/ipfs/test/http-api/inject/bitswap.js +++ b/packages/ipfs/test/http-api/inject/bitswap.js @@ -16,6 +16,7 @@ describe('/bitswap', () => { ipfs = { bitswap: { wantlist: sinon.stub(), + wantlistForPeer: sinon.stub(), stat: sinon.stub(), unwant: sinon.stub() } @@ -33,7 +34,7 @@ describe('/bitswap', () => { }) it('/wantlist', async () => { - ipfs.bitswap.wantlist.withArgs(undefined, defaultOptions).returns([ + ipfs.bitswap.wantlist.withArgs(defaultOptions).returns([ cid ]) @@ -47,7 +48,7 @@ describe('/bitswap', () => { }) it('/wantlist?timeout=1s', async () => { - ipfs.bitswap.wantlist.withArgs(undefined, { + ipfs.bitswap.wantlist.withArgs({ ...defaultOptions, timeout: 1000 }).returns([ @@ -65,7 +66,7 @@ describe('/bitswap', () => { // TODO: unskip after switch to v1 CIDs by default it.skip('/wantlist?cid-base=base64', async () => { - ipfs.bitswap.wantlist.withArgs(undefined, defaultOptions).returns([ + ipfs.bitswap.wantlist.withArgs(defaultOptions).returns([ cid ]) @@ -79,7 +80,7 @@ describe('/bitswap', () => { }) it('/wantlist?cid-base=invalid', async () => { - ipfs.bitswap.wantlist.withArgs(undefined, defaultOptions).returns([ + ipfs.bitswap.wantlist.withArgs(defaultOptions).returns([ cid ]) @@ -95,7 +96,7 @@ describe('/bitswap', () => { it('/wantlist?peer=QmSnuWmxptJZdLJpKRarxBMS2Ju2oANVrgbr2xWbie9b2D', async () => { const peerId = 'QmSnuWmxptJZdLJpKRarxBMS2Ju2oANVrgbr2xWbie9b2D' - ipfs.bitswap.wantlist.withArgs(peerId, defaultOptions).returns([ + ipfs.bitswap.wantlistForPeer.withArgs(peerId, defaultOptions).returns([ cid ]) @@ -108,6 +109,25 @@ describe('/bitswap', () => { expect(res).to.have.nested.property('result.Keys').that.deep.includes({ '/': cid.toString() }) }) + it('/wantlist?peer=QmSnuWmxptJZdLJpKRarxBMS2Ju2oANVrgbr2xWbie9b2D&timeout=1s', async () => { + const peerId = 'QmSnuWmxptJZdLJpKRarxBMS2Ju2oANVrgbr2xWbie9b2D' + + ipfs.bitswap.wantlistForPeer.withArgs(peerId, { + ...defaultOptions, + timeout: 1000 + }).returns([ + cid + ]) + + const res = await http({ + method: 'POST', + url: `/api/v0/bitswap/wantlist?peer=${peerId}&timeout=1s` + }, { ipfs }) + + expect(res).to.have.property('statusCode', 200) + expect(res).to.have.nested.property('result.Keys').that.deep.includes({ '/': cid.toString() }) + }) + it('/wantlist?peer=invalid', async () => { const peerId = 'invalid' diff --git a/packages/ipfs/test/http-api/inject/bootstrap.js b/packages/ipfs/test/http-api/inject/bootstrap.js index f8d8e49a1c..999c8602d0 100644 --- a/packages/ipfs/test/http-api/inject/bootstrap.js +++ b/packages/ipfs/test/http-api/inject/bootstrap.js @@ -18,7 +18,9 @@ describe('/bootstrap', () => { bootstrap: { list: sinon.stub(), add: sinon.stub(), - rm: sinon.stub() + rm: sinon.stub(), + clear: sinon.stub(), + reset: sinon.stub() } } }) @@ -81,7 +83,6 @@ describe('/bootstrap', () => { describe('/add', () => { const defaultOptions = { - default: false, signal: sinon.match.instanceOf(AbortSignal), timeout: undefined } @@ -110,11 +111,27 @@ describe('/bootstrap', () => { expect(res).to.have.deep.nested.property('result.Peers', [validIp4]) }) - it('restores default', async () => { - ipfs.bootstrap.add.withArgs(undefined, { + it('adds a bootstrapper with a timeout', async () => { + ipfs.bootstrap.add.withArgs(validIp4, { ...defaultOptions, - default: true + timeout: 1000 }).returns({ + Peers: [ + validIp4 + ] + }) + + const res = await http({ + method: 'POST', + url: `/api/v0/bootstrap/add?arg=${validIp4}&timeout=1s` + }, { ipfs }) + + expect(res).to.have.property('statusCode', 200) + expect(res).to.have.deep.nested.property('result.Peers', [validIp4]) + }) + + it('restores default', async () => { + ipfs.bootstrap.reset.withArgs(defaultOptions).returns({ Peers: defaultList }) @@ -128,9 +145,8 @@ describe('/bootstrap', () => { }) it('accepts a timeout', async () => { - ipfs.bootstrap.add.withArgs(undefined, { + ipfs.bootstrap.reset.withArgs({ ...defaultOptions, - default: true, timeout: 1000 }).returns({ Peers: defaultList @@ -147,7 +163,6 @@ describe('/bootstrap', () => { describe('/default', () => { const defaultOptions = { - default: true, signal: sinon.match.instanceOf(AbortSignal), timeout: undefined } @@ -157,7 +172,7 @@ describe('/bootstrap', () => { }) it('restores default', async () => { - ipfs.bootstrap.add.withArgs(null, defaultOptions).returns({ + ipfs.bootstrap.reset.withArgs(defaultOptions).returns({ Peers: defaultList }) @@ -171,7 +186,7 @@ describe('/bootstrap', () => { }) it('accepts a timeout', async () => { - ipfs.bootstrap.add.withArgs(null, { + ipfs.bootstrap.reset.withArgs({ ...defaultOptions, timeout: 1000 }).returns({ @@ -191,7 +206,6 @@ describe('/bootstrap', () => { describe('/rm', () => { const defaultOptions = { - all: false, signal: sinon.match.instanceOf(AbortSignal), timeout: undefined } @@ -220,11 +234,27 @@ describe('/bootstrap', () => { expect(res).to.have.deep.nested.property('result.Peers', [validIp4]) }) - it('removes all bootstrappers', async () => { - ipfs.bootstrap.rm.withArgs(undefined, { + it('removes a bootstrapper with a timeout', async () => { + ipfs.bootstrap.rm.withArgs(validIp4, { ...defaultOptions, - all: true + timeout: 1000 }).returns({ + Peers: [ + validIp4 + ] + }) + + const res = await http({ + method: 'POST', + url: `/api/v0/bootstrap/rm?arg=${validIp4}&timeout=1s` + }, { ipfs }) + + expect(res).to.have.property('statusCode', 200) + expect(res).to.have.deep.nested.property('result.Peers', [validIp4]) + }) + + it('removes all bootstrappers', async () => { + ipfs.bootstrap.clear.withArgs(defaultOptions).returns({ Peers: defaultList }) @@ -238,9 +268,8 @@ describe('/bootstrap', () => { }) it('accepts a timeout', async () => { - ipfs.bootstrap.rm.withArgs(undefined, { + ipfs.bootstrap.clear.withArgs({ ...defaultOptions, - all: true, timeout: 1000 }).returns({ Peers: defaultList @@ -257,7 +286,6 @@ describe('/bootstrap', () => { describe('/all', () => { const defaultOptions = { - all: true, signal: sinon.match.instanceOf(AbortSignal), timeout: undefined } @@ -267,7 +295,7 @@ describe('/bootstrap', () => { }) it('removes all bootstrappers', async () => { - ipfs.bootstrap.rm.withArgs(null, defaultOptions).returns({ + ipfs.bootstrap.clear.withArgs(defaultOptions).returns({ Peers: defaultList }) @@ -281,7 +309,7 @@ describe('/bootstrap', () => { }) it('accepts a timeout', async () => { - ipfs.bootstrap.rm.withArgs(null, { + ipfs.bootstrap.clear.withArgs({ ...defaultOptions, timeout: 1000 }).returns({ diff --git a/packages/ipfs/test/http-api/inject/dag.js b/packages/ipfs/test/http-api/inject/dag.js index 170443563b..f3cbca2785 100644 --- a/packages/ipfs/test/http-api/inject/dag.js +++ b/packages/ipfs/test/http-api/inject/dag.js @@ -45,7 +45,8 @@ describe('/dag', () => { describe('/get', () => { const defaultOptions = { signal: sinon.match.instanceOf(AbortSignal), - timeout: undefined + timeout: undefined, + path: undefined } it('only accepts POST', () => { @@ -72,7 +73,7 @@ describe('/dag', () => { it('returns value', async () => { const node = new DAGNode(Buffer.from([]), []) - ipfs.dag.get.withArgs(cid, '', defaultOptions).returns({ value: node }) + ipfs.dag.get.withArgs(cid, defaultOptions).returns({ value: node }) const res = await http({ method: 'POST', @@ -86,7 +87,7 @@ describe('/dag', () => { it('uses text encoding for data by default', async () => { const node = new DAGNode(Buffer.from([0, 1, 2, 3]), []) - ipfs.dag.get.withArgs(cid, '', defaultOptions).returns({ value: node }) + ipfs.dag.get.withArgs(cid, defaultOptions).returns({ value: node }) const res = await http({ method: 'POST', @@ -101,7 +102,7 @@ describe('/dag', () => { it('overrides data encoding', async () => { const node = new DAGNode(Buffer.from([0, 1, 2, 3]), []) - ipfs.dag.get.withArgs(cid, '', defaultOptions).returns({ value: node }) + ipfs.dag.get.withArgs(cid, defaultOptions).returns({ value: node }) const res = await http({ method: 'POST', @@ -114,7 +115,10 @@ describe('/dag', () => { }) it('returns value with a path as part of the cid', async () => { - ipfs.dag.get.withArgs(cid, 'foo', defaultOptions).returns({ value: 'bar' }) + ipfs.dag.get.withArgs(cid, { + ...defaultOptions, + path: '/foo' + }).returns({ value: 'bar' }) const res = await http({ method: 'POST', @@ -127,7 +131,10 @@ describe('/dag', () => { it('returns value with a path as part of the cid for dag-pb nodes', async () => { const node = new DAGNode(Buffer.from([0, 1, 2, 3]), []) - ipfs.dag.get.withArgs(cid, 'Data', defaultOptions).returns({ value: node.Data }) + ipfs.dag.get.withArgs(cid, { + ...defaultOptions, + path: '/Data' + }).returns({ value: node.Data }) const res = await http({ method: 'POST', @@ -145,7 +152,7 @@ describe('/dag', () => { qux: Buffer.from([0, 1, 2, 3]) } } - ipfs.dag.get.withArgs(cid, '', defaultOptions).returns({ value: node }) + ipfs.dag.get.withArgs(cid, defaultOptions).returns({ value: node }) const res = await http({ method: 'POST', @@ -161,7 +168,7 @@ describe('/dag', () => { foo: 'bar', baz: Buffer.from([0, 1, 2, 3]) } - ipfs.dag.get.withArgs(cid, '', defaultOptions).returns({ value: node }) + ipfs.dag.get.withArgs(cid, defaultOptions).returns({ value: node }) const res = await http({ method: 'POST', @@ -176,7 +183,7 @@ describe('/dag', () => { const node = { foo: 'bar' } - ipfs.dag.get.withArgs(cid, '', { + ipfs.dag.get.withArgs(cid, { ...defaultOptions, timeout: 1000 }).returns({ value: node }) @@ -309,7 +316,8 @@ describe('/dag', () => { describe('/resolve', () => { const defaultOptions = { signal: sinon.match.instanceOf(AbortSignal), - timeout: undefined + timeout: undefined, + path: undefined } it('only accepts POST', () => { @@ -326,7 +334,7 @@ describe('/dag', () => { }) it('resolves a node', async () => { - ipfs.dag.resolve.withArgs(cid, '', defaultOptions).returns([{ + ipfs.dag.resolve.withArgs(cid, defaultOptions).returns([{ value: cid, remainderPath: '' }]) @@ -341,12 +349,32 @@ describe('/dag', () => { expect(res).to.have.nested.property('result.RemPath', '') }) + it('resolves a node with a path arg', async () => { + ipfs.dag.resolve.withArgs(cid, { + ...defaultOptions, + path: '/foo' + }).returns([{ + value: cid, + remainderPath: '' + }]) + + const res = await http({ + method: 'POST', + url: `/api/v0/dag/resolve?arg=${cid.toString()}&path=/foo` + }, { ipfs }) + + expect(res).to.have.property('statusCode', 200) + expect(res).to.have.deep.nested.property('result.Cid', { '/': cid.toString() }) + expect(res).to.have.nested.property('result.RemPath', '') + }) + it('returns the remainder path from within the resolved node', async () => { - ipfs.dag.resolve.withArgs(cid, 'foo', defaultOptions).returns([{ - value: { - value: cid, - remainderPath: 'foo' - } + ipfs.dag.resolve.withArgs(cid, { + ...defaultOptions, + path: '/foo' + }).returns([{ + value: cid, + remainderPath: 'foo' }]) const res = await http({ @@ -360,7 +388,10 @@ describe('/dag', () => { }) it('returns an error when the path is not available', async () => { - ipfs.dag.resolve.withArgs(cid, 'bar', defaultOptions).throws(new Error('Not found')) + ipfs.dag.resolve.withArgs(cid, { + ...defaultOptions, + path: '/bar' + }).throws(new Error('Not found')) const res = await http({ method: 'POST', @@ -374,7 +405,10 @@ describe('/dag', () => { it('resolves across multiple nodes, returning the CID of the last node traversed', async () => { const cid2 = new CID('QmUBdnXXPyoDFXj3Hj39dNJ5VkN3QFRskXxcGaYFBB8CNA') - ipfs.dag.resolve.withArgs(cid, 'foo/bar', defaultOptions).returns([{ + ipfs.dag.resolve.withArgs(cid, { + ...defaultOptions, + path: '/foo/bar' + }).returns([{ value: cid, remainderPath: 'foo' }, { @@ -393,7 +427,7 @@ describe('/dag', () => { }) it('accepts a timeout', async () => { - ipfs.dag.resolve.withArgs(cid, '', { + ipfs.dag.resolve.withArgs(cid, { ...defaultOptions, timeout: 1000 }).returns([{ diff --git a/packages/ipfs/test/http-api/inject/object.js b/packages/ipfs/test/http-api/inject/object.js index 65ecf9fd4c..5cacebeee8 100644 --- a/packages/ipfs/test/http-api/inject/object.js +++ b/packages/ipfs/test/http-api/inject/object.js @@ -63,7 +63,10 @@ describe('/object', () => { }) it('returns value', async () => { - ipfs.object.new.withArgs(undefined, defaultOptions).returns(cid) + ipfs.object.new.withArgs({ + ...defaultOptions, + template: undefined + }).returns(cid) ipfs.object.get.withArgs(cid, defaultOptions).returns(emptyDirectoryNode) const res = await http({ @@ -79,7 +82,10 @@ describe('/object', () => { it('should create an object with the passed template', async () => { const template = 'unixfs-dir' - ipfs.object.new.withArgs(template, defaultOptions).returns(cid) + ipfs.object.new.withArgs({ + ...defaultOptions, + template + }).returns(cid) ipfs.object.get.withArgs(cid, defaultOptions).returns(emptyDirectoryNode) const res = await http({ @@ -95,7 +101,10 @@ describe('/object', () => { it('should not reate an object with an invalid template', async () => { const template = 'derp' - ipfs.object.new.withArgs(template, defaultOptions).returns(cid) + ipfs.object.new.withArgs({ + ...defaultOptions, + template + }).returns(cid) ipfs.object.get.withArgs(cid, defaultOptions).returns(emptyDirectoryNode) const res = await http({ @@ -108,7 +117,10 @@ describe('/object', () => { // TODO: unskip after switch to v1 CIDs by default it.skip('should create a new object and return a base64 encoded CID', async () => { - ipfs.object.new.withArgs(undefined, defaultOptions).returns(cid) + ipfs.object.new.withArgs({ + ...defaultOptions, + template: undefined + }).returns(cid) ipfs.object.get.withArgs(cid, defaultOptions).returns(emptyDirectoryNode) const res = await http({ @@ -131,8 +143,9 @@ describe('/object', () => { }) it('accepts a timeout', async () => { - ipfs.object.new.withArgs(undefined, { + ipfs.object.new.withArgs({ ...defaultOptions, + template: undefined, timeout: 1000 }).returns(cid) ipfs.object.get.withArgs(cid, { diff --git a/packages/ipfs/test/http-api/inject/pin.js b/packages/ipfs/test/http-api/inject/pin.js index 367eafede6..5d636054fb 100644 --- a/packages/ipfs/test/http-api/inject/pin.js +++ b/packages/ipfs/test/http-api/inject/pin.js @@ -21,7 +21,8 @@ describe('/pin', () => { pin: { ls: sinon.stub(), add: sinon.stub(), - rm: sinon.stub() + rm: sinon.stub(), + query: sinon.stub() } } }) @@ -220,7 +221,8 @@ describe('/pin', () => { const defaultOptions = { type: 'all', signal: sinon.match.instanceOf(AbortSignal), - timeout: undefined + timeout: undefined, + paths: undefined } it('only accepts POST', () => { @@ -237,7 +239,7 @@ describe('/pin', () => { }) it('finds all pinned objects', async () => { - ipfs.pin.ls.withArgs(undefined, defaultOptions).returns([{ + ipfs.pin.ls.withArgs(defaultOptions).returns([{ cid, type: 'recursive' }]) @@ -252,7 +254,7 @@ describe('/pin', () => { }) it('finds all pinned objects streaming', async () => { - ipfs.pin.ls.withArgs(undefined, defaultOptions).returns([{ + ipfs.pin.ls.withArgs(defaultOptions).returns([{ cid: cid, type: 'recursive' }, { @@ -273,7 +275,10 @@ describe('/pin', () => { }) it('finds specific pinned objects', async () => { - ipfs.pin.ls.withArgs([`${cid}`], defaultOptions).returns([{ + ipfs.pin.ls.withArgs({ + ...defaultOptions, + paths: [`${cid}`] + }).returns([{ cid, type: 'recursive' }]) @@ -292,7 +297,7 @@ describe('/pin', () => { }) it('finds pins of type', async () => { - ipfs.pin.ls.withArgs(undefined, { + ipfs.pin.ls.withArgs({ ...defaultOptions, type: 'direct' }).returns([{ @@ -314,7 +319,7 @@ describe('/pin', () => { }) it('should list pins and return base64 encoded CIDs', async () => { - ipfs.pin.ls.withArgs(undefined, defaultOptions).returns([{ + ipfs.pin.ls.withArgs(defaultOptions).returns([{ cid, type: 'direct' }]) @@ -343,7 +348,7 @@ describe('/pin', () => { }) it('accepts a timeout', async () => { - ipfs.pin.ls.withArgs(undefined, { + ipfs.pin.ls.withArgs({ ...defaultOptions, timeout: 1000 }).returns([{