diff --git a/docs/CONFIG.md b/docs/CONFIG.md index 2980292b79..130121088e 100644 --- a/docs/CONFIG.md +++ b/docs/CONFIG.md @@ -252,7 +252,7 @@ The "basic" connection manager tries to keep between `LowWater` and `HighWater` 1. Keeping all connections until `HighWater` connections is reached. 2. Once `HighWater` is reached, it closes connections until `LowWater` is reached. -**Example:** +### Example ```json { diff --git a/docs/core-api/BITSWAP.md b/docs/core-api/BITSWAP.md index 7320cedce8..9de51472ab 100644 --- a/docs/core-api/BITSWAP.md +++ b/docs/core-api/BITSWAP.md @@ -1,21 +1,47 @@ -# Bitswap API +# Bitswap API + +- [`ipfs.bitswap.wantlist([peerId,] [options])`](#ipfsbitswapwantlistpeerid-options) + - [Parameters](#parameters) + - [Options](#options) + - [Returns](#returns) + - [Example](#example) +- [`ipfs.bitswap.unwant(cids, [options])`](#ipfsbitswapunwantcids-options) + - [Parameters](#parameters-1) + - [Options](#options-1) + - [Returns](#returns-1) + - [Example](#example-1) +- [`ipfs.bitswap.stat([options])`](#ipfsbitswapstatoptions) + - [Parameters](#parameters-2) + - [Options](#options-2) + - [Returns](#returns-2) + - [Example](#example-2) + +## `ipfs.bitswap.wantlist([peerId,] [options])` -* [bitswap.wantlist](#bitswapwantlist) -* [bitswap.stat](#bitswapstat) +> Returns the wantlist, optionally filtered by peer ID -### `bitswap.wantlist` +### Parameters -> Returns the wantlist, optionally filtered by peer ID +| Name | Type | Description | +| ---- | ---- | ----------- | +| peerId | [PeerId][], [CID][], `String` or `Buffer` | An optional peer ID to return the wantlist for | + +### Options + +An optional object which may have the following keys: -#### `ipfs.bitswap.wantlist([peerId])` +| 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** +### Returns | Type | Description | | -------- | -------- | -| `Promise` | An array of [CID][cid]s currently in the wantlist | +| `Promise` | An array of [CID][]s currently in the wantlist | -**Example:** +### Example ```JavaScript const list = await ipfs.bitswap.wantlist() @@ -29,15 +55,67 @@ console.log(list2) A great source of [examples][] can be found in the tests for this API. -#### `bitswap.stat` +## `ipfs.bitswap.unwant(cids, [options])` -> Show diagnostic information on the bitswap agent. +> Removes one or more CIDs from the wantlist + +### Parameters + +| Name | Type | Description | +| ---- | ---- | ----------- | +| cids | A [CID][] or Array of [CID][]s | The CIDs to remove from the wantlist | + +### 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` | A promise that resolves once the request is complete | + +### Example + +```JavaScript +let list = await ipfs.bitswap.wantlist() +console.log(list) +// [ CID('QmHash') ] + +await ipfs.bitswap.unwant(cid) + +list = await ipfs.bitswap.wantlist() +console.log(list) +// [] +``` + +A great source of [examples][] can be found in the tests for this API. + +## `ipfs.bitswap.stat([options])` -##### `ipfs.bitswap.stat()` +> Show diagnostic information on the bitswap agent. Note: `bitswap.stat` and `stats.bitswap` can be used interchangeably. -**Returns** +### 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 | | -------- | -------- | @@ -55,7 +133,7 @@ The returned object contains the following keys: - `dupBlksReceived` is a [BigNumber Int][1] - `dupDataReceived` is a [BigNumber Int][1] -**Example:** +### Example ```JavaScript const stats = await ipfs.bitswap.stat() @@ -81,3 +159,5 @@ A great source of [examples][] can be found in the tests for this API. [1]: https://github.com/MikeMcl/bignumber.js/ [examples]: https://github.com/ipfs/js-ipfs/blob/master/packages/interface-ipfs-core/src/bitswap [cid]: https://www.npmjs.com/package/cids +[peerid]: https://www.npmjs.com/package/peer-id +[AbortSignal]: https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal \ No newline at end of file diff --git a/docs/core-api/BLOCK.md b/docs/core-api/BLOCK.md index 8f8a54d90a..5df394b33b 100644 --- a/docs/core-api/BLOCK.md +++ b/docs/core-api/BLOCK.md @@ -1,29 +1,52 @@ -# Block API +# Block API + +- [`ipfs.block.get(cid, [options])`](#ipfsblockgetcid-options) + - [Parameters](#parameters) + - [Options](#options) + - [Returns](#returns) + - [Example](#example) +- [`ipfs.block.put(block, [options])`](#ipfsblockputblock-options) + - [Parameters](#parameters-1) + - [Options](#options-1) + - [Returns](#returns-1) + - [Example](#example-1) +- [`ipfs.block.rm(cid, [options])`](#ipfsblockrmcid-options) + - [Parameters](#parameters-2) + - [Options](#options-2) + - [Returns](#returns-2) + - [Example](#example-2) +- [`ipfs.block.stat(cid, [options])`](#ipfsblockstatcid-options) + - [Parameters](#parameters-3) + - [Options](#options-3) + - [Returns](#returns-3) + - [Example](#example-3) + +## `ipfs.block.get(cid, [options])` -* [block.get](#blockget) -* [block.put](#blockput) -* [block.rm](#blockrm) -* [block.stat](#blockstat) +> Get a raw IPFS block. -#### `block.get` +### Parameters -> Get a raw IPFS block. +| Name | Type | Description | +| ---- | ---- | ----------- | +| cid | [CID][], `String` or `Buffer` | A CID that corresponds to the desired block | -##### `ipfs.block.get(cid, [options])` +### Options -`cid` is a [cid][cid] which can be passed as: +An optional object which may have the following keys: -- Buffer, the raw Buffer of the cid -- CID, a CID instance -- String, the base58 encoded version of the multihash +| 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** +### Returns | Type | Description | | -------- | -------- | | `Promise` | A [Block][block] type object, containing both the data and the hash of the block | -**Example:** +### Example ```JavaScript const block = await ipfs.block.get(cid) @@ -32,43 +55,44 @@ console.log(block.data) A great source of [examples][] can be found in the tests for this API. -#### `block.put` +## `ipfs.block.put(block, [options])` > Stores input as an IPFS block. -##### `ipfs.block.put(block, [options])` - -Where `block` can be: +### Parameters -- `Buffer` - the raw bytes of the Block -- [`Block`][block] instance +| Name | Type | Description | +| ---- | ---- | ----------- | +| block | A `Buffer` or [Block][] instance | The block or data to store | -and `options` is an Object that can contain the following properties: +### Options -- `cid` - a [cid][cid] which can be passed as: - - Buffer, the raw Buffer of the cid - - CID, a CID instance - - String, the base58 encoded version of the multihash -- format -- mhtype -- mhlen -- version +An optional object which may have the following keys: -if no options are passed, it defaults to `{ format: 'dag-pb', mhtype: 'sha2-256', version: 0 }` +| Name | Type | Default | Description | +| ---- | ---- | ------- | ----------- | +| cid | [CID][] | `undefined` | A CID to store the block under | +| format | `String` | `'dag-pb'` | The codec to use to create the CID | +| mhtype | `String` | `sha2-256` | The hashing algorithm to use to create the CID | +| mhlen | `Number` | | | +| version | `Number` | 0 | The version to use to create the CID | +| pin | `boolean` | false | If true, pin added blocks recursively | +| 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 you pass a [`Block`][block] instance as the block parameter, you don't need to pass options, as the block instance will carry the CID value as a property. -**Returns** +### Returns | Type | Description | | -------- | -------- | | `Promise` | A [Block][block] type object, containing both the data and the hash of the block | -**Example:** +### Example ```JavaScript // Defaults -const buf = new Buffer('a serialized object') +const buf = Buffer.from('a serialized object') const block = await ipfs.block.put(buf) @@ -81,7 +105,7 @@ console.log(block.cid.toString()) // With custom format and hashtype through CID const CID = require('cids') -const buf = new Buffer('another serialized object') +const buf = Buffer.from('another serialized object') const cid = new CID(1, 'dag-pb', multihash) const block = await ipfs.block.put(blob, cid) @@ -96,25 +120,28 @@ console.log(block.cid.toString()) A great source of [examples][] can be found in the tests for this API. -#### `block.rm` +## `ipfs.block.rm(cid, [options])` > Remove one or more IPFS block(s). -##### `ipfs.block.rm(cid, [options])` +### Parameters -`cid` is a [cid][cid] which can be passed as: +| Name | Type | Description | +| ---- | ---- | ----------- | +| cid | A [CID][] or Array of [CID][]s | Blocks corresponding to the passed CID(s) will be removed | -- Buffer, the raw Buffer of the cid -- CID, a CID instance -- String, the base58 encoded version of the multihash -- Array, list of CIDs in any of the above three formats +### Options -`options` is an Object that can contain the following properties: +An optional object which may have the following keys: -- `force` (boolean): Ignores nonexistent blocks. -- `quiet` (boolean): write minimal output +| Name | Type | Default | Description | +| ---- | ---- | ------- | ----------- | +| force | `boolean` | `false` | Ignores nonexistent blocks | +| quiet | `boolean` | `false | Write minimal output | +| 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** +### Returns | Type | Description | | -------- | -------- | @@ -131,7 +158,7 @@ Each object yielded is of the form: Note: If an error string is present for a given object, the block with that hash was not removed and the string will contain the reason why, for example if the block was pinned. -**Example:** +### Example ```JavaScript for await (const result of ipfs.block.rm(cid)) { @@ -141,19 +168,26 @@ for await (const result of ipfs.block.rm(cid)) { A great source of [examples][] can be found in the tests for this API. -#### `block.stat` +## `ipfs.block.stat(cid, [options])` > Print information of a raw IPFS block. -##### `ipfs.block.stat(cid)` +### Parameters + +| Name | Type | Description | +| ---- | ---- | ----------- | +| cid | A [CID][] or Array of [CID][]s | The stats of the passed CID will be returned | + +### Options -`cid` is a [cid][cid] which can be passed as: +An optional object which may have the following keys: -- `Buffer`, the raw Buffer of the multihash (or of and encoded version) -- `String`, the toString version of the multihash (or of an encoded version) -- CID, a CID instance +| 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** +### Returns | Type | Description | | -------- | -------- | @@ -168,7 +202,7 @@ the returned object has the following keys: } ``` -**Example:** +### Example ```JavaScript const multihashStr = 'QmQULBtTjNcMwMr4VMNknnVv3RpytrLSdgpvMcTnfNhrBJ' @@ -188,4 +222,5 @@ A great source of [examples][] can be found in the tests for this API. [block]: https://github.com/ipfs/js-ipfs-block [multihash]: https://github.com/multiformats/multihash [examples]: https://github.com/ipfs/js-ipfs/blob/master/packages/interface-ipfs-core/src/block +[AbortSignal]: https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal [cid]: https://www.npmjs.com/package/cids diff --git a/docs/core-api/BOOTSTRAP.md b/docs/core-api/BOOTSTRAP.md index 35d5d59a8a..1d1baa44b1 100644 --- a/docs/core-api/BOOTSTRAP.md +++ b/docs/core-api/BOOTSTRAP.md @@ -1,27 +1,50 @@ -# Bootstrap API +# Bootstrap API -> Manipulates the `bootstrap list`, which contains - the addresses of the bootstrap nodes. These are the trusted peers from - which to learn about other peers in the network. +> Manipulates the bootstrap list, which contains the addresses of the bootstrap nodes. These are the trusted peers from which to learn about other peers in the network. -> Only edit this list if you understand the risks of adding or removing nodes +Warning: your node requires bootstrappers to join the network and find other peers. -* [bootstrap.add](#bootstrapadd) -* [bootstrap.list](#bootstraplist) -* [bootstrap.rm](#bootstraprm) +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 })`. -#### `bootstrap.add` +- [`ipfs.bootstrap.add([addr,] [options])`](#ipfsbootstrapaddaddr-options) + - [Parameters](#parameters) + - [Options](#options) + - [Returns](#returns) + - [Example](#example) +- [`ipfs.bootstrap.list([options])`](#ipfsbootstraplistoptions) + - [Parameters](#parameters-1) + - [Options](#options-1) + - [Returns](#returns-1) + - [Example](#example-1) +- [`ipfs.bootstrap.rm([addr,] [options])`](#ipfsbootstraprmaddr-options) + - [Parameters](#parameters-2) + - [Options](#options-2) + - [Returns](#returns-2) + - [Example](#example-2) + +## `ipfs.bootstrap.add([addr,] [options])` > Add a peer address to the bootstrap list -##### `ipfs.bootstrap.add(addr, [options])` +### Parameters + +| Name | Type | Description | +| ---- | ---- | ----------- | +| addr | [MultiAddr][] | The address of a network peer. If omitted the `default` option must be passed as `true`. | + +### Options -- `addr` is a [multiaddr](https://github.com/multiformats/js-multiaddr) to a peer node -- `options.default` if true, add the default peers to the list +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** +### Returns | Type | Description | | -------- | -------- | @@ -35,7 +58,7 @@ example of the returned object: } ``` -**Example:** +### Example ```JavaScript const validIp4 = '/ip4/104....9z' @@ -48,13 +71,24 @@ console.log(res.Peers) A great source of [examples][] can be found in the tests for this API. -#### `bootstrap.list` +## `ipfs.bootstrap.list([options])` > List all peer addresses in the bootstrap list -##### `ipfs.bootstrap.list()` +### Parameters + +None + +### Options -**Returns** +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 | | -------- | -------- | @@ -68,7 +102,7 @@ example of the returned object: } ``` -**Example:** +### Example ```JavaScript const res = await ipfs.bootstrap.list() @@ -79,18 +113,29 @@ console.log(res.Peers) A great source of [examples][] can be found in the tests for this API. -#### `bootstrap.rm` +## `ipfs.bootstrap.rm([addr,] [options])` > Remove a peer address from the bootstrap list -##### `ipfs.bootstrap.rm(peer, [options])` +### Parameters + +| Name | Type | Description | +| ---- | ---- | ----------- | +| addr | [MultiAddr][] | The address of a network peer. If omitted the `all` option must be passed as `true`. | + +### Options + +An optional object which may have the following keys: -- `addr` is a [multiaddr](https://github.com/multiformats/js-multiaddr) to a peer node -- `options.all` if true, remove all peers from the list +| 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** +### Returns | Type | Description | | -------- | -------- | @@ -102,7 +147,7 @@ Note: If passing the `all` option, `addr` is an optional parameter (may be `unde } ``` -**Example:** +### Example ```JavaScript const res = await ipfs.bootstrap.rm(null, { all: true }) @@ -114,3 +159,5 @@ console.log(res.Peers) A great source of [examples][] can be found in the tests for this API. [examples]: https://github.com/ipfs/js-ipfs/blob/master/packages/interface-ipfs-core/src/bootstrap +[MultiAddr]: https://github.com/multiformats/js-multiaddr +[AbortSignal]: https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal diff --git a/docs/core-api/CONFIG.md b/docs/core-api/CONFIG.md index 121fda9de9..7dc627b64e 100644 --- a/docs/core-api/CONFIG.md +++ b/docs/core-api/CONFIG.md @@ -1,26 +1,56 @@ -# Config API +# Config API + +- [`ipfs.config.get([key,] [options])`](#ipfsconfiggetkey-options) + - [Parameters](#parameters) + - [Options](#options) + - [Example](#example) +- [`ipfs.config.set(key, value, [options])`](#ipfsconfigsetkey-value-options) + - [Parameters](#parameters-1) + - [Options](#options-1) + - [Returns](#returns) + - [Example](#example-1) +- [`ipfs.config.replace(config, [options])`](#ipfsconfigreplaceconfig-options) + - [Parameters](#parameters-2) + - [Options](#options-2) + - [Returns](#returns-1) + - [Example](#example-2) +- [`ipfs.config.profiles.list([options])`](#ipfsconfigprofileslistoptions) + - [Parameters](#parameters-3) + - [Options](#options-3) + - [Returns](#returns-2) + - [Example](#example-3) +- [`ipfs.config.profiles.apply(name, [options])`](#ipfsconfigprofilesapplyname-options) + - [Parameters](#parameters-4) + - [Options](#options-4) + - [Returns](#returns-3) + - [Example](#example-4) + +## `ipfs.config.get([key,] [options])` -* [config.get](#configget) -* [config.set](#configset) -* [config.replace](#configreplace) -* [config.profiles.list](#configprofileslist) -* [config.profiles.apply](#configprofilesapply) +> Returns the currently being used config. If the daemon is off, it returns the stored config. -#### `config.get` +### Parameters -> Returns the currently being used config. If the daemon is off, it returns the stored config. +| Name | Type | Description | +| ---- | ---- | ----------- | +| key | `String` | The key of the value that should be fetched from the config file. If no key is passed, then the whole config will be returned. | -##### `ipfs.config.get([key])` +### Options -`key` is the key of the value that should be fetched from the config file. If no key is passed, then the whole config should be returned. `key` should be of type String. +An optional object which may have the following keys: -**Returns** +| 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 object containing the configuration of the IPFS node | -**Example:** +### Example ```JavaScript const config = await ipfs.config.get() @@ -29,17 +59,27 @@ console.log(config) A great source of [examples][] can be found in the tests for this API. -#### `config.set` +## `ipfs.config.set(key, value, [options])` > Adds or replaces a config value. -##### `ipfs.config.set(key, value)` +### Parameters + +| Name | Type | Description | +| ---- | ---- | ----------- | +| key | `String` | The key of the value that should be added or replaced | +| value | any | The value to be set | -`key` is the key value that will be added or replaced (in case of the value already). `key` should be of type String. +### Options -`value` value to be set. +An optional object which may have the following keys: -**Returns** +| 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 | | -------- | -------- | @@ -47,7 +87,7 @@ A great source of [examples][] can be found in the tests for this API. Note that this operation will **not** spark the restart of any service, i.e: if a config.replace changes the multiaddrs of the Swarm, Swarm will have to be restarted manually for the changes to take difference. -**Example:** +### Example ```JavaScript await ipfs.config.set('Discovery.MDNS.Enabled', false) @@ -56,15 +96,26 @@ await ipfs.config.set('Discovery.MDNS.Enabled', false) A great source of [examples][] can be found in the tests for this API. -#### `config.replace` +## `ipfs.config.replace(config, [options])` + +> Adds or replaces a config file + +### Parameters + +| Name | Type | Description | +| ---- | ---- | ----------- | +| config | Object | An object that contains the new config | -> Adds or replaces a config file. +### Options -##### `ipfs.config.replace(config)` +An optional object which may have the following keys: -`config` is a JSON object that contains the new config. +| 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** +### Returns | Type | Description | | -------- | -------- | @@ -72,30 +123,43 @@ A great source of [examples][] can be found in the tests for this API. Note that this operation will **not** spark the restart of any service, i.e: if a config.replace changes the multiaddrs of the Swarm, Swarm will have to be restarted manually for the changes to take difference. -**Example:** +### Example ```JavaScript +const newConfig = { + Bootstrap: [] +} + await ipfs.config.replace(newConfig) // config has been replaced ``` A great source of [examples][] can be found in the tests for this API. -#### `config.profiles.list` +## `ipfs.config.profiles.list([options])` > List available config profiles -##### `ipfs.config.profiles.list([options])` +### Parameters + +None + +### Options + +An optional object which may have the following keys: -`options` is a object. +| 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** +### Returns | Type | Description | | -------- | -------- | | `Promise` | An array with all the available config profiles | -**Example:** +### Example ```JavaScript const profiles = await ipfs.config.profiles.list() @@ -106,23 +170,35 @@ profiles.forEach(profile => { A great source of [examples][] can be found in the tests for this API. -#### `config.profiles.apply` +## `ipfs.config.profiles.apply(name, [options])` > Apply a config profile -##### `ipfs.config.profiles.apply(name, [options])` +### Parameters + +| Name | Type | Description | +| ---- | ---- | ----------- | +| name | `String` | The name of the profile to apply | + +Call `config.profiles.list()` for a list of valid profile names. + +### Options + +An optional object which may have the following keys: -`name` is a string. Call `config.profiles.list()` for a list of valid profile names. -`options` an object that might contain the following values: - - `dryRun` is a boolean which if true does not apply the profile +| Name | Type | Default | Description | +| ---- | ---- | ------- | ----------- | +| dryRun | `boolean` | false | If true does not apply the profile | +| 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** +### Returns | Type | Description | | -------- | -------- | | `Promise` | An object containing both the `original` and `updated` config | -**Example:** +### Example ```JavaScript const diff = await ipfs.config.profiles.apply('lowpower') @@ -135,3 +211,4 @@ Note that you will need to restart your node for config changes to take effect. A great source of [examples][] can be found in the tests for this API. [examples]: https://github.com/ipfs/js-ipfs/blob/master/packages/interface-ipfs-core/src/config +[AbortSignal]: https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal diff --git a/docs/core-api/DAG.md b/docs/core-api/DAG.md index c215a9069c..464d9d5478 100644 --- a/docs/core-api/DAG.md +++ b/docs/core-api/DAG.md @@ -1,35 +1,59 @@ -# DAG API +# DAG API > The dag API comes to replace the `object API`, it supports the creation and manipulation of dag-pb object, as well as other IPLD formats (i.e dag-cbor, ethereum-block, git, etc) -* [dag.put](#dagput) -* [dag.get](#dagget) -* [dag.tree](#dagtree) +- [`ipfs.dag.put(dagNode, [options])`](#ipfsdagputdagnode-options) + - [Parameters](#parameters) + - [Options](#options) + - [Returns](#returns) + - [Example](#example) +- [`ipfs.dag.get(cid, [path], [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) + - [Parameters](#parameters-2) + - [Options](#options-2) + - [Returns](#returns-2) + - [Example](#example-2) _Explore the DAG API through interactive coding challenges in our ProtoSchool tutorials:_ - _[P2P data links with content addressing](https://proto.school/#/basics/) (beginner)_ - _[Blogging on the Decentralized Web](https://proto.school/#/blog/) (intermediate)_ -#### `dag.put` +## `ipfs.dag.put(dagNode, [options])` > Store an IPLD format node -##### `ipfs.dag.put(dagNode, [options])` +### Parameters -- `dagNode` - a DAG node that follows one of the supported IPLD formats. -- `options` - a object that might contain the following values: - - `format` - The IPLD format multicodec (default `dag-cbor`). - - `hashAlg` - The hash algorithm to be used over the serialized DAG node (default `sha2-256`). - - `cid` - The CID of the node passed. **Note**: You should pass the CID or the `format` + `hashAlg` pair but _not both_. - - `pin` - Pin this node when adding (default `false`) +| Name | Type | Description | +| ---- | ---- | ----------- | +| dagNode | `Object` | A DAG node that follows one of the supported IPLD formats | -**Returns** +### Options + +An optional object which may have the following keys: + +| Name | Type | Default | Description | +| ---- | ---- | ------- | ----------- | +| format | `String` | `'dag-cbor'` | The IPLD format multicodec | +| hashAlg | `String` | `'sha2-256'` | The hash algorithm to be used over the serialized DAG node | +| cid | [CID][] | `'dag-cbor'` | The IPLD format multicodec | +| pin | `boolean` | `false` | Pin this node when adding to the blockstore | +| 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**: You should pass `cid` or the `format` & `hashAlg` pair but _not both_. + +### Returns | Type | Description | | -------- | -------- | -| `Promise` | A [CID](https://github.com/ipfs/js-cid) instance. The CID generated through the process or the one that was passed | +| `Promise` | A [CID][] instance. The CID generated through the process or the one that was passed | -**Example:** +### Example ```JavaScript const obj = { simple: 'object' } @@ -41,32 +65,39 @@ console.log(cid.toString()) A great source of [examples][] can be found in the tests for this API. -#### `dag.get` +## `ipfs.dag.get(cid, [path], [options])` > Retrieve an IPLD format node -##### `ipfs.dag.get(cid, [path], [options])` +### Parameters + +| 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` - can be one of the following: - - a [CID](https://github.com/ipfs/js-cid) instance. - - a CID in its String format (i.e: zdpuAkxd9KzGwJFGhymCZRkPCXtBmBW7mB2tTuEH11HLbES9Y) - - a CID in its String format concatenated with the path to be resolved -- `path` - the path to be resolved. Optional. -- `options` - a object that might contain the following values: - - `localResolve` - bool - if set to true, it will avoid resolving through different objects. +### Options -**Returns** +An optional object which may have the following keys: + +| Name | Type | Default | Description | +| ---- | ---- | ------- | ----------- | +| 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 | + +### Returns | Type | Description | | -------- | -------- | | `Promise` | An object representing an IPLD format node | -the returned object contains: +The returned object contains: - `value` - the value or node that was fetched during the get operation. - `remainderPath` - The remainder of the Path that the node was unable to resolve or what was left in a localResolve scenario. -**Example:** +### Example ```JavaScript // example obj @@ -110,27 +141,34 @@ await getAndLog('zdpuAmtur968yprkhG9N5Zxn6MFVoqAWBbhUAkNLJs2UtkTq5/c/ca/1') A great source of [examples][] can be found in the tests for this API. -#### `dag.tree` +## `ipfs.dag.tree(cid, [path,] [options])` > Enumerate all the entries in a graph -##### `ipfs.dag.tree(cid, [path], [options])` +### Parameters + +| 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 + +An optional object which may have the following keys: -- `cid` - can be one of the following: - - a [CID](https://github.com/ipfs/js-cid) instance. - - a CID in its String format (i.e: zdpuAkxd9KzGwJFGhymCZRkPCXtBmBW7mB2tTuEH11HLbES9Y) - - a CID in its String format concatenated with the path to be resolved -- `path` - the path to be resolved. Optional. -- `options` - a object that might contain the following values: - - `recursive` - bool - if set to true, it will follow the links and continuously run tree on them, returning all the paths in the graph. +| Name | Type | Default | Description | +| ---- | ---- | ------- | ----------- | +| 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 | -**Returns** +### Returns | Type | Description | | -------- | -------- | | `Promise` | An array with the paths passed | -**Example:** +### Example ```JavaScript // example obj @@ -167,3 +205,5 @@ A great source of [examples][] can be found in the tests for this API. [examples]: https://github.com/ipfs/js-ipfs/blob/master/packages/interface-ipfs-core/src/dag +[cid]: https://www.npmjs.com/package/cids +[AbortSignal]: https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal diff --git a/docs/core-api/DHT.md b/docs/core-api/DHT.md index d1527587a3..fcb8d3a023 100644 --- a/docs/core-api/DHT.md +++ b/docs/core-api/DHT.md @@ -1,27 +1,62 @@ -# DHT API +# DHT API + +- [`ipfs.dht.findPeer(peerId, [options])`](#ipfsdhtfindpeerpeerid-options) + - [Parameters](#parameters) + - [Options](#options) + - [Returns](#returns) + - [Example](#example) +- [`ipfs.dht.findProvs(cid, [options])`](#ipfsdhtfindprovscid-options) + - [Parameters](#parameters-1) + - [Options](#options-1) + - [Returns](#returns-1) + - [Example](#example-1) +- [`ipfs.dht.get(key, [options])`](#ipfsdhtgetkey-options) + - [Parameters](#parameters-2) + - [Options](#options-2) + - [Returns](#returns-2) + - [Example](#example-2) +- [`ipfs.dht.provide(cid, [options])`](#ipfsdhtprovidecid-options) + - [Parameters](#parameters-3) + - [Options](#options-3) + - [Returns](#returns-3) + - [Example](#example-3) +- [`ipfs.dht.put(key, value, [options])`](#ipfsdhtputkey-value-options) + - [Parameters](#parameters-4) + - [Options](#options-4) + - [Returns](#returns-4) + - [Example](#example-4) +- [`ipfs.dht.query(peerId, [options])`](#ipfsdhtquerypeerid-options) + - [Parameters](#parameters-5) + - [Options](#options-5) + - [Returns](#returns-5) + - [Example](#example-5) + +## `ipfs.dht.findPeer(peerId, [options])` -* [dht.findPeer](#dhtfindpeer) -* [dht.findProvs](#dhtfindprovs) -* [dht.get](#dhtget) -* [dht.provide](#dhtprovide) -* [dht.put](#dhtput) -* [dht.query](#dhtquery) +> Find the multiaddresses associated with a Peer ID -#### `dht.findPeer` +### Parameters -> Find the multiaddresses associated with a Peer ID +| Name | Type | Description | +| ---- | ---- | ----------- | +| peerId | [PeerID][] or [CID][] | The Peer ID of the node to find | + +### Options -##### `ipfs.dht.findPeer(peerId)` +An optional object which may have the following keys: -Where `peerId` is a Peer ID in `String`, [`CID`](https://github.com/multiformats/js-cid) or [`PeerId`](https://github.com/libp2p/js-peer-id) format. +| 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** +### Returns | Type | Description | | -------- | -------- | | `Promise<{ id: String, addrs: Multiaddr[] }>` | A promise that resolves to an object with `id` and `addrs`. `id` is a String - the peer's ID and `addrs` is an array of [Multiaddr](https://github.com/multiformats/js-multiaddr/) - addresses for the peer. | -**Example:** +### Example ```JavaScript const info = await ipfs.dht.findPeer('QmcZf59bWwK5XFi76CZX8cbJ4BhTzzA3gU1ZjYZcYW3dwt') @@ -43,26 +78,35 @@ info.addrs.forEach(addr => console.log(addr.toString())) A great source of [examples][] can be found in the tests for this API. -#### `dht.findProvs` +## `ipfs.dht.findProvs(cid, [options])` > Find peers that can provide a specific value, given a CID. -##### `ipfs.dht.findProvs(cid, [options])` +### Parameters + +| Name | Type | Description | +| ---- | ---- | ----------- | +| cid | [CID][] | The CID of the content to find | + +### Options -Where `cid` is a CID as a `String`, `Buffer` or [`CID`](https://github.com/multiformats/js-cid) instance. +An optional object which may have the following keys: -`options` an optional object with the following properties: - - `numProviders` - the number of providers to find. Default: 20 +| Name | Type | Default | Description | +| ---- | ---- | ------- | ----------- | +| numProviders | `Number` | 20 | How many providers to find | +| 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 that if `options.numProviders` are not found an error will be thrown. -**Returns** +### Returns | Type | Description | | -------- | -------- | | `AsyncIterable<{ id: String, addrs: Multiaddr[] }>` | A async iterable that yields objects with `id` and `addrs`. `id` is a String - the peer's ID and `addrs` is an array of [Multiaddr](https://github.com/multiformats/js-multiaddr/) - addresses for the peer. | -**Example:** +### Example ```JavaScript const providers = ipfs.dht.findProvs('QmdPAhQRxrDKqkGPvQzBvjYe3kU8kiEEAd2J6ETEamKAD9') @@ -74,21 +118,32 @@ for await (const provider of providers) { A great source of [examples][] can be found in the tests for this API. -#### `dht.get` +## `ipfs.dht.get(key, [options])` > Given a key, query the routing system for its best value. -##### `ipfs.dht.get(key)` +### Parameters -Where `key` is a `Buffer`. +| Name | Type | Description | +| ---- | ---- | ----------- | +| key | Buffer | The key associated with the value to find | -**Returns** +### 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` | The value that was stored under that key | -**Example:** +### Example ```JavaScript const value = await ipfs.dht.get(key) @@ -96,18 +151,27 @@ const value = await ipfs.dht.get(key) A great source of [examples][] can be found in the tests for this API. -#### `dht.provide` +## `ipfs.dht.provide(cid, [options])` > Announce to the network that you are providing given values. -##### `ipfs.dht.provide(cid, [options])` +### Parameters + +| Name | Type | Description | +| ---- | ---- | ----------- | +| cid | [CID][] or Array<[CID][]> | The key associated with the value to find | -Where `cid` is a CID or array of CIDs as a `String`, `Buffer` or [`CID`](https://github.com/multiformats/js-cid) instance. +### Options -`options` an optional object with the following properties: - - `recursive` - boolean, set to `true` to recursively provide the entire graph. Default `false`. +An optional object which may have the following keys: -**Returns** +| Name | Type | Default | Description | +| ---- | ---- | ------- | ----------- | +| recursive | `boolean` | false | If `true` the entire graph will be provided recursively | +| 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 | | -------- | -------- | @@ -115,7 +179,7 @@ Where `cid` is a CID or array of CIDs as a `String`, `Buffer` or [`CID`](https:/ Note: You must consume the iterable to completion to complete the provide operation. -**Example:** +### Example ```JavaScript for await (const message of ipfs.dht.provide('QmbWqxBEKC3P8tqsKc98xmWNzrzDtRLMiMPL8wBuTGsMnR')) { @@ -155,21 +219,34 @@ await consume(ipfs.dht.provide('QmbWqxBEKC3P8tqsKc98xmWNzrzDtRLMiMPL8wBuTGsMnR') A great source of [examples][] can be found in the tests for this API. -#### `dht.put` +## `ipfs.dht.put(key, value, [options])` > Write a key/value pair to the routing system. -##### `ipfs.dht.put(key, value)` -Where `key` is a `Buffer` and `value` is a `Buffer`. +### Parameters + +| Name | Type | Description | +| ---- | ---- | ----------- | +| key | Buffer | The key to put the value as | +| value | Buffer | Value to put | + +### Options + +An optional object which may have the following keys: -**Returns** +| 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 | | -------- | -------- | | `AsyncIterable` | DHT query messages. See example below for structure. | -**Example:** +### Example ```JavaScript for await (const message of ipfs.dht.put(key, value)) { @@ -209,21 +286,32 @@ await consume(ipfs.dht.put(key, value)) A great source of [examples][] can be found in the tests for this API. -#### `dht.query` +## `ipfs.dht.query(peerId, [options])` > Find the closest Peer IDs to a given Peer ID by querying the DHT. -##### `ipfs.dht.query(peerId)` +### Parameters + +| Name | Type | Description | +| ---- | ---- | ----------- | +| peerId | [PeerID][] or [CID][] | The peer id to query | + +### Options + +An optional object which may have the following keys: -Where `peerId` is a Peer ID in `String`, [`CID`](https://github.com/multiformats/js-cid) or [`PeerId`](https://github.com/libp2p/js-peer-id) format. +| 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** +### Returns | Type | Description | | -------- | -------- | | `AsyncIterable` | DHT query messages. See example below for structure. | -**Example:** +### Example ```JavaScript for await (const info of ipfs.dht.query('QmcZf59bWwK5XFi76CZX8cbJ4BhTzzA3gU1ZjYZcYW3dwt')) { @@ -257,3 +345,6 @@ https://github.com/libp2p/go-libp2p-core/blob/6e566d10f4a5447317a66d64c7459954b9 A great source of [examples][] can be found in the tests for this API. [examples]: https://github.com/ipfs/js-ipfs/blob/master/packages/interface-ipfs-core/src/dht +[peerid]: https://www.npmjs.com/package/peer-id +[cid]: https://www.npmjs.com/package/cids +[AbortSignal]: https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal diff --git a/docs/core-api/FILES.md b/docs/core-api/FILES.md index 404dd802d0..50cfe87718 100644 --- a/docs/core-api/FILES.md +++ b/docs/core-api/FILES.md @@ -1,37 +1,101 @@ -# Files API +# Files API -> The files API enables users to use the File System abstraction of IPFS. There are two Files API, one at the top level, the original `add`, `cat`, `get` and `ls`, and another behind the [`files`, also known as MFS](https://github.com/ipfs/specs/issues/98). [We are currently going through a revamping process of these APIs to make them more user-friendly](https://github.com/ipfs/interface-ipfs-core/issues/284). - -#### The Regular API -The regular, top-level API for add, cat, get and ls Files on IPFS -- [add](#add) -- [cat](#cat) -- [get](#get) -- [ls](#ls) - -#### The Files API -The Files API, aka MFS (Mutable File System) -- [files.chmod](#fileschmod) -- [files.cp](#filescp) -- [files.flush](#filesflush) -- [files.ls](#filesls) -- [files.mkdir](#filesmkdir) -- [files.mv](#filesmv) -- [files.read](#filesread) -- [files.rm](#filesrm) -- [files.stat](#filesstat) -- [files.touch](#filestouch) -- [files.write](#fileswrite) +> The files API enables users to use the File System abstraction of IPFS. There are two Files API, one at the top level, the original `add`, `cat`, `get` and `ls`, and another behind the [`files`, also known as MFS](https://docs.ipfs.io/guides/concepts/mfs/) _Explore the Mutable File System through interactive coding challenges in our [ProtoSchool tutorial](https://proto.school/#/mutable-file-system/)._ -#### `add` +- [The Regular API](#the-regular-api) + - [`ipfs.add(data, [options])`](#ipfsadddata-options) + - [Parameters](#parameters) + - [Options](#options) + - [Returns](#returns) + - [Notes](#notes) + - [Chunking options](#chunking-options) + - [Hash algorithms](#hash-algorithms) + - [Importing files from the file system](#importing-files-from-the-file-system) + - [Importing a file from a URL](#importing-a-file-from-a-url) + - [`ipfs.cat(ipfsPath, [options])`](#ipfscatipfspath-options) + - [Parameters](#parameters-1) + - [Options](#options-1) + - [Returns](#returns-1) + - [Example](#example) + - [`ipfs.get(ipfsPath, [options])`](#ipfsgetipfspath-options) + - [Parameters](#parameters-2) + - [Options](#options-2) + - [Returns](#returns-2) + - [`ipfs.ls(ipfsPath)`](#ipfslsipfspath) + - [Parameters](#parameters-3) + - [Options](#options-3) + - [Returns](#returns-3) + - [Example](#example-1) +- [The Mutable Files API](#the-mutable-files-api) + - [`ipfs.files.chmod(path, mode, [options])`](#ipfsfileschmodpath-mode-options) + - [Parameters](#parameters-4) + - [Options](#options-4) + - [Returns](#returns-4) + - [Example](#example-2) + - [`ipfs.files.cp(...from, to, [options])`](#ipfsfilescpfrom-to-options) + - [Parameters](#parameters-5) + - [Options](#options-5) + - [Returns](#returns-5) + - [Example](#example-3) + - [Notes](#notes-1) + - [`ipfs.files.mkdir(path, [options])`](#ipfsfilesmkdirpath-options) + - [Parameters](#parameters-6) + - [Options](#options-6) + - [Returns](#returns-6) + - [Example](#example-4) + - [`ipfs.files.stat(path, [options])`](#ipfsfilesstatpath-options) + - [Parameters](#parameters-7) + - [Options](#options-7) + - [Returns](#returns-7) + - [Example](#example-5) + - [`ipfs.files.touch(path, [options])`](#ipfsfilestouchpath-options) + - [Parameters](#parameters-8) + - [Options](#options-8) + - [Returns](#returns-8) + - [Example](#example-6) + - [`ipfs.files.rm(...paths, [options])`](#ipfsfilesrmpaths-options) + - [Parameters](#parameters-9) + - [Options](#options-9) + - [Example](#example-7) + - [`ipfs.files.read(path, [options])`](#ipfsfilesreadpath-options) + - [Parameters](#parameters-10) + - [Options](#options-10) + - [Returns](#returns-9) + - [`ipfs.files.write(path, content, [options])`](#ipfsfileswritepath-content-options) + - [Parameters](#parameters-11) + - [Options](#options-11) + - [Returns](#returns-10) + - [`ipfs.files.mv(...from, to, [options])`](#ipfsfilesmvfrom-to-options) + - [Parameters](#parameters-12) + - [Options](#options-12) + - [Returns](#returns-11) + - [Example](#example-8) + - [`ipfs.files.flush([path,] [options])`](#ipfsfilesflushpath-options) + - [Parameters](#parameters-13) + - [Options](#options-13) + - [Returns](#returns-12) + - [`ipfs.files.ls([path], [options])`](#ipfsfileslspath-options) + - [Parameters](#parameters-14) + - [Options](#options-14) + - [Returns](#returns-13) + - [Example](#example-9) + +## The Regular API +The regular, top-level API for add, cat, get and ls Files on IPFS + +### `ipfs.add(data, [options])` > Import files and data into IPFS. -##### `ipfs.add(data, [options])` +#### Parameters + +| Name | Type | Description | +| ---- | ---- | ----------- | +| data | Object | Data to import (see below) | -Where `data` may be: +`data` may be: * `Bytes` (alias for `Buffer`|`ArrayBuffer`|`TypedArray`) [single file] * `Bloby` (alias for: `Blob`|`File`) [single file] @@ -84,26 +148,27 @@ As an object, `secs` is the number of seconds since (positive) or before (negati As an array of numbers, it must have two elements, as per the output of [`process.hrtime()`](https://nodejs.org/dist/latest/docs/api/process.html#process_process_hrtime_time). -`options` is an optional object argument that might include the following keys: +#### Options -- `chunker` (string, default `size-262144`): chunking algorithm used to build ipfs DAGs. Available formats: - - size-{size} - - rabin - - rabin-{avg} - - rabin-{min}-{avg}-{max} -- `cidVersion` (integer, default `0`): the CID version to use when storing the data (storage keys are based on the CID, including its version). -- `enableShardingExperiment`: allows to create directories with an unlimited number of entries currently size of unixfs directories is limited by the maximum block size. Note that this is an experimental feature. -- `hashAlg` (string, default `sha2-256`): multihash hashing algorithm to use. [The list of all possible values]( https://github.com/multiformats/js-multihash/blob/master/src/constants.js#L5-L343). -- `onlyHash` (boolean, default `false`): doesn't actually add the file to IPFS, but rather calculates its hash. -- `pin` (boolean, default `true`): pin this object when adding. -- `progress` (function): a function that will be called with the byte length of chunks as a file is added to ipfs. -- `rawLeaves` (boolean, default `false`): if true, DAG leaves will contain raw file data and not be wrapped in a protobuf. -- `shardSplitThreshold` (integer, default `1000`): specifies the maximum size of unsharded directory that can be generated. -- `trickle` (boolean, default `false`): if true will use the trickle DAG format for DAG generation. - [Trickle definition from go-ipfs documentation](https://godoc.org/github.com/ipsn/go-ipfs/gxlibs/github.com/ipfs/go-unixfs/importer/trickle). -- `wrapWithDirectory` (boolean, default `false`): adds a wrapping node around the content. - -**Returns** +An optional object which may have the following keys: + +| Name | Type | Default | Description | +| ---- | ---- | ------- | ----------- | +| chunker | `String` | `'size-262144` | chunking algorithm used to build ipfs DAGs | +| cidVersion | `Number` | `0` | the CID version to use when storing the data | +| enableShardingExperiment | `boolean` | `false` | allows to create directories with an unlimited number of entries currently size of unixfs directories is limited by the maximum block size. Note that this is an experimental feature | +| hashAlg | `String` | `'sha2-256'` | multihash hashing algorithm to use | +| onlyHash | `boolean` | `false` | If true, will not add blocks to the blockstore | +| pin | `boolean` | `true` | pin this object when adding | +| progress | function | `undefined` | a function that will be called with the byte length of chunks as a file is added to ipfs | +| rawLeaves | `boolean` | `false` | if true, DAG leaves will contain raw file data and not be wrapped in a protobuf | +| shardSplitThreshold | `Number` | `1000` | Directories with more than this number of files will be created as HAMT-sharded directories | +| trickle | `boolean` | `false` | if true will use the [trickle DAG](https://godoc.org/github.com/ipsn/go-ipfs/gxlibs/github.com/ipfs/go-unixfs/importer/trickle) format for DAG generation | +| wrapWithDirectory | `boolean` | `false` | Adds a wrapping node around the content | +| 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 | | -------- | -------- | @@ -121,7 +186,7 @@ Each yielded object is of the form: } ``` -**Example:** +#### Example ```js const files = [{ @@ -156,7 +221,23 @@ Prints out objects like: Now [ipfs.io/ipfs/Qm...WW](https://ipfs.io/ipfs/QmNz1UBzpdd4HfZ3qir3aPiRdX5a93XwTuDNyXRc6PKhWW) returns the "ABC" string. -###### Importing files from the file system +#### Notes + +##### Chunking options + +The `chunker` option can be one of the following formats: + - size-{size} + - rabin + - rabin-{avg} + - rabin-{min}-{avg}-{max} + +`size-*` will result in fixed-size chunks, `rabin(-*)` will use [rabin fingerprinting](https://en.wikipedia.org/wiki/Rabin_fingerprint) to potentially generate variable size chunks. + +##### Hash algorithms + +See the [multihash](https://github.com/multiformats/js-multihash/blob/master/src/constants.js#L5-L343) module for the list of all possible values. + +##### Importing files from the file system Both js-ipfs and js-ipfs-http-client export a utility to make importing files from the file system easier (Note: it not available in the browser). @@ -185,7 +266,7 @@ for await (const file of ipfs.add(globSource('./docs', { recursive: true }))) { */ ``` -###### Importing a file from a URL +##### Importing a file from a URL Both js-ipfs and js-ipfs-http-client export a utility to make importing a file from a URL easier. @@ -210,34 +291,34 @@ for await (const file of ipfs.add(urlSource('https://ipfs.io/images/ipfs-logo.sv A great source of [examples](https://github.com/ipfs/js-ipfs/blob/master/packages/interface-ipfs-core/src/add.js) can be found in the tests for this API. -#### `cat` +### `ipfs.cat(ipfsPath, [options])` > Returns a file addressed by a valid IPFS Path. -##### `ipfs.cat(ipfsPath, [options])` +#### Parameters + +| Name | Type | Description | +| ---- | ---- | ----------- | +| ipfsPath | String or [CID][] | An [IPFS path][] or CID to export | -`ipfsPath` can be of type: +#### Options -- [`CID`][cid] of type: - - `string` - the base encoded version of the CID - - [CID](https://github.com/ipfs/js-cid) - a CID instance - - [Buffer][b] - the raw Buffer of the CID -- `string` - including the ipfs handler, a CID and a path to traverse to, e.g. - - '/ipfs/QmXEmhrMpbVvTh61FNAxP9nU7ygVtyvZA8HZDUaqQCAb66' - - '/ipfs/QmXEmhrMpbVvTh61FNAxP9nU7ygVtyvZA8HZDUaqQCAb66/a.txt' - - 'QmXEmhrMpbVvTh61FNAxP9nU7ygVtyvZA8HZDUaqQCAb66/a.txt' +An optional object which may have the following keys: -`options` is an optional object that may contain the following keys: - - `offset` is an optional byte offset to start the stream at - - `length` is an optional number of bytes to read from the stream +| Name | Type | Default | Description | +| ---- | ---- | ------- | ----------- | +| offset | `Number` | `undefined` | An offset to start reading the file from | +| length | `Number` | `undefined` | An optional max length to read from the file | +| 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** +#### Returns | Type | Description | | -------- | -------- | | `AsyncIterable` | An async iterable that yields [`Buffer`][b] objects with the contents of `path` | -**Example:** +#### Example ```JavaScript const chunks = [] @@ -249,24 +330,26 @@ console.log(Buffer.concat(chunks).toString()) A great source of [examples](https://github.com/ipfs/js-ipfs/blob/master/packages/interface-ipfs-core/src/cat.js) can be found in the tests for this API. -#### `get` +### `ipfs.get(ipfsPath, [options])` > Fetch a file or an entire directory tree from IPFS that is addressed by a valid IPFS Path. -##### `ipfs.get(ipfsPath)` +#### Parameters -`ipfsPath` can be of type: +| Name | Type | Description | +| ---- | ---- | ----------- | +| ipfsPath | String or [CID][] | An [IPFS path][] or CID to export | -- [`CID`][cid] of type: - - `string` - the base encoded version of the CID - - [CID](https://github.com/ipfs/js-cid) - a CID instance - - [Buffer][b] - the raw Buffer of the CID -- String, including the ipfs handler, a cid and a path to traverse to, e.g. - - '/ipfs/QmXEmhrMpbVvTh61FNAxP9nU7ygVtyvZA8HZDUaqQCAb66' - - '/ipfs/QmXEmhrMpbVvTh61FNAxP9nU7ygVtyvZA8HZDUaqQCAb66/a.txt' - - 'QmXEmhrMpbVvTh61FNAxP9nU7ygVtyvZA8HZDUaqQCAb66/a.txt' +#### Options -**Returns** +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 | | -------- | -------- | @@ -285,7 +368,7 @@ Each yielded object is of the form: Here, each `path` corresponds to the name of a file, and `content` is an async iterable with the file contents. -**Example:** +#### Example ```JavaScript const BufferList = require('bl/BufferList') @@ -293,7 +376,7 @@ const cid = 'QmQ2r6iMNpky5f1m4cnm3Yqw8VSvjuKpTcK1X7dBR1LkJF' for await (const file of ipfs.get(cid)) { console.log(file.path) - + if (!file.content) continue; const content = new BufferList() @@ -307,24 +390,26 @@ for await (const file of ipfs.get(cid)) { A great source of [examples](https://github.com/ipfs/js-ipfs/blob/master/packages/interface-ipfs-core/src/get.js) can be found in the tests for this API. -#### `ls` +### `ipfs.ls(ipfsPath)` > Lists a directory from IPFS that is addressed by a valid IPFS Path. -##### `ipfs.ls(ipfsPath)` +#### Parameters -`ipfsPath` can be of type: +| Name | Type | Description | +| ---- | ---- | ----------- | +| ipfsPath | String or [CID][] | An [IPFS path][] or CID to list | -- [`CID`][cid] of type: - - `string` - the base encoded version of the CID - - [CID](https://github.com/ipfs/js-cid) - a CID instance - - [Buffer][b] - the raw Buffer of the CID -- String, including the ipfs handler, a cid and a path to traverse to, e.g. - - '/ipfs/QmXEmhrMpbVvTh61FNAxP9nU7ygVtyvZA8HZDUaqQCAb66' - - '/ipfs/QmXEmhrMpbVvTh61FNAxP9nU7ygVtyvZA8HZDUaqQCAb66/a.txt' - - 'QmXEmhrMpbVvTh61FNAxP9nU7ygVtyvZA8HZDUaqQCAb66/a.txt' +#### Options -**Returns** +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 | | -------- | -------- | @@ -345,7 +430,7 @@ Each yielded object is of the form: } ``` -**Example:** +#### Example ```JavaScript const cid = 'QmQ2r6iMNpky5f1m4cnm3Yqw8VSvjuKpTcK1X7dBR1LkJF' @@ -359,38 +444,41 @@ A great source of [examples](https://github.com/ipfs/js-ipfs/blob/master/package --- -## The Files API aka MFS (The Mutable File System) +## The Mutable Files API The Mutable File System (MFS) is a virtual file system on top of IPFS that exposes a Unix like API over a virtual directory. It enables users to write and read from paths without having to worry about updating the graph. It enables things like [ipfs-blob-store](https://github.com/ipfs/ipfs-blob-store) to exist. -#### `files.chmod` +### `ipfs.files.chmod(path, mode, [options])` > Change mode for files and directories -##### `ipfs.files.chmod(path, mode, [options])` +#### Parameters + +| Name | Type | Description | +| ---- | ---- | ----------- | +| path | String or [CID][] | An [MFS Path][], [IPFS path][] or CID to modify | +| mode | String or Number | An integer (e.g. `0o755` or `parseInt('0755', 8)`) or a string modification of the existing mode, e.g. `'a+x'`, `'g-w'`, etc | -Where: +#### Options -- `path` is the path to the entry to modify. It might be: - - An existing MFS path to a file or a directory (e.g. `/my-dir/my-file.txt`) - - An IPFS path (e.g. `/ipfs/QmWGeRAEgtsHW3ec7U4qW2CyVy7eA2mFRVbk1nb24jFyks`) - - A [CID][cid] instance (e.g. `new CID('QmWGeRAEgtsHW3ec7U4qW2CyVy7eA2mFRVbk1nb24jFyks')`) -- `mode` is the new file mode. It might be: - - A string modification of the existing mode, e.g. `'a+x'`, `'g-w'`, etc - - An integer, e.g. the returned value from `parseInt('0755', 8)` or `0o755` -- `options` is an optional Object that might contain the following keys: - - `recursive` is a Boolean value that indicates if `mode` should be applied to all sub files/directories of `path` (default: false) - - `hashAlg` is which algorithm to use when creating CIDs for modified entries. (default: `sha2-256`) [The list of all possible values]( https://github.com/multiformats/js-multihash/blob/master/src/constants.js#L5-L343) - - `flush` is a Boolean value to decide whether or not to immediately flush MFS changes to disk (default: true) - - `cidVersion`: the CID version to use for any updated entries (integer, default 0) +An optional object which may have the following keys: -**Returns** +| Name | Type | Default | Description | +| ---- | ---- | ------- | ----------- | +| recursive | `boolean` | `false` | If true `mode` will be applied to the entire tree under `path` | +| flush | `boolean` | `true` | If true the changes will be immediately flushed to disk | +| hashAlg | `String` | `'sha2-256'` | The hash algorithm to use for any updated entries | +| cidVersion | `Number` | `0` | The CID version to use for any updated entries | +| 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` | If action is successfully completed. Otherwise an error will be thrown | -**Example:** +#### Example ```JavaScript // To give a file -rwxrwxrwx permissions @@ -403,41 +491,37 @@ await ipfs.files.chmod('/path/to/file.txt', '+rwx') await ipfs.files.chmod('/path/to/file.txt', '777') ``` -#### `files.cp` - -> Copy files. - -##### `ipfs.files.cp(...from, to, [options])` +### `ipfs.files.cp(...from, to, [options])` -Where: +> Copy files from one location to another -- `from` is the path(s) of the source to copy. It might be: - - An existing MFS path to a file or a directory (e.g. `/my-dir/my-file.txt`) - - An IPFS path (e.g. `/ipfs/QmWGeRAEgtsHW3ec7U4qW2CyVy7eA2mFRVbk1nb24jFyks`) - - A [CID][cid] instance (e.g. `new CID('QmWGeRAEgtsHW3ec7U4qW2CyVy7eA2mFRVbk1nb24jFyks')`) -- `to` is the path of the destination to copy to -- `options` is an optional Object that might contain the following keys: - - `parents` is a Boolean value to decide whether or not to make the parent directories if they don't exist (default: false) - - `hashAlg` is which algorithm to use when creating CIDs for newly created directories. (default: `sha2-256`) [The list of all possible values]( https://github.com/multiformats/js-multihash/blob/master/src/constants.js#L5-L343) - - `flush` is a Boolean value to decide whether or not to immediately flush MFS changes to disk (default: true) - -If `from` has multiple values then `to` must be a directory. +#### Parameters -If `from` has a single value and `to` exists and is a directory, `from` will be copied into `to`. +| Name | Type | Description | +| ---- | ---- | ----------- | +| from | One or more Strings or [CID][]s | An [MFS path][], [IPFS path][] or CID | +| to | `String` | An [MFS path][] | -If `from` has a single value and `to` exists and is a file, `from` must be a file and the contents of `to` will be replaced with the contents of `from` otherwise an error will be returned. +#### Options -If `from` is an IPFS path, and an MFS path exists with the same name, the IPFS path will be chosen. +An optional object which may have the following keys: -If `from` is an IPFS path and the content does not exist in your node's repo, only the root node of the source file with be retrieved from the network and linked to from the destination. The remainder of the file will be retrieved on demand. +| Name | Type | Default | Description | +| ---- | ---- | ------- | ----------- | +| parents | `boolean` | `false` | If true, create intermediate directories | +| flush | `boolean` | `true` | If true the changes will be immediately flushed to disk | +| hashAlg | `String` | `'sha2-256'` | The hash algorithm to use for any updated entries | +| cidVersion | `Number` | `0` | The CID version to use for any updated entries | +| 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** +#### Returns | Type | Description | | -------- | -------- | | `Promise` | If action is successfully completed. Otherwise an error will be thrown | -**Example:** +#### Example ```JavaScript // To copy a file @@ -450,52 +534,78 @@ await ipfs.files.cp('/src-dir', '/dst-dir') await ipfs.files.cp('/src-file1', '/src-file2', '/dst-dir') ``` -#### `files.mkdir` +#### Notes -> Make a directory. +If `from` has multiple values then `to` must be a directory. -##### `ipfs.files.mkdir(path, [options])` +If `from` has a single value and `to` exists and is a directory, `from` will be copied into `to`. -Where: +If `from` has a single value and `to` exists and is a file, `from` must be a file and the contents of `to` will be replaced with the contents of `from` otherwise an error will be returned. + +If `from` is an IPFS path, and an MFS path exists with the same name, the IPFS path will be chosen. + +If `from` is an IPFS path and the content does not exist in your node's repo, only the root node of the source file with be retrieved from the network and linked to from the destination. The remainder of the file will be retrieved on demand. -- `path` is the path to the directory to make -- `options` is an optional Object that might contain the following keys: - - `parents` is a Boolean value to decide whether or not to make the parent directories if they don't exist (default: false) - - `hashAlg` is which algorithm to use when creating CIDs for newly created directories (default: `sha2-256`) [The list of all possible values]( https://github.com/multiformats/js-multihash/blob/master/src/constants.js#L5-L343) - - `flush` is a Boolean value to decide whether or not to immediately flush MFS changes to disk (default: true) - - `mode`: optional UnixFS mode to create the directory with - a number or a string that will be interpreted as a base 8 number - - `mtime`: A Date object, an object with `{ secs, nsecs }` properties where `secs` is the number of seconds since (positive) or before (negative) the Unix Epoch began and `nsecs` is the number of nanoseconds since the last full second, or the output of [`process.hrtime()`](https://nodejs.org/api/process.html#process_process_hrtime_time) +### `ipfs.files.mkdir(path, [options])` -**Returns** +> Make a directory in your MFS + +#### Parameters + +| Name | Type | Description | +| ---- | ---- | ----------- | +| path | `String` | The [MFS path][] to create a directory at | + +#### Options + +An optional object which may have the following keys: + +| Name | Type | Default | Description | +| ---- | ---- | ------- | ----------- | +| parents | `boolean` | `false` | If true, create intermediate directories | +| mode | `Number` | `undefined` | An integer that represents the file mode | +| mtime | `Object` | `undefined` | A Date object, an object with `{ secs, nsecs }` properties where `secs` is the number of seconds since (positive) or before (negative) the Unix Epoch began and `nsecs` is the number of nanoseconds since the last full second, or the output of [`process.hrtime()`](https://nodejs.org/api/process.html#process_process_hrtime_time) | +| flush | `boolean` | `true` | If true the changes will be immediately flushed to disk | +| hashAlg | `String` | `'sha2-256'` | The hash algorithm to use for any updated entries | +| cidVersion | `Number` | `0` | The CID version to use for any updated entries | +| 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` | If action is successfully completed. Otherwise an error will be thrown | -**Example:** +#### Example ```JavaScript await ipfs.files.mkdir('/my/beautiful/directory') ``` -#### `files.stat` +### `ipfs.files.stat(path, [options])` -> Get file or directory status. +> Get file or directory statistics -##### `ipfs.files.stat(path, [options])` +#### Parameters -Where: +| Name | Type | Description | +| ---- | ---- | ----------- | +| path | `String` | The [MFS path][] return statistics from | -- `path` is the path to the file or directory to stat. It might be: - - An existing MFS path to a file or directory (e.g. `/my-dir/a.txt`) - - An IPFS path (e.g. `/ipfs/QmWGeRAEgtsHW3ec7U4qW2CyVy7eA2mFRVbk1nb24jFyks`) - - A [CID][cid] instance (e.g. `new CID('QmWGeRAEgtsHW3ec7U4qW2CyVy7eA2mFRVbk1nb24jFyks')`) -- `options` is an optional Object that might contain the following keys: - - `hash` is a Boolean value to return only the hash (default: false) - - `size` is a Boolean value to return only the size (default: false) - - `withLocal` is a Boolean value to compute the amount of the dag that is local, and if possible the total size (default: false) +#### Options -**Returns** +An optional object which may have the following keys: + +| Name | Type | Default | Description | +| ---- | ---- | ------- | ----------- | +| hash | `boolean` | `false` | If true, return only the CID | +| size | `boolean` | `false` | If true, return only the size | +| withLocal | `boolean` | `false` | If true, compute the amount of the DAG that is local and if popssible the total size | +| 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 | | -------- | -------- | @@ -512,7 +622,7 @@ the returned object has the following keys: - `local` is a boolean to indicate if the queried dag is fully present locally - `sizeLocal` is an integer indicating the cumulative size of the data present locally -**Example:** +#### Example ```JavaScript const stats = await ipfs.files.stat('/file.txt') @@ -527,31 +637,36 @@ console.log(stats) // } ``` -#### `files.touch` +### `ipfs.files.touch(path, [options])` > Update the mtime of a file or directory -##### `ipfs.files.touch(path, [options])` +#### Parameters + +| Name | Type | Description | +| ---- | ---- | ----------- | +| path | `String` | The [MFS path][] to update the mtime for | -Where: +#### Options -- `path` is the path to the file or directory to update. It might be: - - An existing MFS path to a file or directory (e.g. `/my-dir/a.txt`) - - An IPFS path (e.g. `/ipfs/QmWGeRAEgtsHW3ec7U4qW2CyVy7eA2mFRVbk1nb24jFyks`) - - A [CID][cid] instance (e.g. `new CID('QmWGeRAEgtsHW3ec7U4qW2CyVy7eA2mFRVbk1nb24jFyks')`) -- `options` is an optional Object that might contain the following keys: - - `mtime` Either a ` Date` object, an object with `{ sec, nsecs }` properties or the output of `process.hrtime()` (default: now) - - `hashAlg` is which algorithm to use when creating CIDs for modified entries. (default: `sha2-256`) [The list of all possible values]( https://github.com/multiformats/js-multihash/blob/master/src/constants.js#L5-L343) - - `flush` is a Boolean value to decide whether or not to immediately flush MFS changes to disk (default: true) - - `cidVersion`: the CID version to use for any updated entries (integer, default 0) +An optional object which may have the following keys: -**Returns** +| Name | Type | Default | Description | +| ---- | ---- | ------- | ----------- | +| mtime | `Object` | Now | Either a ` Date` object, an object with `{ sec, nsecs }` properties or the output of `process.hrtime()` | +| flush | `boolean` | `true` | If true the changes will be immediately flushed to disk | +| hashAlg | `String` | `'sha2-256'` | The hash algorithm to use for any updated entries | +| cidVersion | `Number` | `0` | The CID version to use for any updated entries | +| 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` | If action is successfully completed. Otherwise an error will be thrown | -**Example:** +#### Example ```JavaScript // set the mtime to the current time @@ -563,25 +678,36 @@ await ipfs.files.touch('/path/to/file.txt', { }) ``` -#### `files.rm` +### `ipfs.files.rm(...paths, [options])` > Remove a file or directory. -##### `ipfs.files.rm(...paths, [options])` +#### Parameters + +| Name | Type | Description | +| ---- | ---- | ----------- | +| path | `String` or `Array` | One or more [MFS path][]s to remove | -Where: +#### Options -- `paths` are one or more paths to remove -- `options` is an optional Object that might contain the following keys: - - `recursive` is a Boolean value to decide whether or not to remove directories recursively (default: false) +An optional object which may have the following keys: -**Returns** +| Name | Type | Default | Description | +| ---- | ---- | ------- | ----------- | +| recursive | `boolean` | `false` | If true all paths under the specifed path(s) will be removed | +| flush | `boolean` | `true` | If true the changes will be immediately flushed to disk | +| hashAlg | `String` | `'sha2-256'` | The hash algorithm to use for any updated entries | +| cidVersion | `Number` | `0` | The CID version to use for any updated entries | +| 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` | If action is successfully completed. Otherwise an error will be thrown | -**Example:** +#### Example ```JavaScript // To remove a file @@ -594,29 +720,34 @@ await ipfs.files.rm('/my/beautiful/file.txt', '/my/other/file.txt') await ipfs.files.rm('/my/beautiful/directory', { recursive: true }) ``` -#### `files.read` +### `ipfs.files.read(path, [options])` > Read a file -##### `ipfs.files.read(path, [options])` +#### Parameters + +| Name | Type | Description | +| ---- | ---- | ----------- | +| path | `String` or [CID][] | An [MFS path][], [IPFS Path][] or [CID][] to read | + +#### Options -Where: +An optional object which may have the following keys: -- `path` is the path of the file to read and must point to a file (and not a directory). It might be: - - An existing MFS path to a file (e.g. `/my-dir/a.txt`) - - An IPFS path (e.g. `/ipfs/QmWGeRAEgtsHW3ec7U4qW2CyVy7eA2mFRVbk1nb24jFyks`) - - A [CID][cid] instance (e.g. `new CID('QmWGeRAEgtsHW3ec7U4qW2CyVy7eA2mFRVbk1nb24jFyks')`) -- `options` is an optional Object that might contain the following keys: - - `offset` is an Integer with the byte offset to begin reading from (default: 0) - - `length` is an Integer with the maximum number of bytes to read (default: Read to the end of stream) +| Name | Type | Default | Description | +| ---- | ---- | ------- | ----------- | +| offset | `Number` | `undefined` | An offset to start reading the file from | +| length | `Number` | `undefined` | An optional max length to read from the file | +| 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** +#### Returns | Type | Description | | -------- | -------- | | `AsyncIterable` | An async iterable that yields [`Buffer`][b] objects with the contents of `path` | -**Example:** +#### Example ```JavaScript const chunks = [] @@ -629,77 +760,80 @@ console.log(Buffer.concat(chunks).toString()) // Hello, World! ``` -#### `files.write` +### `ipfs.files.write(path, content, [options])` -> Write to a file. +> Write to an MFS path -##### `ipfs.files.write(path, content, [options])` +#### Parameters -Where: +| Name | Type | Description | +| ---- | ---- | ----------- | +| path | `String` or `Array` | One or more [MFS path][]s to remove | +| content | `String`, `Buffer`, `AsyncIterable` or [`Blob`][blob] | The content to write to the path | -- `path` is the path of the file to write -- `content` can be: - - a [`Buffer`][b] - - an `AsyncIterable` (note: Node.js readable streams are iterable) - - a [`Blob`][blob] (caveat: will only work in the browser) - - a string path to a file (caveat: will only work in Node.js) -- `options` is an optional Object that might contain the following keys: - - `offset` is an Integer with the byte offset to begin writing at (default: 0) - - `create` is a Boolean to indicate to create the file if it doesn't exist (default: false) - - `truncate` is a Boolean to indicate if the file should be truncated after writing all the bytes from `content` (default: false) - - `parents` is a Boolean value to decide whether or not to make the parent directories if they don't exist (default: false) - - `length` is an Integer with the maximum number of bytes to read (default: Read all bytes from `content`) - - `rawLeaves`: if true, DAG leaves will contain raw file data and not be wrapped in a protobuf (boolean, default false) - - `cidVersion`: the CID version to use when storing the data (storage keys are based on the CID, including its version) (integer, default 0) - - `mode`: optional UnixFS mode to create or update the file with - a number or a string that will be interpreted as a base 8 number - - `mtime`: A Date object, an object with `{ sec, nsecs }` properties or the output of `process.hrtime()` or `process.hrtime.bigint()` +#### Options -**Returns** +An optional object which may have the following keys: + +| Name | Type | Default | Description | +| ---- | ---- | ------- | ----------- | +| offset | `Number` | `undefined` | An offset to start writing to file at | +| length | `Number` | `undefined` | Optionally limit how many bytes are read from the stream | +| create | `boolean` | `false` | Create the MFS path if it does not exist | +| parents | `boolean` | `false` | Create intermediate MFS paths if they do not exist | +| truncate | `boolean` | `false` | Truncate the file at the MFS path if it would have been larger than the passed `content` | +| rawLeaves | `boolean` | `false ` | If true, DAG leaves will contain raw file data and not be wrapped in a protobuf | +| mode | `Number` | `undefined` | An integer that represents the file mode | +| mtime | `Object` | `undefined` | A Date object, an object with `{ secs, nsecs }` properties where `secs` is the number of seconds since (positive) or before (negative) the Unix Epoch began and `nsecs` is the number of nanoseconds since the last full second, or the output of [`process.hrtime()`](https://nodejs.org/api/process.html#process_process_hrtime_time) | +| flush | `boolean` | `true` | If true the changes will be immediately flushed to disk | +| hashAlg | `String` | `'sha2-256'` | The hash algorithm to use for any updated entries | +| cidVersion | `Number` | `0` | The CID version to use for any updated entries | +| 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` | If action is successfully completed. Otherwise an error will be thrown | -**Example:** +#### Example ```JavaScript await ipfs.files.write('/hello-world', Buffer.from('Hello, world!')) ``` -#### `files.mv` +### `ipfs.files.mv(...from, to, [options])` -> Move files. +> Move files from one location to another#### Parameters -##### `ipfs.files.mv(...from, to, [options])` +#### Parameters -Where: +| Name | Type | Description | +| ---- | ---- | ----------- | +| from | `String` or `Array` | One or more [MFS path][]s to move | +| to | `String` | The location to move files to | -- `from` is the path(s) of the source to move -- `to` is the path of the destination to move to -- `options` is an optional Object that might contain the following keys: - - `parents` is a Boolean value to decide whether or not to make the parent directories if they don't exist (default: false) - - `hashAlg` is which algorithm to use when creating CIDs for newly created directories (default: `sha2-256`) [The list of all possible values]( https://github.com/multiformats/js-multihash/blob/master/src/constants.js#L5-L343) - - `flush` is a Boolean value to decide whether or not to immediately flush MFS changes to disk (default: true) +#### Options -If `from` has multiple values then `to` must be a directory. +An optional object which may have the following keys: -If `from` has a single value and `to` exists and is a directory, `from` will be moved into `to`. +| Name | Type | Default | Description | +| ---- | ---- | ------- | ----------- | +| parents | `boolean` | `false` | Create intermediate MFS paths if they do not exist | +| flush | `boolean` | `true` | If true the changes will be immediately flushed to disk | +| hashAlg | `String` | `'sha2-256'` | The hash algorithm to use for any updated entries | +| cidVersion | `Number` | `0` | The CID version to use for any updated entries | +| 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 | -If `from` has a single value and `to` exists and is a file, `from` must be a file and the contents of `to` will be replaced with the contents of `from` otherwise an error will be returned. - -If `from` is an IPFS path, and an MFS path exists with the same name, the IPFS path will be chosen. - -If `from` is an IPFS path and the content does not exist in your node's repo, only the root node of the source file with be retrieved from the network and linked to from the destination. The remainder of the file will be retrieved on demand. - -All values of `from` will be removed after the operation is complete unless they are an IPFS path. - -**Returns** +#### Returns | Type | Description | | -------- | -------- | | `Promise` | If action is successfully completed. Otherwise an error will be thrown | -**Example:** +#### Example ```JavaScript await ipfs.files.mv('/src-file', '/dst-file') @@ -709,44 +843,72 @@ await ipfs.files.mv('/src-dir', '/dst-dir') await ipfs.files.mv('/src-file1', '/src-file2', '/dst-dir') ``` -#### `files.flush` +#### Notes + +If `from` has multiple values then `to` must be a directory. + +If `from` has a single value and `to` exists and is a directory, `from` will be moved into `to`. + +If `from` has a single value and `to` exists and is a file, `from` must be a file and the contents of `to` will be replaced with the contents of `from` otherwise an error will be returned. + +If `from` is an IPFS path, and an MFS path exists with the same name, the IPFS path will be chosen. + +If `from` is an IPFS path and the content does not exist in your node's repo, only the root node of the source file with be retrieved from the network and linked to from the destination. The remainder of the file will be retrieved on demand. + +All values of `from` will be removed after the operation is complete unless they are an IPFS path. + +### `ipfs.files.flush([path,] [options])` > Flush a given path's data to the disk -##### `ipfs.files.flush([path])` +#### Parameters + +| Name | Type | Description | +| ---- | ---- | ----------- | +| path | `String` | Optional [MFS path][] to flush, defaults to `'/'` | + +#### Options -Where: +An optional object which may have the following keys: -- `path` is an optional string path to flush (default: `/`) +| 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** +#### Returns | Type | Description | | -------- | -------- | | `Promise` | The CID of the path that has been flushed | -**Example:** +#### Example ```JavaScript const cid = await ipfs.files.flush('/') ``` -#### `files.ls` +### `ipfs.files.ls([path], [options])` + +> List directories in the local mutable namespace + +#### Parameters -> List directories in the local mutable namespace. +| Name | Type | Description | +| ---- | ---- | ----------- | +| path | `String` | Optional [MFS path][] to list, defaults to `'/'` | -##### `ipfs.files.ls([path], [options])` +#### Options -Where: +An optional object which may have the following keys: -- `path` is an optional string to show listing for (default: `/`). It might be: - - An existing MFS path to a directory (e.g. `/my-dir`) - - An IPFS path (e.g. `/ipfs/QmWGeRAEgtsHW3ec7U4qW2CyVy7eA2mFRVbk1nb24jFyks`) - - A [CID][cid] instance (e.g. `new CID('QmWGeRAEgtsHW3ec7U4qW2CyVy7eA2mFRVbk1nb24jFyks')`) -- `options` is an optional Object that might contain the following keys: - - `sort` is a Boolean value. If true entries will be sorted by filename (default: false) +| Name | Type | Default | Description | +| ---- | ---- | ------- | ----------- | +| sort | `boolean` | `false` | If true entries will be sorted by filename | +| 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** +#### Returns | Type | Description | | -------- | -------- | @@ -761,7 +923,7 @@ Each object contains the following keys: - `mode` the UnixFS mode as a Number - `mtime` an objects with numeric `secs` and `nsecs` properties -**Example:** +#### Example ```JavaScript for await (const file of ipfs.files.ls('/screenshots')) { @@ -775,3 +937,6 @@ for await (const file of ipfs.files.ls('/screenshots')) { [file]: https://developer.mozilla.org/en-US/docs/Web/API/File [cid]: https://www.npmjs.com/package/cids [blob]: https://developer.mozilla.org/en-US/docs/Web/API/Blob +[IPFS Path]: https://www.npmjs.com/package/is-ipfs#isipfspathpath +[MFS Path]: https://docs.ipfs.io/guides/concepts/mfs/ +[AbortSignal]: https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal diff --git a/docs/core-api/KEY.md b/docs/core-api/KEY.md index f70122134c..11a6b6685d 100644 --- a/docs/core-api/KEY.md +++ b/docs/core-api/KEY.md @@ -1,32 +1,64 @@ -# Key API +# Key API + +- [`ipfs.key.gen(name, [options])`](#ipfskeygenname-options) + - [Parameters](#parameters) + - [Options](#options) + - [Returns](#returns) + - [Example](#example) +- [`ipfs.key.list([options])`](#ipfskeylistoptions) + - [Parameters](#parameters-1) + - [Options](#options-1) + - [Returns](#returns-1) + - [Example](#example-1) +- [`ipfs.key.rm(name, [options])`](#ipfskeyrmname-options) + - [Parameters](#parameters-2) + - [Options](#options-2) + - [Returns](#returns-2) + - [Example](#example-2) +- [`ipfs.key.rename(oldName, newName, [options])`](#ipfskeyrenameoldname-newname-options) + - [Parameters](#parameters-3) + - [Options](#options-3) + - [Returns](#returns-3) + - [Example](#example-3) +- [`ipfs.key.export(name, password, [options])`](#ipfskeyexportname-password-options) + - [Parameters](#parameters-4) + - [Options](#options-4) + - [Returns](#returns-4) + - [Example](#example-4) +- [`ipfs.key.import(name, pem, password, [options])`](#ipfskeyimportname-pem-password-options) + - [Parameters](#parameters-5) + - [Options](#options-5) + - [Returns](#returns-5) + - [Example](#example-5) + +## `ipfs.key.gen(name, [options])` -* [key.gen](#keygen) -* [key.list](#keylist) -* [key.rm](#keyrm) -* [key.rename](#keyrename) -* [key.export](#keyexport) -* [key.import](#keyimport) +> Generate a new key -#### `key.gen` +### Parameters -> Generate a new key +| Name | Type | Description | +| ---- | ---- | ----------- | +| name | String | The name to give the key | -##### `ipfs.key.gen(name, options)` +### Options -Where: +An optional object which may have the following keys: -- `name` is a local name for the key -- `options` is an object that contains following properties - - 'type' - the key type, one of 'rsa', 'ed25519' (Note: `js-ipfs` will not support 'ed25519' until [libp2p/js-libp2p-crypto#145](https://github.com/libp2p/js-libp2p-crypto/issues/145) is resolved) - - 'size' - the key size in bits +| Name | Type | Default | Description | +| ---- | ---- | ------- | ----------- | +| type | `String` | `'rsa'` | The key type, one of `'rsa'` or `'ed25519'` | +| size | `Number` | `2048` | The key size in bits | +| 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** +### Returns | Type | Description | | -------- | -------- | | `Promise` | An object that describes the key; `name` and `id` | -**Example:** +### Example ```JavaScript const key = await ipfs.key.gen('my-key', { @@ -41,13 +73,24 @@ console.log(key) A great source of [examples][] can be found in the tests for this API. -#### `key.list` +## `ipfs.key.list([options])` > List all the keys -##### `ipfs.key.list()` +### Parameters + +None + +### Options + +An optional object which may have the following keys: -**Returns** +| 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 | | -------- | -------- | @@ -62,7 +105,7 @@ example of the returned array: } ``` -**Example:** +### Example ```JavaScript const keys = await ipfs.key.list() @@ -78,16 +121,26 @@ console.log(keys) A great source of [examples][] can be found in the tests for this API. -#### `key.rm` +## `ipfs.key.rm(name, [options])` > Remove a key -##### `ipfs.key.rm(name)` +### Parameters + +| Name | Type | Description | +| ---- | ---- | ----------- | +| name | String | The name of the key to remove | + +### Options + +An optional object which may have the following keys: -Where: -- `name` is the local name for the key +| 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** +### Returns | Type | Description | | -------- | -------- | @@ -102,7 +155,7 @@ example of the returned object: } ``` -**Example:** +### Example ```JavaScript const key = await ipfs.key.rm('my-key') @@ -114,23 +167,33 @@ console.log(key) A great source of [examples][] can be found in the tests for this API. -#### `key.rename` +## `ipfs.key.rename(oldName, newName, [options])` > Rename a key -##### `ipfs.key.rename(oldName, newName)` +### Parameters -Where: -- `oldName` is the local name for the key -- `newName` a new name for key +| Name | Type | Description | +| ---- | ---- | ----------- | +| oldName | String | The current key name | +| newName | String | The desired key name | -**Returns** +### 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 object that describes the renamed key | -**Example:** +### Example ```JavaScript const key = await ipfs.key.rename('my-key', 'my-new-key') @@ -144,23 +207,33 @@ console.log(key) A great source of [examples][] can be found in the tests for this API. -#### `key.export` +## `ipfs.key.export(name, password, [options])` > Export a key in a PEM encoded password protected PKCS #8 -##### `ipfs.key.export(name, password)` +### Parameters + +| Name | Type | Description | +| ---- | ---- | ----------- | +| name | String | The name of the key to export | +| password | String | Password to set on the PEM output | + +### Options -Where: -- `name` is the local name for the key -- `password` is the password to protect the key +An optional object which may have the following keys: -**Returns** +| 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` | The string representation of the key | -**Example:** +### Example ```JavaScript const pem = await ipfs.key.export('self', 'password') @@ -175,24 +248,34 @@ console.log(pem) A great source of [examples][] can be found in the tests for this API. -#### `key.import` +## `ipfs.key.import(name, pem, password, [options])` > Import a PEM encoded password protected PKCS #8 key -##### `ipfs.key.import(name, pem, password)` +### Parameters + +| Name | Type | Description | +| ---- | ---- | ----------- | +| name | String | The name of the key to export | +| pem | String | The PEM encoded key | +| password | String | The password that protects the PEM key | + +### Options + +An optional object which may have the following keys: -Where: -- `name` is a local name for the key -- `pem` is the PEM encoded key -- `password` is the password that protects the PEM key +| 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** +### Returns | Type | Description | | -------- | -------- | | `Promise` | An object that describes the new key | -**Example:** +### Example ```JavaScript const key = await ipfs.key.import('clone', 'password') @@ -205,3 +288,5 @@ console.log(key) A great source of [examples][] can be found in the tests for this API. [examples]: https://github.com/ipfs/js-ipfs/blob/master/packages/interface-ipfs-core/src/key +[cid]: https://www.npmjs.com/package/cids +[AbortSignal]: https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal \ No newline at end of file diff --git a/docs/core-api/MISCELLANEOUS.md b/docs/core-api/MISCELLANEOUS.md index 9f155cd02f..fc01213c53 100644 --- a/docs/core-api/MISCELLANEOUS.md +++ b/docs/core-api/MISCELLANEOUS.md @@ -1,19 +1,54 @@ -# Miscellaneous API +# Miscellaneous API + +- [`ipfs.id([options])`](#ipfsidoptions) + - [Parameters](#parameters) + - [Options](#options) + - [Returns](#returns) + - [Example](#example) +- [`ipfs.version([options])`](#ipfsversionoptions) + - [Parameters](#parameters-1) + - [Options](#options-1) + - [Returns](#returns-1) + - [Example](#example-1) +- [`ipfs.dns(domain, [options])`](#ipfsdnsdomain-options) + - [Parameters](#parameters-2) + - [Options](#options-2) + - [Returns](#returns-2) + - [Example](#example-2) +- [`ipfs.stop([options])`](#ipfsstopoptions) + - [Parameters](#parameters-3) + - [Options](#options-3) + - [Returns](#returns-3) + - [Example](#example-3) +- [`ipfs.ping(peerId, [options])`](#ipfspingpeerid-options) + - [Parameters](#parameters-4) + - [Options](#options-4) + - [Returns](#returns-4) + - [Example](#example-4) +- [`ipfs.resolve(name, [options])`](#ipfsresolvename-options) + - [Parameters](#parameters-5) + - [Options](#options-5) + - [Returns](#returns-5) + - [Example](#example-5) + +## `ipfs.id([options])` -* [id](#id) -* [version](#version) -* [dns](#dns) -* [stop](#stop) -* [ping](#ping) -* [resolve](#resolve) +> Returns the identity of the Peer -#### `id` +### Parameters -> Returns the identity of the Peer +None + +### Options -##### `ipfs.id()` +An optional object which may have the following keys: -**Returns** +| 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 | | -------- | -------- | @@ -27,7 +62,7 @@ The Peer identity has the following properties: - `agentVersion: String` - The agent version - `protocolVersion: String` - The supported protocol version -**Example:** +### Example ```JavaScript const identity = await ipfs.id() @@ -36,19 +71,30 @@ console.log(identity) A great source of [examples](https://github.com/ipfs/js-ipfs/blob/master/packages/interface-ipfs-core/src/miscellaneous/id.js) can be found in the tests for this API. -#### `version` +## `ipfs.version([options])` > Returns the implementation version -##### `ipfs.version()` +### Parameters + +None + +### Options -**Returns** +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 object with the version of the implementation, the commit and the Repo | -**Example:** +### Example ```JavaScript const version = await ipfs.version() @@ -57,24 +103,33 @@ console.log(version) A great source of [examples](https://github.com/ipfs/js-ipfs/blob/master/packages/interface-ipfs-core/src/miscellaneous/version.js) can be found in the tests for this API. -#### `dns` +## `ipfs.dns(domain, [options])` > Resolve DNS links -##### `ipfs.dns(domain, [options])` +### Parameters -Where: +| Name | Type | Description | +| ---- | ---- | ----------- | +| domain | String | The domain to resolve | -- `options` is an optional object argument that might include the following properties: - - `recursive` (boolean, default true): resolve until result is not a domain name +### Options + +An optional object which may have the following keys: + +| Name | Type | Default | Description | +| ---- | ---- | ------- | ----------- | +| recursive | `boolean` | `true` | Resolve until result is not a domain name | +| 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** +### Returns | Type | Description | | -------- | -------- | | `Promise` | A string representing the IPFS path for that domain | -**Example:** +### Example ```JavaScript const path = await ipfs.dns('ipfs.io') @@ -83,19 +138,30 @@ console.log(path) A great source of [examples](https://github.com/ipfs/js-ipfs/blob/master/packages/interface-ipfs-core/src/miscellaneous/dns.js) can be found in the tests for this API. -#### `stop` +## `ipfs.stop([options])` > Stops the IPFS node and in case of talking with an IPFS Daemon, it stops the process. -##### `ipfs.stop()` +### Parameters -**Returns** +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` | If action is successfully completed. Otherwise an error will be thrown | -**Example:** +### Example ```JavaScript await ipfs.stop() @@ -103,11 +169,26 @@ await ipfs.stop() A great source of [examples](https://github.com/ipfs/js-ipfs/blob/master/packages/interface-ipfs-core/src/miscellaneous/stop.js) can be found in the tests for this API. -#### `ping` +## `ipfs.ping(peerId, [options])` > Send echo request packets to IPFS hosts -##### `ipfs.ping(peerId, [options])` +### Parameters + +| Name | Type | Description | +| ---- | ---- | ----------- | +| peerId | [PeerID][] or [CID][] | The remote peer to send packets to | + +### Options + +An optional object which may have the following keys: + +| Name | Type | Default | Description | +| ---- | ---- | ------- | ----------- | +| count | `Number` | `10` | The number of ping messages to send | +| 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 | + Where: @@ -115,7 +196,7 @@ Where: - `options` is an optional object argument that might include the following properties: - `count` (integer, default 10): the number of ping messages to send -**Returns** +### Returns | Type | Description | | -------- | -------- | @@ -133,7 +214,7 @@ Each yielded object is of the form: Note that not all ping response objects are "pongs". A "pong" message can be identified by a truthy `success` property and an empty `text` property. Other ping responses are failures or status updates. -**Example:** +### Example ```JavaScript for await (const res of ipfs.ping('Qmhash')) { @@ -147,28 +228,36 @@ for await (const res of ipfs.ping('Qmhash')) { A great source of [examples](https://github.com/ipfs/js-ipfs/tree/master/packages/interface-ipfs-core/src/ping) can be found in the tests for this API. -#### `resolve` +## `ipfs.resolve(name, [options])` > Resolve the value of names to IPFS There are a number of mutable name protocols that can link among themselves and into IPNS. For example IPNS references can (currently) point at an IPFS object, and DNS links can point at other DNS links, IPNS entries, or IPFS objects. This command accepts any of these identifiers and resolves them to the referenced item. -##### `ipfs.resolve(name, [options])` +### Parameters -Where: +| Name | Type | Description | +| ---- | ---- | ----------- | +| name | String | The name to resolve | + +### Options + +An optional object which may have the following keys: -- `name` (string): The name to resolve -- `options` is an optional object that might include the following properties: - - `recursive` (boolean, default false): Resolve until the result is an IPFS name - - `cidBase` (string): Multibase codec name the CID in the resolved path will be encoded with +| Name | Type | Default | Description | +| ---- | ---- | ------- | ----------- | +| recursive | `boolean` | `true` | Resolve until result is an IPFS name | +| cidBase | `String` | `base58btc` | Multibase codec name the CID in the resolved path will be encoded with | +| 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** +### Returns | Type | Description | | -------- | -------- | | `Promise` | A string representing the resolved name | -**Examples:** +### Example Resolve the value of your identity: @@ -209,3 +298,5 @@ A great source of [examples](https://github.com/ipfs/js-ipfs/blob/master/package [examples]: https://github.com/ipfs/js-ipfs/blob/master/packages/interface-ipfs-core/src/miscellaneous [rs]: https://www.npmjs.com/package/readable-stream [ps]: https://www.npmjs.com/package/pull-stream +[cid]: https://www.npmjs.com/package/cids +[AbortSignal]: https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal \ No newline at end of file diff --git a/docs/core-api/NAME.md b/docs/core-api/NAME.md index 87b4864762..5069d45f24 100644 --- a/docs/core-api/NAME.md +++ b/docs/core-api/NAME.md @@ -1,34 +1,57 @@ -# Name API - -* [name.publish](#namepublish) -* [name.pubsub.cancel](#namepubsubcancel) -* [name.pubsub.state](#namepubsubstate) -* [name.pubsub.subs](#namepubsubsubs) -* [name.resolve](#nameresolve) - -#### `name.publish` +# Name API + +- [`ipfs.name.publish(value, [options])`](#ipfsnamepublishvalue-options) + - [Parameters](#parameters) + - [Options](#options) + - [Returns](#returns) + - [Example](#example) + - [Notes](#notes) +- [`ipfs.name.pubsub.cancel(name, [options])`](#ipfsnamepubsubcancelname-options) + - [Parameters](#parameters-1) + - [Options](#options-1) + - [Returns](#returns-1) + - [Example](#example-1) +- [`ipfs.name.pubsub.state([options])`](#ipfsnamepubsubstateoptions) + - [Parameters](#parameters-2) + - [Options](#options-2) + - [Returns](#returns-2) + - [Example](#example-2) +- [`ipfs.name.pubsub.subs([options])`](#ipfsnamepubsubsubsoptions) + - [Parameters](#parameters-3) + - [Options](#options-3) + - [Returns](#returns-3) + - [Example](#example-3) +- [`ipfs.name.resolve(value, [options])`](#ipfsnameresolvevalue-options) + - [Parameters](#parameters-4) + - [Options](#options-4) + - [Returns](#returns-4) + - [Example](#example-4) + +## `ipfs.name.publish(value, [options])` > Publish an IPNS name with a given value. -##### `ipfs.name.publish(value, [options])` +### Parameters -`value` is a base58 encoded IPFS multihash, such as: `/ipfs/QmbezGequPwcsWo8UL4wDF6a8hYwM1hmbzYv2mnKkEWaUp`. +| Name | Type | Description | +| ---- | ---- | ----------- | +| value | [CID][] | The content to publish | -`options` is an object that may contain: +### Options -```JavaScript -{ - resolve: // bool - Resolve given path before publishing. Default: true - lifetime: // string - Time duration of the record. Default: 24h - ttl: // string - Time duration this record should be cached - key: // string - Name of the key to be used. Default: 'self' - allowOffline: // bool - When offline, save the IPNS record to the the local datastore without broadcasting to the network instead of simply failing. -} -``` +An optional object which may have the following keys: -Note: `allowOffline` option is not yet implemented in js-ipfs. See tracking issue [ipfs/js-ipfs#1997](https://github.com/ipfs/js-ipfs/issues/1997). +| Name | Type | Default | Description | +| ---- | ---- | ------- | ----------- | +| resolve | `boolean` | `true` | Resolve given path before publishing | +| lifetime | `String` | `24h` | Time duration of the record | +| ttl | `String` | `undefined` | Time duration this record should be cached | +| key | `String` | `'self'` | Name of the key to be used | +| allowOffline | `boolean` | `true` | When offline, save the IPNS record to the the local datastore without broadcasting to the network instead of simply failing. | +| 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** +### Returns | Type | Description | | -------- | -------- | @@ -43,7 +66,7 @@ example of the returned object: } ``` -**Example:** +### Example Imagine you want to publish your website under IPFS. You can use the [Files API](./FILES.md) to publish your static website and then you'll get a multihash you can link to. But when you need to make a change, a problem arises: you get a new multihash because you now have a different content. And it is not possible for you to be always giving others the new address. @@ -64,15 +87,32 @@ This way, you can republish a new version of your website under the same address A great source of [examples][] can be found in the tests for this API. -#### `name.pubsub.cancel` +### Notes + +The `allowOffline` option is not yet implemented in js-ipfs. See tracking issue [ipfs/js-ipfs#1997](https://github.com/ipfs/js-ipfs/issues/1997). -> Cancel a name subscription. +## `ipfs.name.pubsub.cancel(name, [options])` -##### `ipfs.name.pubsub.cancel(arg)` +> Cancel a name subscription + +### Parameters + +| Name | Type | Description | +| ---- | ---- | ----------- | +| name | `String` | The name of the subscription to cancel | + +### 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 | `arg` is the name of the subscription to cancel. -**Returns** +### Returns | Type | Description | | -------- | -------- | @@ -86,7 +126,7 @@ example of the returned object: } ``` -**Example:** +### Example ```JavaScript const name = 'QmQrX8hka2BtNHa8N8arAq16TCVx5qHcb46c5yPewRycLm' @@ -98,13 +138,24 @@ console.log(result.canceled) A great source of [examples][examples-pubsub] can be found in the tests for this API. -#### `name.pubsub.state` +## `ipfs.name.pubsub.state([options])` + +> Query the state of IPNS pubsub -> Query the state of IPNS pubsub. +### Parameters -##### `ipfs.name.pubsub.state()` +None -**Returns** +### 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 | | -------- | -------- | @@ -118,7 +169,7 @@ example of the returned object: } ``` -**Example:** +### Example ```JavaScript const result = await ipfs.name.pubsub.state() @@ -128,13 +179,24 @@ console.log(result.enabled) A great source of [examples][examples-pubsub] can be found in the tests for this API. -#### `name.pubsub.subs` +## `ipfs.name.pubsub.subs([options])` + +> Show current name subscriptions + +### Parameters + +None -> Show current name subscriptions. +### Options -##### `ipfs.name.pubsub.subs()` +An optional object which may have the following keys: -**Returns** +| 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 | | -------- | -------- | @@ -146,7 +208,7 @@ example of the returned array: ['/ipns/QmQrX8hka2BtNHa8N8arAq16TCVx5qHcb46c5yPewRycLm'] ``` -**Example:** +### Example ```JavaScript const result = await ipfs.name.pubsub.subs() @@ -156,30 +218,34 @@ console.log(result) A great source of [examples][examples-pubsub] can be found in the tests for this API. -#### `name.resolve` +## `ipfs.name.resolve(value, [options])` > Resolve an IPNS name. -##### `ipfs.name.resolve(value, [options])` +### Parameters -`value` is a IPNS address, such as: `/ipns/ipfs.io`. +| Name | Type | Description | +| ---- | ---- | ----------- | +| value | `String` | An IPNS address such as `/ipns/ipfs.io` | -`options` is an object that may contain: +### Options -```JavaScript -{ - recursive: // bool - Resolve until the result is not an IPNS name. Default: false. - nocache: // bool - Do not use cached entries. Default: false. -} -``` +An optional object which may have the following keys: + +| Name | Type | Default | Description | +| ---- | ---- | ------- | ----------- | +| 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 | +| signal | [AbortSignal][] | `undefined` | Can be used to cancel any long running requests started as a result of this call | -**Returns** +### Returns | Type | Description | | -------- | -------- | | `AsyncIterable` | An async iterable that yields strings that are increasingly more accurate resolved paths. | -**Example:** +### Example ```JavaScript // The IPNS address you want to resolve. @@ -195,3 +261,5 @@ A great source of [examples][] can be found in the tests for this API. [examples]: https://github.com/ipfs/js-ipfs/blob/master/packages/interface-ipfs-core/src/name [examples-pubsub]: https://github.com/ipfs/js-ipfs/blob/master/packages/interface-ipfs-core/src/name-pubsub +[cid]: https://www.npmjs.com/package/cids +[AbortSignal]: https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal diff --git a/docs/core-api/OBJECT.md b/docs/core-api/OBJECT.md index dba6f0d894..43395504ed 100644 --- a/docs/core-api/OBJECT.md +++ b/docs/core-api/OBJECT.md @@ -1,31 +1,85 @@ -# Object API +# Object API + +- [`ipfs.object.new([template,] [options])`](#ipfsobjectnewtemplate-options) + - [Parameters](#parameters) + - [Options](#options) + - [Returns](#returns) + - [Example](#example) +- [`ipfs.object.put(obj, [options])`](#ipfsobjectputobj-options) + - [Parameters](#parameters-1) + - [Options](#options-1) + - [Returns](#returns-1) + - [Example](#example-1) +- [`ipfs.object.get(cid, [options])`](#ipfsobjectgetcid-options) + - [Parameters](#parameters-2) + - [Options](#options-2) + - [Returns](#returns-2) + - [Example](#example-2) +- [`ipfs.object.data(cid, [options])`](#ipfsobjectdatacid-options) + - [Parameters](#parameters-3) + - [Options](#options-3) + - [Returns](#returns-3) + - [Example](#example-3) +- [`ipfs.object.links(cid, [options])`](#ipfsobjectlinkscid-options) + - [Parameters](#parameters-4) + - [Options](#options-4) + - [Returns](#returns-4) + - [Example](#example-4) +- [`ipfs.object.stat(cid, [options])`](#ipfsobjectstatcid-options) + - [Parameters](#parameters-5) + - [Options](#options-5) + - [Returns](#returns-5) + - [Example](#example-5) +- [`ipfs.object.patch.addLink(cid, link, [options])`](#ipfsobjectpatchaddlinkcid-link-options) + - [Parameters](#parameters-6) + - [Options](#options-6) + - [Returns](#returns-6) + - [Example](#example-6) + - [Notes](#notes) +- [`ipfs.object.patch.rmLink(cid, link, [options])`](#ipfsobjectpatchrmlinkcid-link-options) + - [Parameters](#parameters-7) + - [Options](#options-7) + - [Returns](#returns-7) + - [Example](#example-7) +- [`ipfs.object.patch.appendData(cid, data, [options])`](#ipfsobjectpatchappenddatacid-data-options) + - [Parameters](#parameters-8) + - [Options](#options-8) + - [Returns](#returns-8) + - [Example](#example-8) +- [`ipfs.object.patch.setData(multihash, data, [options])`](#ipfsobjectpatchsetdatamultihash-data-options) + - [Parameters](#parameters-9) + - [Options](#options-9) + - [Returns](#returns-9) + - [Example](#example-9) + +## `ipfs.object.new([template,] [options])` -* [object.new](#objectnew) -* [object.put](#objectput) -* [object.get](#objectget) -* [object.data](#objectdata) -* [object.links](#objectlinks) -* [object.stat](#objectstat) -* [object.patch.addLink](#objectpatchaddlink) -* [object.patch.rmLink](#objectpatchrmlink) -* [object.patch.appendData](#objectpatchappenddata) -* [object.patch.setData](#objectpatchsetdata) +> Create a new MerkleDAG node, using a specific layout. Caveat: So far, only UnixFS object layouts are supported. -#### `object.new` +### Parameters -> Create a new MerkleDAG node, using a specific layout. Caveat: So far, only UnixFS object layouts are supported. +| 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 | -##### `ipfs.object.new([template])` +### Options -`template` if defined, must be a string `unixfs-dir` and if that is passed, the created node will be an empty unixfs style directory. +An optional object which may have the following keys: -**Returns** +| Name | Type | Default | Description | +| ---- | ---- | ------- | ----------- | +| 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 | +| signal | [AbortSignal][] | `undefined` | Can be used to cancel any long running requests started as a result of this call | + +### Returns | Type | Description | | -------- | -------- | | `Promise` | A [CID](https://github.com/ipfs/js-cid) instance | -**Example:** +### Example ```JavaScript const cid = await ipfs.object.new('unixfs-dir') @@ -36,33 +90,37 @@ console.log(cid.toString()) A great source of [examples][] can be found in the tests for this API. -#### `object.put` +## `ipfs.object.put(obj, [options])` -> Store an MerkleDAG node. +> Store a MerkleDAG node. -##### `ipfs.object.put(obj, [options])` +### Parameters -`obj` is the MerkleDAG Node to be stored. Can of type: +| Name | Type | Description | +| ---- | ---- | ----------- | +| obj | `Object{ Data: , Links: [] }`, `Buffer` or [DAGNode][] | The MerkleDAG Node to be stored | -- Object, with format `{ Data: , Links: [] }` -- Buffer, requiring that the encoding is specified on the options. If no encoding is specified, Buffer is treated as the Data field -- [DAGNode][] +### Options -`options` is a optional argument of type object, that can contain the following properties: +An optional object which may have the following keys: -- `enc`, the encoding of the Buffer (json, yml, etc), if passed a Buffer. +| Name | Type | Default | Description | +| ---- | ---- | ------- | ----------- | +| enc | `String` | `undefined` | The encoding of the Buffer (json, yml, etc), if passed a Buffer | +| 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** +### Returns | Type | Description | | -------- | -------- | | `Promise` | A [CID](https://github.com/ipfs/js-cid) instance | -**Example:** +### Example ```JavaScript const obj = { - Data: new Buffer('Some data'), + Data: Buffer.from('Some data'), Links: [] } @@ -74,29 +132,32 @@ console.log(cid.toString()) A great source of [examples][] can be found in the tests for this API. -#### `object.get` +## `ipfs.object.get(cid, [options])` > Fetch a MerkleDAG node -##### `ipfs.object.get(multihash, [options])` +### Parameters -`multihash` is a [multihash][] which can be passed as: +| Name | Type | Description | +| ---- | ---- | ----------- | +| cid | [CID][] | The returned [DAGNode][] will correspond to this CID | -- Buffer, the raw Buffer of the multihash (or of and encoded version) -- String, the toString version of the multihash (or of an encoded version) +### Options -`options` is a optional argument of type object, that can contain the following properties: +An optional object which may have the following keys: -- `enc` (`string`) - the encoding of multihash (base58, base64, etc), if any. -- `timeout` (`number`|`string`) - Throw an error if the request does not complete within the specified milliseconds timeout. If `timeout` is a string, the value is parsed as a [human readable duration](https://www.npmjs.com/package/parse-duration). There is no timeout by default. +| 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** +### Returns | Type | Description | | -------- | -------- | | `Promise` | A MerkleDAG node of the type [DAGNode][] | -**Example:** +### Example ```JavaScript const multihash = 'QmPb5f92FxKPYdT3QNBd1GKiL4tZUXUrzF4Hkpdr3Gf1gK' @@ -109,27 +170,32 @@ console.log(node.data) A great source of [examples][] can be found in the tests for this API. -#### `object.data` +## `ipfs.object.data(cid, [options])` > Returns the Data field of an object -##### `ipfs.object.data(multihash, [options])` -`multihash` is a [multihash][] which can be passed as: +### Parameters + +| Name | Type | Description | +| ---- | ---- | ----------- | +| cid | [CID][] | The returned data will be from the [DAGNode][] that corresponds to this CID | -- Buffer, the raw Buffer of the multihash (or of and encoded version) -- String, the toString version of the multihash (or of an encoded version) +### Options -`options` is a optional argument of type object, that can contain the following properties: +An optional object which may have the following keys: -- `enc`, the encoding of multihash (base58, base64, etc), if any. +| 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** +### Returns | Type | Description | | -------- | -------- | | `Promise` | An Promise that resolves to Buffer objects with the data that the MerkleDAG node contained | -**Example:** +### Example ```JavaScript const cid = 'QmPb5f92FxKPYdT3QNBd1GKiL4tZUXUrzF4Hkpdr3Gf1gK' @@ -142,28 +208,32 @@ console.log(data.toString()) A great source of [examples][] can be found in the tests for this API. -#### `object.links` +## `ipfs.object.links(cid, [options])` > Returns the Links field of an object -##### `ipfs.object.links(multihash, [options])` +### Parameters -`multihash` is a [multihash][] which can be passed as: +| Name | Type | Description | +| ---- | ---- | ----------- | +| cid | [CID][] | The returned [DAGLink][]s will be from the [DAGNode][] that corresponds to this CID | -- Buffer, the raw Buffer of the multihash (or of and encoded version) -- String, the toString version of the multihash (or of an encoded version) +### Options -`options` is a optional argument of type object, that can contain the following properties: +An optional object which may have the following keys: -- `enc`, the encoding of multihash (base58, base64, etc), if any. +| 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** +### Returns | Type | Description | | -------- | -------- | | `Promise` | An Array of [DAGLink](https://github.com/ipld/js-ipld-dag-pb/blob/master/src/dag-link/dagLink.js) objects | -**Example:** +### Example ```JavaScript const multihash = 'Qmc5XkteJdb337s7VwFBAGtiaoj2QCEzyxtNRy3iMudc3E' @@ -180,22 +250,26 @@ console.log(hashes) A great source of [examples][] can be found in the tests for this API. -#### `object.stat` +## `ipfs.object.stat(cid, [options])` > Returns stats about an Object -##### `ipfs.object.stat(multihash, [options])` +### Parameters -`multihash` is a [multihash][] which can be passed as: +| Name | Type | Description | +| ---- | ---- | ----------- | +| cid | [CID][] | The returned stats will be from the [DAGNode][] that corresponds to this CID | -- Buffer, the raw Buffer of the multihash (or of and encoded version) -- String, the toString version of the multihash (or of an encoded version) +### Options -`options` is a optional argument of type object, that can contain the following properties: +An optional object which may have the following keys: -- `timeout`, A timeout to pass to the IPFS daemon so the request expires after a certain amount of time without any response. NOTE: not yet supported in JS IPFS. +| 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** +### Returns | Type | Description | | -------- | -------- | @@ -214,7 +288,7 @@ the returned object has the following format: } ``` -**Example:** +### Example ```JavaScript const multihash = 'QmPTkMuuL6PD8L2SwTwbcs1NPg14U8mRzerB1ZrrBrkSDD' @@ -234,51 +308,33 @@ console.log(stats) A great source of [examples][] can be found in the tests for this API. -#### `object.patch` - -> `object.patch` exposes the available patch calls. - -##### `object.patch.addLink` +## `ipfs.object.patch.addLink(cid, link, [options])` > Add a Link to an existing MerkleDAG Object -###### `ipfs.object.patch.addLink(multihash, link, [options])` +### Parameters -`multihash` is a [multihash][] which can be passed as: +| Name | Type | Description | +| ---- | ---- | ----------- | +| cid | [CID][] | Add a link to the [DAGNode][] that corresponds to this CID | +| link | [DAGLink][] | The link to add | -- Buffer, the raw Buffer of the multihash (or of and encoded version) -- String, the toString version of the multihash (or of an encoded version) +### Options -`link` is the new link to be added on the node that is identified by the `multihash`, can be passed as: -- `DAGLink` -- Object containing: name, cid and size properties +An optional object which may have the following keys: -```js -const link = { - name: 'Qmef7ScwzJUCg1zUSrCmPAz45m8uP5jU7SLgt2EffjBmbL', - size: 37, - cid: new CID('Qmef7ScwzJUCg1zUSrCmPAz45m8uP5jU7SLgt2EffjBmbL') -}; -``` +| 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 | -or - -```js -const link = new DAGLink(name, size, multihash) -``` - -`options` is a optional argument of type object, that can contain the following properties: - -- `enc`, the encoding of multihash (base58, base64, etc), if any. - -**Returns** +### Returns | Type | Description | | -------- | -------- | | `Promise` | An instance of [CID][] representing the new DAG node that was created due to the operation | - -**Example:** +### Example ```JavaScript // cid is CID of the DAG node created by adding a link @@ -291,44 +347,51 @@ const cid = await ipfs.object.patch.addLink(node, { A great source of [examples][] can be found in the tests for this API. -##### `object.patch.rmLink` +### Notes -> Remove a Link from an existing MerkleDAG Object +The `DAGLink` to be added can also be passed as an object containing: `name`, `cid` and `size` properties: -###### `ipfs.object.patch.rmLink(multihash, link, [options])` +```js +const link = { + name: 'Qmef7ScwzJUCg1zUSrCmPAz45m8uP5jU7SLgt2EffjBmbL', + size: 37, + cid: new CID('Qmef7ScwzJUCg1zUSrCmPAz45m8uP5jU7SLgt2EffjBmbL') +}; +``` -`multihash` is a [multihash][] which can be passed as: +or -- Buffer, the raw Buffer of the multihash (or of and encoded version) -- String, the toString version of the multihash (or of an encoded version) +```js +const link = new DAGLink(name, size, multihash) +``` -`link` is the link to be removed on the node that is identified by the `multihash`, can be passed as: +## `ipfs.object.patch.rmLink(cid, link, [options])` -- `DAGLink` +> Remove a Link from an existing MerkleDAG Object - ```js - const link = new DAGLink(name, size, multihash) - ``` +### Parameters -- Object containing a `name` property +| Name | Type | Description | +| ---- | ---- | ----------- | +| cid | [CID][] | Remove a link to the [DAGNode][] that corresponds to this CID | +| link | [DAGLink][] | The [DAGLink][] to remove | - ```js - const link = { - name: 'Qmef7ScwzJUCg1zUSrCmPAz45m8uP5jU7SLgt2EffjBmbL' - }; - ``` +### Options -`options` is a optional argument of type object, that can contain the following properties: +An optional object which may have the following keys: -- `enc`, the encoding of multihash (base58, base64, etc), if any. +| 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** +### Returns | Type | Description | | -------- | -------- | | `Promise` | An instance of [CID][] representing the new DAG node that was created due to the operation | -**Example:** +### Example ```JavaScript // cid is CID of the DAG node created by removing a link @@ -341,69 +404,94 @@ const cid = await ipfs.object.patch.rmLink(node, { A great source of [examples][] can be found in the tests for this API. -##### `object.patch.appendData` +### Notes -> Append Data to the Data field of an existing node. +`link` is the link to be removed on the node that is identified by the `multihash`, can be passed as: -###### `ipfs.object.patch.appendData(multihash, data, [options])` +- `DAGLink` + ```js + const link = new DAGLink(name, size, multihash) + ``` -`multihash` is a [multihash][] which can be passed as: +- Object containing a `name` property + ```js + const link = { + name: 'Qmef7ScwzJUCg1zUSrCmPAz45m8uP5jU7SLgt2EffjBmbL' + }; + ``` + +## `ipfs.object.patch.appendData(cid, data, [options])` -- Buffer, the raw Buffer of the multihash (or of and encoded version) -- String, the toString version of the multihash (or of an encoded version) +> Append Data to the Data field of an existing node -`data` is a Buffer containing Data to be appended to the existing node. +### Parameters -`options` is a optional argument of type object, that can contain the following properties: +| Name | Type | Description | +| ---- | ---- | ----------- | +| cid | [CID][] | Add data to the [DAGNode][] that corresponds to this CID | +| data | `Buffer` | The data to append to the `.Data` field of the node | -- `enc`, the encoding of multihash (base58, base64, etc), if any. +### Options -**Returns** +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 instance of [CID][] representing the new DAG node that was created due to the operation | -**Example:** +### Example ```JavaScript -const cid = await ipfs.object.patch.appendData(multihash, new Buffer('more data')) +const cid = await ipfs.object.patch.appendData(multihash, Buffer.from('more data')) ``` A great source of [examples][] can be found in the tests for this API. -##### `object.patch.setData` - -> Reset the Data field of a MerkleDAG Node to new Data +## `ipfs.object.patch.setData(multihash, data, [options])` -###### `ipfs.object.patch.setData(multihash, data, [options])` +> Overwrite the Data field of a DAGNode with new Data -`multihash` is a [multihash][] which can be passed as: +### Parameters -- Buffer, the raw Buffer of the multihash (or of and encoded version) -- String, the toString version of the multihash (or of an encoded version) +| Name | Type | Description | +| ---- | ---- | ----------- | +| cid | [CID][] | Replace data of the [DAGNode][] that corresponds to this CID | +| data | `Buffer` | The data to overwrite with | -`data` is a Buffer containing Data to replace the existing Data on the node. +### Options -`options` is a optional argument of type object, that can contain the following properties: +An optional object which may have the following keys: -- `enc`, the encoding of multihash (base58, base64, etc), if any. +| 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** +### Returns | Type | Description | | -------- | -------- | | `Promise` | An instance of [CID][] representing the new DAG node that was created due to the operation | -**Example:** +### Example ```JavaScript -const cid = await ipfs.object.patch.setData(multihash, new Buffer('more data')) +const cid = '/ipfs/Qmfoo' +const updatedCid = await ipfs.object.patch.setData(cid, Buffer.from('more data')) ``` A great source of [examples][] can be found in the tests for this API. [CID]: https://github.com/multiformats/js-cid [DAGNode]: https://github.com/ipld/js-ipld-dag-pb +[DAGLink]: https://github.com/ipld/js-ipld-dag-pb [multihash]: http://github.com/multiformats/multihash [examples]: https://github.com/ipfs/js-ipfs/blob/master/packages/interface-ipfs-core/src/object +[AbortSignal]: https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal diff --git a/docs/core-api/PIN.md b/docs/core-api/PIN.md index 5b08a11645..14970ea841 100644 --- a/docs/core-api/PIN.md +++ b/docs/core-api/PIN.md @@ -1,23 +1,42 @@ -# Pin API +# Pin API -* [pin.add](#pinadd) -* [pin.ls](#pinls) -* [pin.rm](#pinrm) +- [`ipfs.pin.add(cid, [options])`](#ipfspinaddcid-options) + - [Parameters](#parameters) + - [Options](#options) + - [Returns](#returns) + - [Example](#example) +- [`ipfs.pin.ls([cid], [options])`](#ipfspinlscid-options) + - [Parameters](#parameters-1) + - [Options](#options-1) + - [Returns](#returns-1) + - [Example](#example-1) +- [`ipfs.pin.rm(cid, [options])`](#ipfspinrmcid-options) + - [Parameters](#parameters-2) + - [Options](#options-2) + - [Returns](#returns-2) + - [Example](#example-2) -#### `pin.add` +## `ipfs.pin.add(cid, [options])` -> Adds an IPFS object to the pinset and also stores it to the IPFS repo. pinset is the set of hashes currently pinned (not gc'able). +> Adds an IPFS object to the pinset and also stores it to the IPFS repo. pinset is the set of hashes currently pinned (not gc'able) -##### `ipfs.pin.add(hash, [options])` +### Parameters -Where: +| Name | Type | Description | +| ---- | ---- | ----------- | +| cid | [CID][] | Pin this CID in your repo | -- `hash` is an IPFS multihash. -- `options` is an object that can contain the following keys - - `recursive` (`boolean`) - Recursively pin the object linked. Type: bool. Default: `true` - - `timeout` (`number`|`string`) - Throw an error if the request does not complete within the specified milliseconds timeout. If `timeout` is a string, the value is parsed as a [human readable duration](https://www.npmjs.com/package/parse-duration). There is no timeout by default. +### Options -**Returns** +An optional object which may have the following keys: + +| Name | Type | Default | Description | +| ---- | ---- | ------- | ----------- | +| recursive | `boolean` | `true` | Recursively pin all links contained by the object | +| 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 | | -------- | -------- | @@ -31,7 +50,7 @@ an array of objects is returned, each of the form: } ``` -**Example:** +### Example ```JavaScript const pinset = await ipfs.pin.add('QmWATWQ7fVPP2EFGu71UkfnqhYXDYH566qy47CnJDgvs8u') @@ -42,25 +61,33 @@ console.log(pinset) A great source of [examples][] can be found in the tests for this API. -#### `pin.ls` +## `ipfs.pin.ls([cid], [options])` + +> List all the objects pinned to local storage or under a specific hash + +### Parameters -> List all the objects pinned to local storage or under a specific hash. +| Name | Type | Description | +| ---- | ---- | ----------- | +| cid | [CID][] or `Array` | List these specific CIDs | -##### `ipfs.pin.ls([cid], [options])` +### Options -Where: +An optional object which may have the following keys: -- `cid` - a [CID][cid] instance or CID as a string or an array of CIDs. -- `options` - is an object that can contain the following keys: - - `type` - filter by this type of pin ("recursive", "direct" or "indirect") +| Name | Type | Default | Description | +| ---- | ---- | ------- | ----------- | +| 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 | -**Returns** +### Returns | Type | Description | | -------- | -------- | | `AsyncIterable<{ cid: CID, type: string }>` | An async iterable that yields currently pinned objects with `cid` and `type` properties. `cid` is a [CID][cid] of the pinned node, `type` is the pin type ("recursive", "direct" or "indirect") | -**Example:** +### Example ```JavaScript for await (const { cid, type } of ipfs.pin.ls()) { @@ -73,24 +100,33 @@ for await (const { cid, type } of ipfs.pin.ls()) { A great source of [examples][] can be found in the tests for this API. -#### `pin.rm` +## `ipfs.pin.rm(cid, [options])` + +> Unpin this block from your repo + +### Parameters + +| Name | Type | Description | +| ---- | ---- | ----------- | +| cid | [CID][] | Unpin this CID | -> Remove a hash from the pinset +### Options -##### `ipfs.pin.rm(hash, [options])` +An optional object which may have the following keys: -Where: -- `hash` is a multihash. -- `options` is an object that can contain the following keys - - 'recursive' - Recursively unpin the object linked. Type: bool. Default: `true` +| Name | Type | Default | Description | +| ---- | ---- | ------- | ----------- | +| recursive | `boolean` | `true` | Recursively unpin the object linked | +| 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** +### Returns | Type | Description | | -------- | -------- | | `Promise<{ cid: CID }>` | An array of unpinned objects | -**Example:** +### Example ```JavaScript const pinset = await ipfs.pin.rm('QmWATWQ7fVPP2EFGu71UkfnqhYXDYH566qy47CnJDgvs8u') @@ -103,3 +139,4 @@ A great source of [examples][] can be found in the tests for this API. [examples]: https://github.com/ipfs/js-ipfs/blob/master/packages/interface-ipfs-core/src/pin [cid]: https://www.npmjs.com/package/cids +[AbortSignal]: https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal diff --git a/docs/core-api/PUBSUB.md b/docs/core-api/PUBSUB.md index 01f4c9ad53..e66118514f 100644 --- a/docs/core-api/PUBSUB.md +++ b/docs/core-api/PUBSUB.md @@ -1,31 +1,55 @@ -# PubSub API +# PubSub API + +- [`ipfs.pubsub.subscribe(topic, handler, [options])`](#ipfspubsubsubscribetopic-handler-options) + - [Parameters](#parameters) + - [Options](#options) + - [Returns](#returns) + - [Example](#example) +- [`ipfs.pubsub.unsubscribe(topic, handler, [options])`](#ipfspubsubunsubscribetopic-handler-options) + - [Parameters](#parameters-1) + - [Options](#options-1) + - [Returns](#returns-1) + - [Example](#example-1) + - [Notes](#notes) +- [`ipfs.pubsub.publish(topic, data, [options])`](#ipfspubsubpublishtopic-data-options) + - [Returns](#returns-2) + - [Example](#example-2) +- [`ipfs.pubsub.ls([options])`](#ipfspubsublsoptions) + - [Parameters](#parameters-2) + - [Options](#options-2) + - [Returns](#returns-3) + - [Example](#example-3) +- [`ipfs.pubsub.peers(topic, [options])`](#ipfspubsubpeerstopic-options) + - [Returns](#returns-4) + - [Example](#example-4) + +## `ipfs.pubsub.subscribe(topic, handler, [options])` -* [pubsub.subscribe](#pubsubsubscribe) -* [pubsub.unsubscribe](#pubsubunsubscribe) -* [pubsub.publish](#pubsubpublish) -* [pubsub.ls](#pubsubls) -* [pubsub.peers](#pubsubpeers) +> Subscribe to a pubsub topic. -#### `pubsub.subscribe` +### Parameters -> Subscribe to a pubsub topic. +| Name | Type | Description | +| ---- | ---- | ----------- | +| topic | `String` | The topic name | +| handler | `Function<(msg) => {}>` | Event handler which will be called with a message object everytime one is received. The `msg` has the format `{from: String, seqno: Buffer, data: Buffer, topicIDs: Array}` | -##### `ipfs.pubsub.subscribe(topic, handler, [options])` +### Options -- `topic: String` -- `handler: (msg) => {}` - Event handler which will be called with a message object everytime one is received. The `msg` has the format `{from: String, seqno: Buffer, data: Buffer, topicIDs: Array}`. -- `options: Object` - (Optional) Object containing the following properties: - - `discover: Boolean` - (Default: `false`) Will use the DHT to find other peers. ***Note:** This option is currently unimplemented and, thus, you can't use it for now.* +An optional object which may have the following keys: -> _In the future, topic can also be type of TopicDescriptor (https://github.com/libp2p/pubsub-notes/blob/master/flooding/flooding.proto#L23). However, for now, only strings are supported._ +| 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** +### Returns | Type | Description | | -------- | -------- | | `Promise` | If action is successfully completed. Otherwise an error will be thrown | -**Example:** +### Example ```JavaScript const topic = 'fruit-of-the-day' @@ -37,26 +61,33 @@ console.log(`subscribed to ${topic}`) A great source of [examples][] can be found in the tests for this API. -#### `pubsub.unsubscribe` +## `ipfs.pubsub.unsubscribe(topic, handler, [options])` > Unsubscribes from a pubsub topic. -##### `ipfs.pubsub.unsubscribe(topic, handler)` +### Parameters -- `topic: String` - The topic to unsubscribe from -- `handler: (msg) => {}` - The handler to remove. +| Name | Type | Description | +| ---- | ---- | ----------- | +| topic | `String` | The topic to unsubscribe from | +| handler | `Function<(msg) => {}>` | The handler to remove | -If the `topic` and `handler` are provided, the `handler` will no longer receive updates for the `topic`. This behaves like [EventEmitter.removeListener](https://nodejs.org/dist/latest/docs/api/events.html#events_emitter_removelistener_eventname_listener). If the `handler` is not equivalent to the `handler` provided on `subscribe`, no action will be taken. +### Options -If **only** the `topic` param is provided, unsubscribe will remove **all** handlers for the `topic`. This behaves like [EventEmitter.removeAllListeners](https://nodejs.org/dist/latest/docs/api/events.html#events_emitter_removealllisteners_eventname). Use this if you would like to no longer receive any updates for the `topic`. +An optional object which may have the following keys: -**Returns** +| 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` | If action is successfully completed. Otherwise an error will be thrown | -**Example:** +### Example ```JavaScript const topic = 'fruit-of-the-day' @@ -83,22 +114,26 @@ await ipfs.pubsub.unsubscribe(topic); A great source of [examples][] can be found in the tests for this API. -#### `pubsub.publish` +### Notes -> Publish a data message to a pubsub topic. +If the `topic` and `handler` are provided, the `handler` will no longer receive updates for the `topic`. This behaves like [EventEmitter.removeListener](https://nodejs.org/dist/latest/docs/api/events.html#events_emitter_removelistener_eventname_listener). If the `handler` is not equivalent to the `handler` provided on `subscribe`, no action will be taken. -##### `ipfs.pubsub.publish(topic, data)` +If **only** the `topic` param is provided, unsubscribe will remove **all** handlers for the `topic`. This behaves like [EventEmitter.removeAllListeners](https://nodejs.org/dist/latest/docs/api/events.html#events_emitter_removealllisteners_eventname). Use this if you would like to no longer receive any updates for the `topic`. + +## `ipfs.pubsub.publish(topic, data, [options])` + +> Publish a data message to a pubsub topic. - `topic: String` - `data: Buffer|String` - The message to send -**Returns** +### Returns | Type | Description | | -------- | -------- | | `Promise` | If action is successfully completed. Otherwise an error will be thrown | -**Example:** +### Example ```JavaScript const topic = 'fruit-of-the-day' @@ -112,19 +147,30 @@ console.log(`published to ${topic}`) A great source of [examples][] can be found in the tests for this API. -#### `pubsub.ls` +## `ipfs.pubsub.ls([options])` > Returns the list of subscriptions the peer is subscribed to. -##### `ipfs.pubsub.ls()` +### Parameters + +None -**Returns** +### 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 topicIDs that the peer is subscribed to | -**Example:** +### Example ```JavaScript const topics = await ipfs.pubsub.ls() @@ -133,21 +179,19 @@ console.log(topics) A great source of [examples][] can be found in the tests for this API. -#### `pubsub.peers` +## `ipfs.pubsub.peers(topic, [options])` > Returns the peers that are subscribed to one topic. -##### `ipfs.pubsub.peers(topic)` - - `topic: String` -**Returns** +### Returns | Type | Description | | -------- | -------- | | `Promise` | An array of peer IDs subscribed to the `topic` | -**Example:** +### Example ```JavaScript const topic = 'fruit-of-the-day' @@ -159,3 +203,4 @@ console.log(peerIds) A great source of [examples][] can be found in the tests for this API. [examples]: https://github.com/ipfs/js-ipfs/blob/master/packages/interface-ipfs-core/src/pubsub +[AbortSignal]: https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal \ No newline at end of file diff --git a/docs/core-api/REFS.md b/docs/core-api/REFS.md index d5e9a4b365..81b6923f92 100644 --- a/docs/core-api/REFS.md +++ b/docs/core-api/REFS.md @@ -1,34 +1,41 @@ -# Refs API +# Refs API -* [refs](#refs) -* [refs.local](#refslocal) +- [`ipfs.refs(ipfsPath, [options])`](#ipfsrefsipfspath-options) + - [Parameters](#parameters) + - [Options](#options) + - [Returns](#returns) + - [Example](#example) +- [`ipfs.refs.local([options])`](#ipfsrefslocaloptions) + - [Parameters](#parameters-1) + - [Options](#options-1) + - [Returns](#returns-1) + - [Example](#example-1) -#### `refs` +## `ipfs.refs(ipfsPath, [options])` > Get links (references) from an object. -##### `ipfs.refs(ipfsPath, [options])` +### Parameters -`ipfsPath` can be of type: +| Name | Type | Description | +| ---- | ---- | ----------- | +| ipfsPath | [CID][] or `String` | The object to search for references | -- [`cid`][cid] of type: - - a [CID](https://github.com/ipfs/js-cid) instance - - [Buffer][b], the raw Buffer of the cid - - String, the base58 encoded version of the cid -- String, including the ipfs handler, a cid and a path to traverse to, ie: - - '/ipfs/QmXEmhrMpbVvTh61FNAxP9nU7ygVtyvZA8HZDUaqQCAb66' - - '/ipfs/QmXEmhrMpbVvTh61FNAxP9nU7ygVtyvZA8HZDUaqQCAb66/a.txt' - - 'QmXEmhrMpbVvTh61FNAxP9nU7ygVtyvZA8HZDUaqQCAb66/a.txt' +### Options -`options` is an optional object that may contain the following keys: - - `recursive (false)`: recursively list references of child nodes - - `unique (false)`: omit duplicate references from output - - `format ("")`: output edges with given format. Available tokens: ``, ``, `` - - `edges (false)`: output references in edge format: `" -> "` - - `maxDepth (1)`: only for recursive refs, limits fetch and listing to the given depth - - `timeout (number|string)`: Throw an error if the request does not complete within the specified milliseconds timeout. If `timeout` is a string, the value is parsed as a [human readable duration](https://www.npmjs.com/package/parse-duration). There is no timeout by default. +An optional object which may have the following keys: -**Returns** +| Name | Type | Default | Description | +| ---- | ---- | ------- | ----------- | +| recursive | `boolean` | `false` | Recursively list references of child nodes | +| unique | `boolean` | `false` | Omit duplicate references from output | +| format | `String` | `''` | output edges with given format. Available tokens: ``, ``, `` | +| edges | `boolean` | `false` | output references in edge format: `" -> "` | +| maxDepth | `Number` | `1` | only for recursive refs, limits fetch and listing to the given depth | +| 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 | | -------- | -------- | @@ -43,7 +50,7 @@ Each yielded object is of the form: } ``` -**Example:** +### Example ```JavaScript for await (const ref of ipfs.refs(ipfsPath, { recursive: true })) { @@ -56,13 +63,24 @@ for await (const ref of ipfs.refs(ipfsPath, { recursive: true })) { } ``` -#### `refs.local` +## `ipfs.refs.local([options])` > Output all local references (CIDs of all blocks in the blockstore) -##### `ipfs.refs.local()` +### 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** +### Returns | Type | Description | | -------- | -------- | @@ -77,7 +95,7 @@ Each yielded object is of the form: } ``` -**Example:** +### Example ```JavaScript for await (const ref of ipfs.refs.local()) { @@ -94,3 +112,4 @@ for await (const ref of ipfs.refs.local()) { [b]: https://www.npmjs.com/package/buffer [cid]: https://www.npmjs.com/package/cids [blob]: https://developer.mozilla.org/en-US/docs/Web/API/Blob +[AbortSignal]: https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal diff --git a/docs/core-api/REPO.md b/docs/core-api/REPO.md index 37c8a930fc..ad79bf8484 100644 --- a/docs/core-api/REPO.md +++ b/docs/core-api/REPO.md @@ -1,22 +1,41 @@ -# Repo API +# Repo API + +- [`ipfs.repo.gc([options])`](#ipfsrepogcoptions) + - [Parameters](#parameters) + - [Options](#options) + - [Returns](#returns) + - [Example](#example) +- [`ipfs.repo.stat([options])`](#ipfsrepostatoptions) + - [Parameters](#parameters-1) + - [Options](#options-1) + - [Returns](#returns-1) + - [Example](#example-1) + - [Notes](#notes) +- [`ipfs.repo.version([options])`](#ipfsrepoversionoptions) + - [Parameters](#parameters-2) + - [Options](#options-2) + - [Returns](#returns-2) + - [Example](#example-2) + +## `ipfs.repo.gc([options])` -* [repo.gc](#repogc) -* [repo.stat](#repostat) -* [repo.version](#repoversion) +> Perform a garbage collection sweep on the repo. -#### `repo.gc` +### Parameters -> Perform a garbage collection sweep on the repo. +None -##### `ipfs.repo.gc([options])` +### Options -Where: +An optional object which may have the following keys: -- `options` is an object that contains following properties - - `quiet` writes a minimal output. - - `stream-errors` stream errors. +| Name | Type | Default | Description | +| ---- | ---- | ------- | ----------- | +| quiet | `boolean` | `false` | Write minimal output | +| 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** +### Returns | Type | Description | | -------- | -------- | @@ -27,7 +46,7 @@ Each yielded object contains the following properties: - `err` is an `Error` if it was not possible to GC a particular block. - `cid` is the [CID][cid] of the block that was Garbage Collected. -**Example:** +### Example ```JavaScript for await (const res of ipfs.repo.gc()) { @@ -35,20 +54,25 @@ for await (const res of ipfs.repo.gc()) { } ``` -#### `repo.stat` +## `ipfs.repo.stat([options])` > Get stats for the currently used repo. -##### `ipfs.repo.stat([options])` +### Parameters -`stats.repo` and `repo.stat` can be used interchangeably. +None -Where: +### Options -- `options` is an object that contains following properties - - `human` a Boolean value to output `repoSize` in MiB. +An optional object which may have the following keys: -**Returns** +| Name | Type | Default | Description | +| ---- | ---- | ------- | ----------- | +| options | `boolean` | `false` | Return storage numbers in `MiB` | +| 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 | | -------- | -------- | @@ -62,7 +86,7 @@ the returned object has the following keys: - `version` is a string. - `storageMax` is a [BigNumber Int][1]. -**Example:** +### Example ```JavaScript const stats = await ipfs.repo.stat() @@ -75,19 +99,34 @@ console.log(stats) // storageMax: 10000000000 } ``` -#### `repo.version` +### Notes + +`stats.repo` and `repo.stat` can be used interchangeably. + +## `ipfs.repo.version([options])` > Show the repo version. -##### `ipfs.repo.version()` +### 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** +### Returns | Type | Description | | -------- | -------- | | `Promise` | A String containing the repo's version | -**Example:** +### Example ```JavaScript const version = await ipfs.repo.version() @@ -98,3 +137,4 @@ console.log(version) [1]: https://github.com/MikeMcl/bignumber.js/ [cid]: https://www.npmjs.com/package/cids +[AbortSignal]: https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal diff --git a/docs/core-api/STATS.md b/docs/core-api/STATS.md index c556c13a81..d979042822 100644 --- a/docs/core-api/STATS.md +++ b/docs/core-api/STATS.md @@ -1,36 +1,47 @@ -# Stats API +# Stats API -* [stats.bitswap](#statsbitswap) -* [stats.repo](#statsrepo) -* [stats.bw](#statsbw) +- [`ipfs.stats.bitswap([options]`](#ipfsstatsbitswapoptions) +- [`ipfs.stats.repo([options])`](#ipfsstatsrepooptions) +- [`ipfs.stats.bw([options])`](#ipfsstatsbwoptions) + - [Parameters](#parameters) + - [Options](#options) + - [Returns](#returns) + - [Example](#example) -#### `stats.bitswap` +## `ipfs.stats.bitswap([options]` > Show diagnostic information on the bitswap agent. Note: `stats.bitswap` and `bitswap.stat` can be used interchangeably. See [`bitswap.stat`](./BITSWAP.md#bitswapstat) for more details. -#### `stats.repo` +## `ipfs.stats.repo([options])` > Get stats for the currently used repo. Note: `stats.repo` and `repo.stat` can be used interchangeably. See [`repo.stat`](./REPO.md#repostat) for more details. -#### `stats.bw` +## `ipfs.stats.bw([options])` > Get IPFS bandwidth information. -##### `ipfs.stats.bw([options])` +### Parameters -Where: +None -- `options` is an optional object that might contain the following keys: - - `peer` specifies a peer to print bandwidth for. - - `proto` specifies a protocol to print bandwidth for. - - `poll` is used to yield bandwidth info at an interval. - - `interval` is the time interval to wait between updating output, if `poll` is `true`. +### Options -**Returns** +An optional object which may have the following keys: + +| Name | Type | Default | Description | +| ---- | ---- | ------- | ----------- | +| peer | [PeerId][], [CID][] or `String` | `undefined` | Specifies a peer to print bandwidth for | +| proto | `String` | `undefined` | Specifies a protocol to print bandwidth for | +| poll | `boolean` | `undefined` | Is used to yield bandwidth info at an interval | +| interval | `Number` | `undefined` | The time interval to wait between updating output, if `poll` is `true` | +| 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 | | -------- | -------- | @@ -43,7 +54,7 @@ Each yielded object contains the following keys: - `rateIn` - is a [BigNumber Int][bigNumber], in bytes. - `rateOut` - is a [BigNumber Int][bigNumber], in bytes. -**Example:** +### Example ```JavaScript for await (const stats of ipfs.stats.bw()) { @@ -59,3 +70,6 @@ A great source of [examples][] can be found in the tests for this API. [bigNumber]: https://github.com/MikeMcl/bignumber.js/ [examples]: https://github.com/ipfs/js-ipfs/blob/master/packages/interface-ipfs-core/src/stats +[AbortSignal]: https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal +[cid]: https://www.npmjs.com/package/cids +[peerid]: https://www.npmjs.com/package/peer-id diff --git a/docs/core-api/SWARM.md b/docs/core-api/SWARM.md index 80eb70ff1c..c9db832628 100644 --- a/docs/core-api/SWARM.md +++ b/docs/core-api/SWARM.md @@ -1,26 +1,56 @@ -# Swarm API +# Swarm API + +- [Swarm API](#swarm-api) + - [`ipfs.swarm.addrs([options])`](#ipfsswarmaddrsoptions) + - [Parameters](#parameters) + - [Options](#options) + - [Returns](#returns) + - [Example](#example) + - [`ipfs.swarm.connect(addr, [options])`](#ipfsswarmconnectaddr-options) + - [Parameters](#parameters-1) + - [Options](#options-1) + - [Returns](#returns-1) + - [Example](#example-1) + - [`ipfs.swarm.disconnect(addr, [options])`](#ipfsswarmdisconnectaddr-options) + - [Parameters](#parameters-2) + - [Options](#options-2) + - [Returns](#returns-2) + - [Example](#example-2) + - [`ipfs.swarm.localAddrs([options])`](#ipfsswarmlocaladdrsoptions) + - [Parameters](#parameters-3) + - [Options](#options-3) + - [Returns](#returns-3) + - [Example](#example-3) + - [`ipfs.swarm.peers([options])`](#ipfsswarmpeersoptions) + - [Parameters](#parameters-4) + - [Options](#options-4) + - [Returns](#returns-4) + - [Example](#example-4) + +## `ipfs.swarm.addrs([options])` -* [swarm.addrs](#swarmaddrs) -* [swarm.connect](#swarmconnect) -* [swarm.disconnect](#swarmdisconnect) -* [swarm.localAddrs](#swarmlocaladdrs) -* [swarm.peers](#swarmpeers) -* [swarm.filters.add](#swarmfiltersadd) (not implemented yet) -* [swarm.filters.rm](#swarmfiltersrm) (not implemented yet) +> List of known addresses of each peer connected. -#### `swarm.addrs` +### Parameters -> List of known addresses of each peer connected. +None + +### Options + +An optional object which may have the following keys: -##### `ipfs.swarm.addrs()` +| 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** +### Returns | Type | Description | | -------- | -------- | | `Promise>` | A promise that resolves to an array of objects with `id` and `addrs`. `id` is a String - the peer's ID and `addrs` is an array of [Multiaddr](https://github.com/multiformats/js-multiaddr/) - addresses for the peer. | -**Example:** +### Example ```JavaScript const peerInfos = await ipfs.swarm.addrs() @@ -45,21 +75,32 @@ peerInfos.forEach(info => { A great source of [examples][] can be found in the tests for this API. -#### `swarm.connect` +## `ipfs.swarm.connect(addr, [options])` > Open a connection to a given address. -##### `ipfs.swarm.connect(addr)` +### Parameters + +| Name | Type | Description | +| ---- | ---- | ----------- | +| addr | [MultiAddr][] | The object to search for references | + +### Options + +An optional object which may have the following keys: -Where `addr` is of type [multiaddr](https://github.com/multiformats/js-multiaddr) +| 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** +### Returns | Type | Description | | -------- | -------- | | `Promise` | If action is successfully completed. Otherwise an error will be thrown | -**Example:** +### Example ```JavaScript await ipfs.swarm.connect(addr) @@ -67,21 +108,32 @@ await ipfs.swarm.connect(addr) A great source of [examples][] can be found in the tests for this API. -#### `swarm.disconnect` +## `ipfs.swarm.disconnect(addr, [options])` > Close a connection on a given address. -##### `ipfs.swarm.disconnect(addr)` +### Parameters -Where `addr` is of type [multiaddr](https://github.com/multiformats/js-multiaddr) +| Name | Type | Description | +| ---- | ---- | ----------- | +| addr | [MultiAddr][] | The object to search for references | -**Returns** +### 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` | If action is successfully completed. Otherwise an error will be thrown | -**Example:** +### Example ```JavaScript await ipfs.swarm.disconnect(addr) @@ -89,19 +141,30 @@ await ipfs.swarm.disconnect(addr) A great source of [examples][] can be found in the tests for this API. -#### `swarm.localAddrs` +## `ipfs.swarm.localAddrs([options])` > Local addresses this node is listening on. -##### `ipfs.swarm.localAddrs()` +### 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** +### Returns | Type | Description | | -------- | -------- | | `Promise` | An array of [`Multiaddr`](https://github.com/multiformats/js-multiaddr) representing the local addresses the node is listening | -**Example:** +### Example ```JavaScript const multiAddrs = await ipfs.swarm.localAddrs() @@ -110,19 +173,28 @@ console.log(multiAddrs) A great source of [examples][] can be found in the tests for this API. -#### `swarm.peers` +## `ipfs.swarm.peers([options])` > List out the peers that we have connections with. -##### `ipfs.swarm.peers([options])` +### Parameters -`options` an optional object with the following properties: - - `direction` - set to `true` to return connection direction information. Default `false` - - `streams` - set to `true` to return information about open muxed streams. Default `false` - - `verbose` - set to `true` to return all extra information. Default `false` - - `latency` - set to `true` to return latency information. Default `false` +None -**Returns** +### Options + +An optional object which may have the following keys: + +| Name | Type | Default | Description | +| ---- | ---- | ------- | ----------- | +| direction | `boolean` | `false` | If true, return connection direction information | +| streams | `boolean` | `false` | If true, return information about open muxed streams | +| verbose | `boolean` | `false` | If true, return all extra information | +| latency | `boolean` | `false` | If true, return latency information | +| 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 | | -------- | -------- | @@ -144,7 +216,7 @@ If an error occurs trying to create an individual object, it will have the prope All other properties may be `undefined`. -**Example:** +### Example ```JavaScript const peerInfos = await ipfs.swarm.peers() @@ -153,66 +225,6 @@ console.log(peerInfos) A great source of [examples][] can be found in the tests for this API. ------------------------------- - -> NOT IMPLEMENTED YET - -#### `swarm.filters` - -> Display current multiaddr filters. Filters are a way to set up rules for the network connections established. - -##### `ipfs.swarm.filters()` - -**Returns** - -| Type | Description | -| -------- | -------- | -| `Promise` | An array of multiaddrs that represent the filters being applied | - -Example: - -```JavaScript -const filters = await ipfs.swarm.filters() -``` - -#### `swarm.filters.add` - -> Add another filter. - -##### `ipfs.swarm.filters.add(filter)` - -Where `filter` is of type [multiaddr]() - -**Returns** - -| Type | Description | -| -------- | -------- | -| `Promise` | If action is successfully completed. Otherwise an error will be thrown | - -Example: - -```JavaScript -await ipfs.swarm.filters.add(filter) -``` - -#### `swarm.filters.rm` - -> Remove a filter - -##### `ipfs.swarm.filters.rm(filter)` - -Where `filter` is of type [multiaddr]() - -**Returns** - -| Type | Description | -| -------- | -------- | -| `Promise` | If action is successfully completed. Otherwise an error will be thrown | - -Example: - -```JavaScript -await ipfs.swarm.filters.rm(filter) -``` - [examples]: https://github.com/ipfs/js-ipfs/blob/master/packages/interface-ipfs-core/src/swarm +[AbortSignal]: https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal +[MultiAddr]: https://github.com/multiformats/js-multiaddr diff --git a/examples/custom-libp2p/package.json b/examples/custom-libp2p/package.json index 83d49b8823..5dc4b618b7 100644 --- a/examples/custom-libp2p/package.json +++ b/examples/custom-libp2p/package.json @@ -17,7 +17,7 @@ "libp2p-mplex": "^0.9.3", "libp2p-secio": "^0.12.2", "libp2p-spdy": "^0.13.3", - "libp2p-tcp": "^0.14.3" + "libp2p-tcp": "^0.14.5" }, "devDependencies": { "execa": "^4.0.0", diff --git a/lerna.json b/lerna.json index 4d6666a734..354101c07f 100644 --- a/lerna.json +++ b/lerna.json @@ -9,7 +9,6 @@ "bootstrap": { "hoist": true, "nohoist": [ - "ipfs-interop", "ipfs-css", "tachyons" ] diff --git a/packages/interface-ipfs-core/package.json b/packages/interface-ipfs-core/package.json index 293db5eb39..aae893cccd 100644 --- a/packages/interface-ipfs-core/package.json +++ b/packages/interface-ipfs-core/package.json @@ -48,6 +48,7 @@ "iso-random-stream": "^1.1.1", "it-all": "^1.0.1", "it-concat": "^1.0.0", + "it-drain": "^1.0.1", "it-last": "^1.0.1", "it-pushable": "^1.3.1", "multiaddr": "^7.4.3", @@ -60,8 +61,8 @@ "temp-write": "^4.0.0" }, "devDependencies": { - "aegir": "^21.10.1", - "ipfsd-ctl": "^4.0.1" + "aegir": "^22.0.0", + "ipfsd-ctl": "^4.1.1" }, "contributors": [ "Alan Shaw ", diff --git a/packages/interface-ipfs-core/src/add.js b/packages/interface-ipfs-core/src/add.js index d804080fbf..70d86b9c85 100644 --- a/packages/interface-ipfs-core/src/add.js +++ b/packages/interface-ipfs-core/src/add.js @@ -6,6 +6,7 @@ const { fixtures } = require('./utils') const { Readable } = require('readable-stream') const all = require('it-all') const last = require('it-last') +const drain = require('it-drain') const fs = require('fs') const os = require('os') const path = require('path') @@ -14,7 +15,7 @@ const globSource = require('ipfs-utils/src/files/glob-source') const urlSource = require('ipfs-utils/src/files/url-source') const { isNode } = require('ipfs-utils/src/env') const { getDescribe, getIt, expect } = require('./utils/mocha') - +const testTimeout = require('./utils/test-timeout') const echoUrl = (text) => `${process.env.ECHO_SERVER}/download?data=${encodeURIComponent(text)}` const redirectUrl = (url) => `${process.env.ECHO_SERVER}/redirect?to=${encodeURI(url)}` @@ -62,6 +63,12 @@ module.exports = (common, options) => { after(() => common.clean()) + it('should respect timeout option when adding files', () => { + return testTimeout(() => drain(ipfs.add(Buffer.from('Hello'), { + timeout: 1 + }))) + }) + it('should add a File', async function () { if (!supportsFileReader) return this.skip('skip in node') diff --git a/packages/interface-ipfs-core/src/bitswap/stat.js b/packages/interface-ipfs-core/src/bitswap/stat.js index 7dd1264238..bb1386fe13 100644 --- a/packages/interface-ipfs-core/src/bitswap/stat.js +++ b/packages/interface-ipfs-core/src/bitswap/stat.js @@ -3,6 +3,7 @@ const { getDescribe, getIt, expect } = require('../utils/mocha') const { expectIsBitswap } = require('../stats/utils') +const testTimeout = require('../utils/test-timeout') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -23,6 +24,12 @@ module.exports = (common, options) => { after(() => common.clean()) + it('should respect timeout option when getting bitswap stats', () => { + return testTimeout(() => ipfs.bitswap.stat({ + timeout: 1 + })) + }) + it('should get bitswap stats', async () => { const res = await ipfs.bitswap.stat() expectIsBitswap(null, res) diff --git a/packages/interface-ipfs-core/src/bitswap/wantlist.js b/packages/interface-ipfs-core/src/bitswap/wantlist.js index 3afc10f704..cf91fe8bc3 100644 --- a/packages/interface-ipfs-core/src/bitswap/wantlist.js +++ b/packages/interface-ipfs-core/src/bitswap/wantlist.js @@ -4,6 +4,7 @@ const { getDescribe, getIt, expect } = 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 */ /** @@ -33,6 +34,12 @@ module.exports = (common, options) => { after(() => common.clean()) + it('should respect timeout option when getting bitswap wantlist', () => { + return testTimeout(() => ipfsA.bitswap.wantlist({ + timeout: 1 + })) + }) + it('should get the wantlist', function () { return waitForWantlistKey(ipfsB, key) }) diff --git a/packages/interface-ipfs-core/src/block/get.js b/packages/interface-ipfs-core/src/block/get.js index 3fee060984..596b84d894 100644 --- a/packages/interface-ipfs-core/src/block/get.js +++ b/packages/interface-ipfs-core/src/block/get.js @@ -4,6 +4,7 @@ const { Buffer } = require('buffer') const multihash = require('multihashes') const CID = require('cids') const { getDescribe, getIt, expect } = require('../utils/mocha') +const testTimeout = require('../utils/test-timeout') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -26,6 +27,12 @@ module.exports = (common, options) => { after(() => common.clean()) + it('should respect timeout option when getting a block', () => { + return testTimeout(() => ipfs.block.get(new CID('QmPv52ekjS75L4JmHpXVeuJ5uX2ecSfSZo88NSyxwA3rA3'), { + timeout: 1 + })) + }) + it('should get by CID object', async () => { const cid = new CID(hash) const block = await ipfs.block.get(cid) diff --git a/packages/interface-ipfs-core/src/block/put.js b/packages/interface-ipfs-core/src/block/put.js index 905d29dd98..c8d529f666 100644 --- a/packages/interface-ipfs-core/src/block/put.js +++ b/packages/interface-ipfs-core/src/block/put.js @@ -6,6 +6,8 @@ const Block = require('ipld-block') const multihash = require('multihashes') const CID = require('cids') const { getDescribe, getIt, expect } = require('../utils/mocha') +const testTimeout = require('../utils/test-timeout') +const all = require('it-all') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -25,6 +27,12 @@ module.exports = (common, options) => { after(() => common.clean()) + it('should respect timeout option when putting a block', () => { + return testTimeout(() => ipfs.block.put(Buffer.from('derp'), { + timeout: 1 + })) + }) + it('should put a buffer, using defaults', async () => { const expectedHash = 'QmPv52ekjS75L4JmHpXVeuJ5uX2ecSfSZo88NSyxwA3rAQ' const blob = Buffer.from('blorb') @@ -62,13 +70,15 @@ module.exports = (common, options) => { const block = await ipfs.block.put(blob, { format: 'raw', mhtype: 'sha2-512', - version: 1 + version: 1, + pin: true }) expect(block.data).to.be.eql(blob) 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) }) it('should put a Block instance', async () => { diff --git a/packages/interface-ipfs-core/src/block/rm.js b/packages/interface-ipfs-core/src/block/rm.js index 4446716907..6b7a9630e3 100644 --- a/packages/interface-ipfs-core/src/block/rm.js +++ b/packages/interface-ipfs-core/src/block/rm.js @@ -5,6 +5,9 @@ const { Buffer } = require('buffer') const { getDescribe, getIt, expect } = require('../utils/mocha') const { nanoid } = require('nanoid') const all = require('it-all') +const drain = require('it-drain') +const CID = require('cids') +const testTimeout = require('../utils/test-timeout') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -22,6 +25,12 @@ module.exports = (common, options) => { after(() => common.clean()) + it('should respect timeout option when removing a block', () => { + return testTimeout(() => drain(ipfs.block.rm(new CID('QmVwdDCY4SPGVFnNCiZnX5CtzwWDn6kAM98JXzKxE3kCmn'), { + timeout: 1 + }))) + }) + it('should remove by CID object', async () => { const cid = await ipfs.dag.put(Buffer.from(nanoid()), { format: 'raw', diff --git a/packages/interface-ipfs-core/src/block/stat.js b/packages/interface-ipfs-core/src/block/stat.js index ad085e03ac..b6aa745793 100644 --- a/packages/interface-ipfs-core/src/block/stat.js +++ b/packages/interface-ipfs-core/src/block/stat.js @@ -4,6 +4,7 @@ const { Buffer } = require('buffer') const CID = require('cids') const { getDescribe, getIt, expect } = require('../utils/mocha') +const testTimeout = require('../utils/test-timeout') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -26,6 +27,12 @@ module.exports = (common, options) => { after(() => common.clean()) + it('should respect timeout option when statting a block', () => { + return testTimeout(() => ipfs.block.stat(new CID('QmVwdDCY4SPGVFnNCiZnX5CtzwWDn6kAM98JXzKxE3kCmn'), { + timeout: 1 + })) + }) + it('should stat by CID', async () => { const cid = new CID(hash) const stats = await ipfs.block.stat(cid) diff --git a/packages/interface-ipfs-core/src/bootstrap/add.js b/packages/interface-ipfs-core/src/bootstrap/add.js index b4030c67a8..83f0626eea 100644 --- a/packages/interface-ipfs-core/src/bootstrap/add.js +++ b/packages/interface-ipfs-core/src/bootstrap/add.js @@ -2,6 +2,7 @@ 'use strict' const { getDescribe, getIt, expect } = require('../utils/mocha') +const testTimeout = require('../utils/test-timeout') const invalidArg = 'this/Is/So/Invalid/' const validIp4 = '/ip4/104.236.176.52/tcp/4001/p2p/QmSoLnSGccFuZQJzRadHn95W2CrSFmZuTdDWP8HXaHca9z' @@ -26,6 +27,13 @@ module.exports = (common, options) => { after(() => common.clean()) + it('should respect timeout option when adding bootstrap nodes', () => { + return testTimeout(() => ipfs.bootstrap.add(null, { + default: true, + timeout: 1 + })) + }) + it('should return an error when called with an invalid arg', () => { return expect(ipfs.bootstrap.add(invalidArg)).to.eventually.be.rejected .and.be.an.instanceOf(Error) diff --git a/packages/interface-ipfs-core/src/bootstrap/list.js b/packages/interface-ipfs-core/src/bootstrap/list.js index 9dd335ef8e..5ebd848657 100644 --- a/packages/interface-ipfs-core/src/bootstrap/list.js +++ b/packages/interface-ipfs-core/src/bootstrap/list.js @@ -2,6 +2,7 @@ 'use strict' const { getDescribe, getIt, expect } = require('../utils/mocha') +const testTimeout = require('../utils/test-timeout') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -21,6 +22,12 @@ module.exports = (common, options) => { after(() => common.clean()) + it('should respect timeout option listing bootstrap nodes', () => { + return testTimeout(() => ipfs.bootstrap.list({ + timeout: 1 + })) + }) + it('should return a list of peers', async () => { const res = await ipfs.bootstrap.list() diff --git a/packages/interface-ipfs-core/src/bootstrap/rm.js b/packages/interface-ipfs-core/src/bootstrap/rm.js index d3047d1bc4..81b7bf41e8 100644 --- a/packages/interface-ipfs-core/src/bootstrap/rm.js +++ b/packages/interface-ipfs-core/src/bootstrap/rm.js @@ -2,6 +2,7 @@ 'use strict' const { getDescribe, getIt, expect } = require('../utils/mocha') +const testTimeout = require('../utils/test-timeout') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -24,6 +25,12 @@ module.exports = (common, options) => { after(() => common.clean()) + it('should respect timeout option when removing bootstrap nodes', () => { + return testTimeout(() => ipfs.bootstrap.rm(validIp4, { + timeout: 1 + })) + }) + it('should return an error when called with an invalid arg', () => { return expect(ipfs.bootstrap.rm(invalidArg)).to.eventually.be.rejected .and.be.an.instanceOf(Error) diff --git a/packages/interface-ipfs-core/src/cat.js b/packages/interface-ipfs-core/src/cat.js index c74f82511d..936bff9933 100644 --- a/packages/interface-ipfs-core/src/cat.js +++ b/packages/interface-ipfs-core/src/cat.js @@ -6,7 +6,9 @@ const { fixtures } = require('./utils') const CID = require('cids') const concat = require('it-concat') const all = require('it-all') +const drain = require('it-drain') const { getDescribe, getIt, expect } = require('./utils/mocha') +const testTimeout = require('./utils/test-timeout') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -31,6 +33,12 @@ module.exports = (common, options) => { all(ipfs.add(fixtures.bigFile.data)) ])) + it('should respect timeout option when catting files', () => { + return testTimeout(() => drain(ipfs.cat(new CID('QmPDqvcuA4AkhBLBuh2y49yhUB98rCnxPxa3eVNC1kAbS1'), { + timeout: 1 + }))) + }) + it('should cat with a base58 string encoded multihash', async () => { const data = await concat(ipfs.cat(fixtures.smallFile.cid)) expect(data.toString()).to.contain('Plz add me!') diff --git a/packages/interface-ipfs-core/src/config/get.js b/packages/interface-ipfs-core/src/config/get.js index 7e1d15fd8f..6aac0c84d3 100644 --- a/packages/interface-ipfs-core/src/config/get.js +++ b/packages/interface-ipfs-core/src/config/get.js @@ -2,6 +2,7 @@ 'use strict' const { getDescribe, getIt, expect } = require('../utils/mocha') +const testTimeout = require('../utils/test-timeout') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -20,6 +21,12 @@ module.exports = (common, options) => { after(() => common.clean()) + it('should respect timeout option when getting config values', () => { + return testTimeout(() => ipfs.config.get('Identity.PeerID', { + timeout: 1 + })) + }) + it('should retrieve the whole config', async () => { const config = await ipfs.config.get() diff --git a/packages/interface-ipfs-core/src/config/profiles/apply.js b/packages/interface-ipfs-core/src/config/profiles/apply.js index 3466a71650..0f35683c02 100644 --- a/packages/interface-ipfs-core/src/config/profiles/apply.js +++ b/packages/interface-ipfs-core/src/config/profiles/apply.js @@ -2,6 +2,8 @@ '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 @@ -21,6 +23,12 @@ module.exports = (common, options) => { after(() => common.clean()) + it('should respect timeout option when applying a config profile', () => { + return testTimeout(() => ipfs.config.profiles.apply('server', { + timeout: 1 + })) + }) + it('should apply a config profile', async () => { const diff = await ipfs.config.profiles.apply('lowpower') expect(diff.original.Swarm.ConnMgr.LowWater).to.not.equal(diff.updated.Swarm.ConnMgr.LowWater) diff --git a/packages/interface-ipfs-core/src/config/profiles/list.js b/packages/interface-ipfs-core/src/config/profiles/list.js index ca6187fbbe..b46c1d5c70 100644 --- a/packages/interface-ipfs-core/src/config/profiles/list.js +++ b/packages/interface-ipfs-core/src/config/profiles/list.js @@ -2,6 +2,8 @@ '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 @@ -21,6 +23,12 @@ module.exports = (common, options) => { after(() => common.clean()) + it('should respect timeout option when listing config profiles', () => { + return testTimeout(() => ipfs.config.profiles.list({ + timeout: 1 + })) + }) + it('should list config profiles', async () => { const profiles = await ipfs.config.profiles.list() diff --git a/packages/interface-ipfs-core/src/config/replace.js b/packages/interface-ipfs-core/src/config/replace.js index 5fe2e4d563..0d9360427f 100644 --- a/packages/interface-ipfs-core/src/config/replace.js +++ b/packages/interface-ipfs-core/src/config/replace.js @@ -2,6 +2,8 @@ '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 @@ -25,6 +27,12 @@ module.exports = (common, options) => { Fruit: 'Bananas' } + it('should respect timeout option when replacing config', () => { + return testTimeout(() => ipfs.config.replace(config, { + timeout: 1 + })) + }) + it('should replace the whole config', async () => { await ipfs.config.replace(config) diff --git a/packages/interface-ipfs-core/src/config/set.js b/packages/interface-ipfs-core/src/config/set.js index 7a201eeaac..bcde94a614 100644 --- a/packages/interface-ipfs-core/src/config/set.js +++ b/packages/interface-ipfs-core/src/config/set.js @@ -3,6 +3,8 @@ const { Buffer } = require('buffer') const { getDescribe, getIt, expect } = require('../utils/mocha') +const testTimeout = require('../utils/test-timeout') + /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** * @param {Factory} common @@ -22,6 +24,12 @@ module.exports = (common, options) => { after(() => common.clean()) + it('should respect timeout option when setting config values', () => { + return testTimeout(() => ipfs.config.set('Fruit', 'banana', { + timeout: 1 + })) + }) + it('should set a new key', async () => { await ipfs.config.set('Fruit', 'banana') diff --git a/packages/interface-ipfs-core/src/dag/get.js b/packages/interface-ipfs-core/src/dag/get.js index b63a31d012..c8a1cbfbbd 100644 --- a/packages/interface-ipfs-core/src/dag/get.js +++ b/packages/interface-ipfs-core/src/dag/get.js @@ -8,7 +8,9 @@ const dagCBOR = require('ipld-dag-cbor') const importer = require('ipfs-unixfs-importer') const Unixfs = require('ipfs-unixfs') const all = require('it-all') +const CID = require('cids') const { getDescribe, getIt, expect } = require('../utils/mocha') +const testTimeout = require('../utils/test-timeout') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -52,6 +54,12 @@ module.exports = (common, options) => { await ipfs.dag.put(nodeCbor, { format: 'dag-cbor', hashAlg: 'sha2-256' }) }) + it('should respect timeout option when getting a DAG node', () => { + return testTimeout(() => ipfs.dag.get(new CID('QmPv52ekjS75L4JmHpXVeuJ5uX2ecSfSZo88NSyxwA3rAQ'), { + timeout: 1 + })) + }) + it('should get a dag-pb node', async () => { const cid = await ipfs.dag.put(pbNode, { format: 'dag-pb', diff --git a/packages/interface-ipfs-core/src/dag/put.js b/packages/interface-ipfs-core/src/dag/put.js index f377b73543..4d0f8e40ea 100644 --- a/packages/interface-ipfs-core/src/dag/put.js +++ b/packages/interface-ipfs-core/src/dag/put.js @@ -8,6 +8,7 @@ const dagCBOR = require('ipld-dag-cbor') const CID = require('cids') const multihash = require('multihashes') const { getDescribe, getIt, expect } = require('../utils/mocha') +const testTimeout = require('../utils/test-timeout') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -44,6 +45,14 @@ module.exports = (common, options) => { done() }) + it('should respect timeout option when putting a DAG node', () => { + return testTimeout(() => ipfs.dag.put(pbNode, { + format: 'dag-pb', + hashAlg: 'sha2-256', + timeout: 1 + })) + }) + it('should put dag-pb with default hash func (sha2-256)', () => { return ipfs.dag.put(pbNode, { format: 'dag-pb', diff --git a/packages/interface-ipfs-core/src/dag/tree.js b/packages/interface-ipfs-core/src/dag/tree.js index 0b25ff62e0..ada763b097 100644 --- a/packages/interface-ipfs-core/src/dag/tree.js +++ b/packages/interface-ipfs-core/src/dag/tree.js @@ -6,7 +6,10 @@ const dagPB = require('ipld-dag-pb') const DAGNode = dagPB.DAGNode const dagCBOR = require('ipld-dag-cbor') const all = require('it-all') +const drain = require('it-drain') const { getDescribe, getIt, expect } = require('../utils/mocha') +const CID = require('cids') +const testTimeout = require('../utils/test-timeout') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -43,6 +46,12 @@ module.exports = (common, options) => { await ipfs.dag.put(nodeCbor, { format: 'dag-cbor', hashAlg: 'sha2-256' }) }) + it('should respect timeout option when resolving a DAG tree', () => { + return testTimeout(() => drain(ipfs.dag.tree(new CID('QmPv52ekjS75L4JmHpXVeuJ5uX2ecSfSZo88NSyxwA3rA8'), { + timeout: 1 + }))) + }) + it('should get tree with CID', async () => { const paths = await all(ipfs.dag.tree(cidCbor)) expect(paths).to.eql([ diff --git a/packages/interface-ipfs-core/src/dht/find-peer.js b/packages/interface-ipfs-core/src/dht/find-peer.js index a742f45dbd..bcec1d725a 100644 --- a/packages/interface-ipfs-core/src/dht/find-peer.js +++ b/packages/interface-ipfs-core/src/dht/find-peer.js @@ -2,6 +2,7 @@ 'use strict' const { getDescribe, getIt, expect } = require('../utils/mocha') +const testTimeout = require('../utils/test-timeout') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -26,6 +27,14 @@ module.exports = (common, options) => { after(() => common.clean()) + it('should respect timeout option when finding a peer on the DHT', async () => { + const nodeBId = await nodeB.id() + + await testTimeout(() => nodeA.dht.findPeer(nodeBId, { + timeout: 1 + })) + }) + it('should find other peers', async () => { const nodeBId = await nodeB.id() const res = await nodeA.dht.findPeer(nodeBId.id) diff --git a/packages/interface-ipfs-core/src/dht/find-provs.js b/packages/interface-ipfs-core/src/dht/find-provs.js index 9b3c047ceb..a7b2a1b7d8 100644 --- a/packages/interface-ipfs-core/src/dht/find-provs.js +++ b/packages/interface-ipfs-core/src/dht/find-provs.js @@ -3,7 +3,9 @@ const { getDescribe, getIt, expect } = require('../utils/mocha') const all = require('it-all') +const drain = require('it-drain') const { fakeCid } = require('./utils') +const testTimeout = require('../utils/test-timeout') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -49,6 +51,12 @@ module.exports = (common, options) => { ]) }) + it('should respect timeout option when finding providers on the DHT', () => { + return testTimeout(() => drain(nodeA.dht.findProvs(providedCid, { + timeout: 1 + }))) + }) + it('should be able to find providers', async function () { this.timeout(20 * 1000) diff --git a/packages/interface-ipfs-core/src/dht/get.js b/packages/interface-ipfs-core/src/dht/get.js index ad73c9b39e..a886c3be8a 100644 --- a/packages/interface-ipfs-core/src/dht/get.js +++ b/packages/interface-ipfs-core/src/dht/get.js @@ -2,8 +2,9 @@ 'use strict' const { Buffer } = require('buffer') -const { nanoid } = require('nanoid') const { getDescribe, getIt, expect } = require('../utils/mocha') +const testTimeout = require('../utils/test-timeout') +const drain = require('it-drain') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -28,19 +29,27 @@ module.exports = (common, options) => { after(() => common.clean()) + it('should respect timeout option when getting a value from the DHT', async () => { + const key = Buffer.from('/ipfs/QmUNLLsPACCz1vLxQVkXqqLX5R1X345qqfHbsf67hvA3Nn') + const data = Buffer.from('data') + + await drain(nodeA.dht.put(key, data, { verbose: true })) + + await testTimeout(() => nodeB.dht.get(key, { + timeout: 1 + })) + }) + it('should error when getting a non-existent key from the DHT', () => { return expect(nodeA.dht.get('non-existing', { timeout: 100 })).to.eventually.be.rejected .and.be.an.instanceOf(Error) }) - // TODO: revisit this test - it puts an invalid key and so go-ipfs throws - // "invalid record keytype" - it needs to put a valid key and value for it to - // be a useful test. - it.skip('should get a value after it was put on another node', async () => { - const key = Buffer.from(nanoid()) - const value = Buffer.from(nanoid()) + it('should get a value after it was put on another node', async () => { + const key = Buffer.from('/ipfs/QmUNLLsPACCz1vLxQVkXqqLX5R1X345qqfHbsf67hvA3Nn') + const value = Buffer.from('data') - await nodeB.dht.put(key, value) + await drain(nodeB.dht.put(key, value)) const result = await nodeA.dht.get(key) expect(result).to.eql(value) diff --git a/packages/interface-ipfs-core/src/dht/provide.js b/packages/interface-ipfs-core/src/dht/provide.js index e040e509c5..699a3cdfb8 100644 --- a/packages/interface-ipfs-core/src/dht/provide.js +++ b/packages/interface-ipfs-core/src/dht/provide.js @@ -5,6 +5,8 @@ const { Buffer } = require('buffer') const CID = require('cids') const all = require('it-all') const { getDescribe, getIt, expect } = require('../utils/mocha') +const testTimeout = require('../utils/test-timeout') +const last = require('it-last') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -28,6 +30,14 @@ module.exports = (common, options) => { after(() => common.clean()) + it('should respect timeout option when providing a value on the DHT', async () => { + const res = await last(ipfs.add(Buffer.from('test'))) + + await testTimeout(() => ipfs.dht.provide(res.cid, { + timeout: 1 + })) + }) + it('should provide local CID', async () => { const res = await all(ipfs.add(Buffer.from('test'))) diff --git a/packages/interface-ipfs-core/src/dht/put.js b/packages/interface-ipfs-core/src/dht/put.js index b126ef4eaa..3c579e9d20 100644 --- a/packages/interface-ipfs-core/src/dht/put.js +++ b/packages/interface-ipfs-core/src/dht/put.js @@ -3,7 +3,9 @@ const { Buffer } = require('buffer') const { getDescribe, getIt } = require('../utils/mocha') -const all = require('it-all') +const drain = require('it-drain') +const testTimeout = require('../utils/test-timeout') +const CID = require('cids') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -29,15 +31,19 @@ module.exports = (common, options) => { after(() => common.clean()) + it('should respect timeout option when putting a value into the DHT', () => { + return testTimeout(() => nodeA.dht.put(new CID('Qmd7qZS4T7xXtsNFdRoK1trfMs5zU94EpokQ9WFtxdPxsZ'), Buffer.from('derp'), { + timeout: 1 + })) + }) + it('should put a value to the DHT', async function () { this.timeout(80 * 1000) const key = Buffer.from('/ipfs/QmUNLLsPACCz1vLxQVkXqqLX5R1X345qqfHbsf67hvA3Nn') const data = Buffer.from('data') - await all(nodeA.dht.put(key, data, { verbose: true })) - - // await nodeA.dht.put(key, data) + await drain(nodeA.dht.put(key, data, { verbose: true })) }) }) } diff --git a/packages/interface-ipfs-core/src/dht/query.js b/packages/interface-ipfs-core/src/dht/query.js index b5acdee2aa..6df7cf2b4c 100644 --- a/packages/interface-ipfs-core/src/dht/query.js +++ b/packages/interface-ipfs-core/src/dht/query.js @@ -3,6 +3,8 @@ const { getDescribe, getIt, expect } = require('../utils/mocha') const all = require('it-all') +const drain = require('it-drain') +const testTimeout = require('../utils/test-timeout') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -27,6 +29,12 @@ module.exports = (common, options) => { after(() => common.clean()) + it('should respect timeout option when querying the DHT', () => { + return testTimeout(() => drain(nodeA.dht.query(nodeB.peerId.id, { + timeout: 1 + }))) + }) + it('should return the other node in the query', async function () { const timeout = 150 * 1000 this.timeout(timeout) diff --git a/packages/interface-ipfs-core/src/files/chmod.js b/packages/interface-ipfs-core/src/files/chmod.js index 10f696de4f..0b501fcf81 100644 --- a/packages/interface-ipfs-core/src/files/chmod.js +++ b/packages/interface-ipfs-core/src/files/chmod.js @@ -5,6 +5,7 @@ const { Buffer } = require('buffer') const { nanoid } = require('nanoid') const { getDescribe, getIt, expect } = require('../utils/mocha') const isShardAtPath = require('../utils/is-shard-at-path') +const testTimeout = require('../utils/test-timeout') module.exports = (common, options) => { const describe = getDescribe(options) @@ -330,5 +331,17 @@ module.exports = (common, options) => { // files with prior execute bit should now be user and group executable await expect(ipfs.files.stat(bin)).to.eventually.have.property('mode', 0o754) }) + + it('should respect timeout option when changing the mode of a file', async () => { + const path = `/foo-${Math.random()}` + + await ipfs.files.write(path, Buffer.from('Hello world'), { + create: true + }) + + await testTimeout(() => ipfs.files.chmod(path, '0777', { + timeout: 1 + })) + }) }) } diff --git a/packages/interface-ipfs-core/src/files/cp.js b/packages/interface-ipfs-core/src/files/cp.js index bed978137e..0fbcd0f6ae 100644 --- a/packages/interface-ipfs-core/src/files/cp.js +++ b/packages/interface-ipfs-core/src/files/cp.js @@ -13,6 +13,7 @@ const CID = require('cids') const randomBytes = require('iso-random-stream/src/random') const createShardedDirectory = require('../utils/create-sharded-directory') const isShardAtPath = require('../utils/is-shard-at-path') +const testTimeout = require('../utils/test-timeout') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -438,5 +439,11 @@ module.exports = (common, options) => { expect(stats).to.have.deep.property('mtime', expectedMtime) expect(stats).to.have.property('mode', mode) }) + + it('should respect timeout option when copying a file', async () => { + await testTimeout(() => ipfs.files.cp('/ipfs/QmaWLMK8yg36wMZX4Ybz7PAbKi1z5FzEtg5iEVeXHtNBqa', '/derp', { + timeout: 1 + })) + }) }) } diff --git a/packages/interface-ipfs-core/src/files/flush.js b/packages/interface-ipfs-core/src/files/flush.js index 04a4546deb..479307d5eb 100644 --- a/packages/interface-ipfs-core/src/files/flush.js +++ b/packages/interface-ipfs-core/src/files/flush.js @@ -3,6 +3,7 @@ const { nanoid } = require('nanoid') const { getDescribe, getIt, expect } = require('../utils/mocha') +const testTimeout = require('../utils/test-timeout') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -49,5 +50,11 @@ module.exports = (common, options) => { expect(dirStats.cid.toString()).to.equal(flushed.toString()) }) + + it('should respect timeout option when flushing changes', async () => { + 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 152a403ad0..21ed098554 100644 --- a/packages/interface-ipfs-core/src/files/ls.js +++ b/packages/interface-ipfs-core/src/files/ls.js @@ -6,7 +6,9 @@ const { getDescribe, getIt, expect } = require('../utils/mocha') const CID = require('cids') const createShardedDirectory = require('../utils/create-sharded-directory') const all = require('it-all') +const drain = require('it-drain') const randomBytes = require('iso-random-stream/src/random') +const testTimeout = require('../utils/test-timeout') const MFS_FILE_TYPES = { file: 0, @@ -197,5 +199,11 @@ module.exports = (common, options) => { expect(files.length).to.equal(1) expect(files.filter(file => file.name === fileName)).to.be.ok() }) + + it('should respect timeout option when listing files', async () => { + await testTimeout(() => drain(ipfs.files.ls({ + timeout: 1 + }))) + }) }) } diff --git a/packages/interface-ipfs-core/src/files/mkdir.js b/packages/interface-ipfs-core/src/files/mkdir.js index 15f8b3c6b4..ae920d30e8 100644 --- a/packages/interface-ipfs-core/src/files/mkdir.js +++ b/packages/interface-ipfs-core/src/files/mkdir.js @@ -7,6 +7,7 @@ const multihash = require('multihashes') const createShardedDirectory = require('../utils/create-sharded-directory') const all = require('it-all') const isShardAtPath = require('../utils/is-shard-at-path') +const testTimeout = require('../utils/test-timeout') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -224,5 +225,11 @@ module.exports = (common, options) => { nsecs: mtime[1] }) }) + + it('should respect timeout option when making a directory', async () => { + await testTimeout(() => ipfs.files.mkdir('/dir-to-make', { + timeout: 1 + })) + }) }) } diff --git a/packages/interface-ipfs-core/src/files/mv.js b/packages/interface-ipfs-core/src/files/mv.js index 816edd99fa..f0fd539841 100644 --- a/packages/interface-ipfs-core/src/files/mv.js +++ b/packages/interface-ipfs-core/src/files/mv.js @@ -7,6 +7,7 @@ const createShardedDirectory = require('../utils/create-sharded-directory') const concat = require('it-concat') const randomBytes = require('iso-random-stream/src/random') const isShardAtPath = require('../utils/is-shard-at-path') +const testTimeout = require('../utils/test-timeout') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -267,5 +268,19 @@ module.exports = (common, options) => { expect(error.message).to.contain('does not exist') } }) + + it('should respect timeout option when moving files', async () => { + const source = `/source-file-${Math.random()}.txt` + const destination = `/dest-file-${Math.random()}.txt` + const data = randomBytes(500) + + await ipfs.files.write(source, data, { + create: true + }) + + await testTimeout(() => ipfs.files.mv(source, destination, { + timeout: 1 + })) + }) }) } diff --git a/packages/interface-ipfs-core/src/files/read.js b/packages/interface-ipfs-core/src/files/read.js index 6ce656a8b3..adfbfde7a4 100644 --- a/packages/interface-ipfs-core/src/files/read.js +++ b/packages/interface-ipfs-core/src/files/read.js @@ -4,10 +4,12 @@ const { Buffer } = require('buffer') const concat = require('it-concat') const all = require('it-all') +const drain = require('it-drain') const { fixtures } = require('../utils') const { getDescribe, getIt, expect } = require('../utils/mocha') const createShardedDirectory = require('../utils/create-sharded-directory') const randomBytes = require('iso-random-stream/src/random') +const testTimeout = require('../utils/test-timeout') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -155,5 +157,18 @@ module.exports = (common, options) => { const testFileData = await concat(ipfs.files.read(`/ipfs/${cid}`)) expect(testFileData.slice()).to.eql(fixtures.smallFile.data) }) + + it('should respect timeout option when reading files', async () => { + const path = `/some-file-${Math.random()}.txt` + const data = randomBytes(100) + + await ipfs.files.write(path, data, { + create: true + }) + + await testTimeout(() => drain(ipfs.files.read(path, { + timeout: 1 + }))) + }) }) } diff --git a/packages/interface-ipfs-core/src/files/rm.js b/packages/interface-ipfs-core/src/files/rm.js index debe1467f6..6f149485e5 100644 --- a/packages/interface-ipfs-core/src/files/rm.js +++ b/packages/interface-ipfs-core/src/files/rm.js @@ -7,6 +7,7 @@ const createShardedDirectory = require('../utils/create-sharded-directory') const createTwoShards = require('../utils/create-two-shards') const randomBytes = require('iso-random-stream/src/random') const isShardAtPath = require('../utils/is-shard-at-path') +const testTimeout = require('../utils/test-timeout') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -256,5 +257,18 @@ module.exports = (common, options) => { expect((await ipfs.files.stat(dirPath)).type).to.equal('directory') expect(updatedDirCid.toString()).to.deep.equal(dirWithSomeFiles.toString()) }) + + it('should respect timeout option when removing files', async () => { + const file = `/some-file-${Math.random()}.txt` + + await ipfs.files.write(file, randomBytes(100), { + create: true, + parents: true + }) + + await testTimeout(() => ipfs.files.rm(file, { + timeout: 1 + })) + }) }) } diff --git a/packages/interface-ipfs-core/src/files/stat.js b/packages/interface-ipfs-core/src/files/stat.js index c7cda7e872..5ac2508abf 100644 --- a/packages/interface-ipfs-core/src/files/stat.js +++ b/packages/interface-ipfs-core/src/files/stat.js @@ -12,6 +12,7 @@ const mh = require('multihashes') const Block = require('ipld-block') const randomBytes = require('iso-random-stream/src/random') const isShardAtPath = require('../utils/is-shard-at-path') +const testTimeout = require('../utils/test-timeout') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -381,5 +382,14 @@ module.exports = (common, options) => { expect(stat.local).to.be.undefined() expect(stat.sizeLocal).to.be.undefined() }) + + it('should respect timeout option when statting files', async () => { + const path = `/directory-${Math.random()}` + await ipfs.files.mkdir(path) + + await testTimeout(() => ipfs.files.stat(path, { + timeout: 1 + })) + }) }) } diff --git a/packages/interface-ipfs-core/src/files/touch.js b/packages/interface-ipfs-core/src/files/touch.js index 18e4c1bc14..b229df99f2 100644 --- a/packages/interface-ipfs-core/src/files/touch.js +++ b/packages/interface-ipfs-core/src/files/touch.js @@ -6,6 +6,7 @@ const { nanoid } = require('nanoid') const { getDescribe, getIt, expect } = require('../utils/mocha') const delay = require('delay') const concat = require('it-concat') +const testTimeout = require('../utils/test-timeout') module.exports = (common, options) => { const describe = getDescribe(options) @@ -156,5 +157,11 @@ module.exports = (common, options) => { nsecs: mtime[1] }) }) + + it('should respect timeout option when updating the modification time of files', async () => { + await testTimeout(() => ipfs.files.touch('/derp', { + timeout: 1 + })) + }) }) } diff --git a/packages/interface-ipfs-core/src/files/write.js b/packages/interface-ipfs-core/src/files/write.js index 079b0bf1be..fe761c9c99 100644 --- a/packages/interface-ipfs-core/src/files/write.js +++ b/packages/interface-ipfs-core/src/files/write.js @@ -14,6 +14,7 @@ const randomStream = require('iso-random-stream') const all = require('it-all') const concat = require('it-concat') const isShardAtPath = require('../utils/is-shard-at-path') +const testTimeout = require('../utils/test-timeout') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -93,11 +94,10 @@ module.exports = (common, options) => { after(() => common.clean()) - // TODO: streaming request errors do not work over http - it.skip('explodes if it cannot convert content to a source', async () => { + it('explodes if it cannot convert content to a source', async () => { await expect(ipfs.files.write('/foo-bad-source', -1, { create: true - })).to.eventually.be.rejectedWith(/unexpected input/) + })).to.eventually.be.rejected() }) it('explodes if given an invalid path', async () => { @@ -119,12 +119,13 @@ module.exports = (common, options) => { }) it('creates a zero length file when passed a zero length', async () => { - await ipfs.files.write('/foo-zero-length', Buffer.from('foo'), { + const path = '/foo-zero-length' + await ipfs.files.write(path, Buffer.from('foo'), { length: 0, create: true }) - await expect(all(ipfs.files.ls('/'))).to.eventually.have.lengthOf(1) + await expect(all(ipfs.files.ls(path))).to.eventually.have.lengthOf(1) .and.to.have.nested.property('[0]').that.includes({ name: 'foo-zero-length', size: 0 @@ -867,5 +868,12 @@ module.exports = (common, options) => { nsecs: mtime[1] }) }) + + it('should respect timeout option when writing files', async () => { + await testTimeout(() => ipfs.files.write('/derp', [], { + create: true, + timeout: 1 + })) + }) }) } diff --git a/packages/interface-ipfs-core/src/get.js b/packages/interface-ipfs-core/src/get.js index 8e04222ee3..d97a172a34 100644 --- a/packages/interface-ipfs-core/src/get.js +++ b/packages/interface-ipfs-core/src/get.js @@ -6,7 +6,9 @@ const { fixtures } = require('./utils') const CID = require('cids') const all = require('it-all') const concat = require('it-concat') +const drain = require('it-drain') const { getDescribe, getIt, expect } = require('./utils/mocha') +const testTimeout = require('./utils/test-timeout') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -30,6 +32,12 @@ module.exports = (common, options) => { after(() => common.clean()) + it('should respect timeout option when getting files', () => { + return testTimeout(() => drain(ipfs.get(new CID('QmPDqvcuA4AkhBLBuh2y49yhUB98rCnxPxa3eVNC1kAbS1'), { + timeout: 1 + }))) + }) + it('should get with a base58 encoded multihash', async () => { const files = await all(ipfs.get(fixtures.smallFile.cid)) expect(files).to.be.length(1) diff --git a/packages/interface-ipfs-core/src/key/export.js b/packages/interface-ipfs-core/src/key/export.js index 467b4459e0..160af76ce4 100644 --- a/packages/interface-ipfs-core/src/key/export.js +++ b/packages/interface-ipfs-core/src/key/export.js @@ -3,6 +3,7 @@ const { nanoid } = require('nanoid') const { getDescribe, getIt, expect } = require('../utils/mocha') +const testTimeout = require('../utils/test-timeout') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -22,6 +23,12 @@ module.exports = (common, options) => { after(() => common.clean()) + it('should respect timeout option when exporting a key', () => { + return testTimeout(() => ipfs.key.export('self', nanoid(), { + timeout: 1 + })) + }) + it('should export "self" key', async function () { const pem = await ipfs.key.export('self', nanoid()) expect(pem).to.exist() diff --git a/packages/interface-ipfs-core/src/key/gen.js b/packages/interface-ipfs-core/src/key/gen.js index d3241b1382..9b3257eb00 100644 --- a/packages/interface-ipfs-core/src/key/gen.js +++ b/packages/interface-ipfs-core/src/key/gen.js @@ -3,6 +3,7 @@ const { nanoid } = require('nanoid') const { getDescribe, getIt, expect } = require('../utils/mocha') +const testTimeout = require('../utils/test-timeout') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -26,6 +27,14 @@ module.exports = (common, options) => { after(() => common.clean()) + it('should respect timeout option when generating a key', () => { + return testTimeout(() => ipfs.key.gen(nanoid(), { + type: 'rsa', + size: 2048, + timeout: 1 + })) + }) + keyTypes.forEach((kt) => { it(`should generate a new ${kt.type} key`, async function () { this.timeout(20 * 1000) diff --git a/packages/interface-ipfs-core/src/key/import.js b/packages/interface-ipfs-core/src/key/import.js index 1faa262a8d..6bc116e6c6 100644 --- a/packages/interface-ipfs-core/src/key/import.js +++ b/packages/interface-ipfs-core/src/key/import.js @@ -3,6 +3,7 @@ const { nanoid } = require('nanoid') const { getDescribe, getIt, expect } = require('../utils/mocha') +const testTimeout = require('../utils/test-timeout') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -22,6 +23,17 @@ module.exports = (common, options) => { after(() => common.clean()) + it('should respect timeout option when importing a key', async () => { + const password = nanoid() + + const pem = await ipfs.key.export('self', password) + expect(pem).to.exist() + + await testTimeout(() => ipfs.key.import('derp', pem, password, { + timeout: 1 + })) + }) + it('should import an exported key', async () => { const password = nanoid() diff --git a/packages/interface-ipfs-core/src/key/list.js b/packages/interface-ipfs-core/src/key/list.js index a965b80c5a..c90c53f82f 100644 --- a/packages/interface-ipfs-core/src/key/list.js +++ b/packages/interface-ipfs-core/src/key/list.js @@ -3,6 +3,7 @@ const { nanoid } = require('nanoid') const { getDescribe, getIt, expect } = require('../utils/mocha') +const testTimeout = require('../utils/test-timeout') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -22,6 +23,12 @@ module.exports = (common, options) => { after(() => common.clean()) + it('should respect timeout option when listing keys', () => { + return testTimeout(() => ipfs.key.list({ + timeout: 1 + })) + }) + it('should list all the keys', async function () { this.timeout(60 * 1000) diff --git a/packages/interface-ipfs-core/src/key/rename.js b/packages/interface-ipfs-core/src/key/rename.js index 9eafa9d622..5ccb6a9ec4 100644 --- a/packages/interface-ipfs-core/src/key/rename.js +++ b/packages/interface-ipfs-core/src/key/rename.js @@ -3,6 +3,7 @@ const { nanoid } = require('nanoid') const { getDescribe, getIt, expect } = require('../utils/mocha') +const testTimeout = require('../utils/test-timeout') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -22,6 +23,16 @@ module.exports = (common, options) => { after(() => common.clean()) + it('should respect timeout option when renaming keys', async () => { + const oldName = nanoid() + const newName = nanoid() + await ipfs.key.gen(oldName, { type: 'rsa', size: 2048 }) + + await testTimeout(() => ipfs.key.rename(oldName, newName, { + timeout: 1 + })) + }) + it('should rename a key', async function () { this.timeout(30 * 1000) diff --git a/packages/interface-ipfs-core/src/key/rm.js b/packages/interface-ipfs-core/src/key/rm.js index df8f7ed143..0f8338aa68 100644 --- a/packages/interface-ipfs-core/src/key/rm.js +++ b/packages/interface-ipfs-core/src/key/rm.js @@ -3,6 +3,7 @@ const { nanoid } = require('nanoid') const { getDescribe, getIt, expect } = require('../utils/mocha') +const testTimeout = require('../utils/test-timeout') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -22,6 +23,15 @@ module.exports = (common, options) => { after(() => common.clean()) + it('should respect timeout option when removing keys', async () => { + const name = nanoid() + await ipfs.key.gen(name, { type: 'rsa', size: 2048 }) + + await testTimeout(() => ipfs.key.rm(name, { + timeout: 1 + })) + }) + it('should rm a key', async function () { this.timeout(30 * 1000) diff --git a/packages/interface-ipfs-core/src/ls.js b/packages/interface-ipfs-core/src/ls.js index 69ddb43fb6..9d237ac1fe 100644 --- a/packages/interface-ipfs-core/src/ls.js +++ b/packages/interface-ipfs-core/src/ls.js @@ -5,6 +5,9 @@ const { Buffer } = require('buffer') const { fixtures } = require('./utils') const { getDescribe, getIt, expect } = require('./utils/mocha') const all = require('it-all') +const drain = require('it-drain') +const CID = require('cids') +const testTimeout = require('./utils/test-timeout') const randomName = prefix => `${prefix}${Math.round(Math.random() * 1000)}` @@ -28,6 +31,12 @@ module.exports = (common, options) => { after(() => common.clean()) + it('should respect timeout option when listing files', () => { + return testTimeout(() => drain(ipfs.ls(new CID('QmVvjDy7yF7hdnqE8Hrf4MHo5ABDtb5AbX6hWbD3Y42bXP'), { + timeout: 1 + }))) + }) + it('should ls with a base58 encoded CID', async function () { const content = (name) => ({ path: `test-folder/${name}`, @@ -195,5 +204,22 @@ module.exports = (common, options) => { expect(output[1].mtime).to.deep.equal(expectedMtime) expect(output[1].mode).to.equal(expectedMode) }) + + it('should ls files by subdir', async () => { + const dir = randomName('DIR') + const subdir = randomName('F0') + const subfile = randomName('F1') + + const input = [ + { path: `${dir}/${subdir}/${subfile}`, content: Buffer.from(randomName('D1')) } + ] + + const res = await all(ipfs.add(input)) + const path = `${res[res.length - 1].cid}/${subdir}` + const output = await all(ipfs.ls(path)) + + expect(output).to.have.lengthOf(1) + expect(output[0]).to.have.property('path', `${path}/${subfile}`) + }) }) } diff --git a/packages/interface-ipfs-core/src/miscellaneous/dns.js b/packages/interface-ipfs-core/src/miscellaneous/dns.js index 585557c15b..3c69572648 100644 --- a/packages/interface-ipfs-core/src/miscellaneous/dns.js +++ b/packages/interface-ipfs-core/src/miscellaneous/dns.js @@ -2,6 +2,7 @@ 'use strict' const { getDescribe, getIt, expect } = require('../utils/mocha') +const testTimeout = require('../utils/test-timeout') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -23,6 +24,12 @@ module.exports = (common, options) => { after(() => common.clean()) + it('should respect timeout option when resolving a DNS name', () => { + return testTimeout(() => ipfs.dns('derp.io', { + timeout: 1 + })) + }) + it('should non-recursively resolve ipfs.io', async () => { const res = await ipfs.dns('ipfs.io', { recursive: false }) diff --git a/packages/interface-ipfs-core/src/miscellaneous/id.js b/packages/interface-ipfs-core/src/miscellaneous/id.js index 98cbf6db50..d862f85a99 100644 --- a/packages/interface-ipfs-core/src/miscellaneous/id.js +++ b/packages/interface-ipfs-core/src/miscellaneous/id.js @@ -4,6 +4,7 @@ const { getDescribe, getIt, expect } = require('../utils/mocha') const Multiaddr = require('multiaddr') const CID = require('cids') +const testTimeout = require('../utils/test-timeout') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -24,6 +25,12 @@ module.exports = (common, options) => { after(() => common.clean()) + it('should respect timeout option when getting the node id', () => { + return testTimeout(() => ipfs.id({ + timeout: 1 + })) + }) + it('should get the node ID', async () => { const res = await ipfs.id() expect(res).to.have.a.property('id').that.is.a('string') diff --git a/packages/interface-ipfs-core/src/miscellaneous/resolve.js b/packages/interface-ipfs-core/src/miscellaneous/resolve.js index dd3a2088ad..f3d7250bf5 100644 --- a/packages/interface-ipfs-core/src/miscellaneous/resolve.js +++ b/packages/interface-ipfs-core/src/miscellaneous/resolve.js @@ -9,6 +9,7 @@ const multibase = require('multibase') const { getDescribe, getIt, expect } = require('../utils/mocha') const all = require('it-all') const { isWebWorker } = require('ipfs-utils/src/env') +const testTimeout = require('../utils/test-timeout') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -29,6 +30,12 @@ module.exports = (common, options) => { after(() => common.clean()) + it('should respect timeout option when resoving an ipfs path', () => { + return testTimeout(() => ipfs.resolve('/ipfs/Qmd7qZS4T7xXtsNFdRoK1trfMs5zU94EpokQ9WFtxdPxsZ/herp/derp', { + timeout: 1 + })) + }) + it('should resolve an IPFS hash', async () => { const content = loadFixture('test/fixtures/testfile.txt', 'interface-ipfs-core') diff --git a/packages/interface-ipfs-core/src/miscellaneous/stop.js b/packages/interface-ipfs-core/src/miscellaneous/stop.js index c8dc16d49d..44f9997dbf 100644 --- a/packages/interface-ipfs-core/src/miscellaneous/stop.js +++ b/packages/interface-ipfs-core/src/miscellaneous/stop.js @@ -2,6 +2,7 @@ 'use strict' const { getDescribe, getIt, expect } = require('../utils/mocha') +const testTimeout = require('../utils/test-timeout') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -14,15 +15,32 @@ module.exports = (common, options) => { describe('.stop', function () { this.timeout(60 * 1000) + let ipfs - it('should stop the node', async () => { - const ipfs = await common.spawn() + beforeEach(async () => { + ipfs = await common.spawn() + }) + + afterEach(() => { + // reset the list of controlled nodes - we've already shut down the + // nodes started in this test but the references hang around and the + // next test will call `common.clean()` which will explode when it + // can't connect to the nodes started by this test. + common.controllers = [] + }) + it('should respect timeout option when stopping the node', () => { + return testTimeout(() => ipfs.api.stop({ + timeout: 1 + })) + }) + + it('should stop the node', async () => { // Should succeed because node is started await ipfs.api.swarm.peers() // Stop the node and try the call again - await ipfs.stop() + await ipfs.api.stop() // Trying to use an API that requires a started node should return an error return expect(ipfs.api.swarm.peers()).to.eventually.be.rejected() diff --git a/packages/interface-ipfs-core/src/miscellaneous/version.js b/packages/interface-ipfs-core/src/miscellaneous/version.js index 82349177be..c8128e8ff5 100644 --- a/packages/interface-ipfs-core/src/miscellaneous/version.js +++ b/packages/interface-ipfs-core/src/miscellaneous/version.js @@ -2,6 +2,7 @@ 'use strict' const { getDescribe, getIt, expect } = require('../utils/mocha') +const testTimeout = require('../utils/test-timeout') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -21,6 +22,12 @@ module.exports = (common, options) => { after(() => common.clean()) + it('should respect timeout option when getting the node version', () => { + return testTimeout(() => ipfs.version({ + timeout: 1 + })) + }) + it('should get the node version', async () => { const result = await ipfs.version() expect(result).to.have.a.property('version') diff --git a/packages/interface-ipfs-core/src/name-pubsub/cancel.js b/packages/interface-ipfs-core/src/name-pubsub/cancel.js index 28d13f851f..9e96387a5c 100644 --- a/packages/interface-ipfs-core/src/name-pubsub/cancel.js +++ b/packages/interface-ipfs-core/src/name-pubsub/cancel.js @@ -4,6 +4,7 @@ const PeerId = require('peer-id') const all = require('it-all') const { getDescribe, getIt, expect } = require('../utils/mocha') +const testTimeout = require('../utils/test-timeout') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -25,6 +26,12 @@ module.exports = (common, options) => { after(() => common.clean()) + it('should respect timeout option when cancelling an IPNS pubsub subscription', () => { + return testTimeout(() => ipfs.name.pubsub.cancel(nodeId, { + timeout: 1 + })) + }) + it('should return false when the name that is intended to cancel is not subscribed', async function () { this.timeout(60 * 1000) diff --git a/packages/interface-ipfs-core/src/name-pubsub/state.js b/packages/interface-ipfs-core/src/name-pubsub/state.js index 01da8dbaac..81f972a70d 100644 --- a/packages/interface-ipfs-core/src/name-pubsub/state.js +++ b/packages/interface-ipfs-core/src/name-pubsub/state.js @@ -2,6 +2,7 @@ 'use strict' const { getDescribe, getIt, expect } = require('../utils/mocha') +const testTimeout = require('../utils/test-timeout') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -21,6 +22,12 @@ module.exports = (common, options) => { after(() => common.clean()) + it('should respect timeout option when getting the IPNS pubsub state', () => { + return testTimeout(() => ipfs.name.pubsub.state({ + timeout: 1 + })) + }) + it('should get the current state of pubsub', async function () { this.timeout(50 * 1000) diff --git a/packages/interface-ipfs-core/src/name-pubsub/subs.js b/packages/interface-ipfs-core/src/name-pubsub/subs.js index 87edcfe765..632a508f87 100644 --- a/packages/interface-ipfs-core/src/name-pubsub/subs.js +++ b/packages/interface-ipfs-core/src/name-pubsub/subs.js @@ -3,6 +3,7 @@ const all = require('it-all') const { getDescribe, getIt, expect } = require('../utils/mocha') +const testTimeout = require('../utils/test-timeout') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -22,6 +23,12 @@ module.exports = (common, options) => { after(() => common.clean()) + it('should respect timeout option when getting IPNS pubsub subscriptions', () => { + return testTimeout(() => ipfs.name.pubsub.subs({ + timeout: 1 + })) + }) + it('should get an empty array as a result of subscriptions before any resolve', async function () { this.timeout(60 * 1000) diff --git a/packages/interface-ipfs-core/src/name/publish.js b/packages/interface-ipfs-core/src/name/publish.js index dbce387ed3..b860411cc7 100644 --- a/packages/interface-ipfs-core/src/name/publish.js +++ b/packages/interface-ipfs-core/src/name/publish.js @@ -7,6 +7,7 @@ const { fixture } = require('./utils') const { getDescribe, getIt, expect } = require('../utils/mocha') const all = require('it-all') const last = require('it-last') +const testTimeout = require('../utils/test-timeout') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -30,6 +31,13 @@ module.exports = (common, options) => { after(() => common.clean()) + it('should respect timeout option when publishing an IPNS name', () => { + return testTimeout(() => ipfs.name.publish(fixture.cid, { + allowOffline: true, + timeout: 1 + })) + }) + it('should publish an IPNS record with the default params', async function () { this.timeout(50 * 1000) diff --git a/packages/interface-ipfs-core/src/object/data.js b/packages/interface-ipfs-core/src/object/data.js index aee73b1b21..a8038c49ce 100644 --- a/packages/interface-ipfs-core/src/object/data.js +++ b/packages/interface-ipfs-core/src/object/data.js @@ -4,6 +4,8 @@ const { Buffer } = require('buffer') const { nanoid } = require('nanoid') const { getDescribe, getIt, expect } = require('../utils/mocha') +const testTimeout = require('../utils/test-timeout') +const CID = require('cids') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -25,6 +27,12 @@ module.exports = (common, options) => { after(() => common.clean()) + it('should respect timeout option when getting the data from an object', () => { + return testTimeout(() => ipfs.object.data(new CID('Qmd7qZS4T7xXtsNFdRoK1trfMs5zU94EpokQ9WFtxdPxsZ'), { + timeout: 1 + })) + }) + it('should get data by multihash', async () => { const testObj = { Data: Buffer.from(nanoid()), diff --git a/packages/interface-ipfs-core/src/object/get.js b/packages/interface-ipfs-core/src/object/get.js index 26cfffe4b1..22ae7bc6ce 100644 --- a/packages/interface-ipfs-core/src/object/get.js +++ b/packages/interface-ipfs-core/src/object/get.js @@ -10,6 +10,8 @@ const UnixFs = require('ipfs-unixfs') const randomBytes = require('iso-random-stream/src/random') const { asDAGLink } = require('./utils') const all = require('it-all') +const testTimeout = require('../utils/test-timeout') +const CID = require('cids') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -31,6 +33,12 @@ module.exports = (common, options) => { after(() => common.clean()) + it('should respect timeout option when getting an object', () => { + return testTimeout(() => ipfs.object.get(new CID('Qmd7qZS4T7xXtsNFdRoK1trfMs5zU94EpokQ9WFtxdPxsZ'), { + timeout: 1 + })) + }) + it('should get object by multihash', async () => { const obj = { Data: Buffer.from(nanoid()), diff --git a/packages/interface-ipfs-core/src/object/links.js b/packages/interface-ipfs-core/src/object/links.js index 309954dd47..ee055d66ae 100644 --- a/packages/interface-ipfs-core/src/object/links.js +++ b/packages/interface-ipfs-core/src/object/links.js @@ -8,6 +8,8 @@ const { nanoid } = require('nanoid') const { getDescribe, getIt, expect } = require('../utils/mocha') const { asDAGLink } = require('./utils') const all = require('it-all') +const testTimeout = require('../utils/test-timeout') +const CID = require('cids') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -29,6 +31,12 @@ module.exports = (common, options) => { after(() => common.clean()) + it('should respect timeout option when getting the links from an object', () => { + return testTimeout(() => ipfs.object.links(new CID('Qmd7qZS4T7xXtsNFdRoK1trfMs5zU94EpokQ9WFtxdPxsZ'), { + timeout: 1 + })) + }) + it('should get empty links by multihash', async () => { const testObj = { Data: Buffer.from(nanoid()), diff --git a/packages/interface-ipfs-core/src/object/new.js b/packages/interface-ipfs-core/src/object/new.js index 3faa3c0569..5c40b84c78 100644 --- a/packages/interface-ipfs-core/src/object/new.js +++ b/packages/interface-ipfs-core/src/object/new.js @@ -2,6 +2,7 @@ 'use strict' const { getDescribe, getIt, expect } = require('../utils/mocha') +const testTimeout = require('../utils/test-timeout') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -23,6 +24,12 @@ module.exports = (common, options) => { after(() => common.clean()) + it('should respect timeout option when creating a new object', () => { + return testTimeout(() => ipfs.object.new({ + timeout: 1 + })) + }) + it('should create a new object with no template', async () => { const cid = await ipfs.object.new() expect(cid.toBaseEncodedString()).to.equal('QmdfTbBqBPQ7VNxZEYEj14VmRuZBkqFbiwReogJgS1zR1n') diff --git a/packages/interface-ipfs-core/src/object/patch/add-link.js b/packages/interface-ipfs-core/src/object/patch/add-link.js index fb346b8347..a480bda2f2 100644 --- a/packages/interface-ipfs-core/src/object/patch/add-link.js +++ b/packages/interface-ipfs-core/src/object/patch/add-link.js @@ -6,6 +6,8 @@ const dagPB = require('ipld-dag-pb') const DAGNode = dagPB.DAGNode const { getDescribe, getIt, expect } = require('../../utils/mocha') const { asDAGLink } = require('../utils') +const CID = require('cids') +const testTimeout = require('../../utils/test-timeout') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -27,6 +29,12 @@ module.exports = (common, options) => { after(() => common.clean()) + it('should respect timeout option when adding a link to an object', () => { + return testTimeout(() => ipfs.object.patch.addLink(new CID('Qmd7qZS4T7xXtsNFdRoK1trfMs5zU94EpokQ9WFtxdPxsZ'), { name: '', size: 37, cid: new CID('Qmd7qZS4T7xXtsNFdRoK1trfMs5zU94EpokQ9WFtxdPxaZ') }, { + timeout: 1 + })) + }) + it('should add a link to an existing node', async () => { const obj = { Data: Buffer.from('patch test object'), diff --git a/packages/interface-ipfs-core/src/object/patch/append-data.js b/packages/interface-ipfs-core/src/object/patch/append-data.js index dd05c918c8..ccdb6dd98f 100644 --- a/packages/interface-ipfs-core/src/object/patch/append-data.js +++ b/packages/interface-ipfs-core/src/object/patch/append-data.js @@ -3,6 +3,8 @@ const { Buffer } = require('buffer') const { getDescribe, getIt, expect } = require('../../utils/mocha') +const testTimeout = require('../../utils/test-timeout') +const CID = require('cids') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -24,6 +26,12 @@ module.exports = (common, options) => { after(() => common.clean()) + it('should respect timeout option when appending data to an object', () => { + return testTimeout(() => ipfs.object.patch.appendData(new CID('Qmd7qZS4T7xXtsNFdRoK1trfMs5zU94EpokQ9WFtxdPxsZ'), Buffer.from('derp'), { + timeout: 1 + })) + }) + it('should append data to an existing node', async () => { const obj = { Data: Buffer.from('patch test object'), diff --git a/packages/interface-ipfs-core/src/object/patch/rm-link.js b/packages/interface-ipfs-core/src/object/patch/rm-link.js index 22a3a8a2cf..2269266062 100644 --- a/packages/interface-ipfs-core/src/object/patch/rm-link.js +++ b/packages/interface-ipfs-core/src/object/patch/rm-link.js @@ -4,6 +4,8 @@ const { Buffer } = require('buffer') const { getDescribe, getIt, expect } = require('../../utils/mocha') const { asDAGLink } = require('../utils') +const testTimeout = require('../../utils/test-timeout') +const CID = require('cids') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -25,6 +27,12 @@ module.exports = (common, options) => { after(() => common.clean()) + it('should respect timeout option when removing a link from an object', () => { + return testTimeout(() => ipfs.object.patch.rmLink(new CID('Qmd7qZS4T7xXtsNFdRoK1trfMs5zU94EpokQ9WFtxdPxsZ'), { name: 'link' }, { + timeout: 1 + })) + }) + it('should remove a link from an existing node', async () => { const obj1 = { Data: Buffer.from('patch test object 1'), diff --git a/packages/interface-ipfs-core/src/object/patch/set-data.js b/packages/interface-ipfs-core/src/object/patch/set-data.js index 6d806fa0ed..0002bf0363 100644 --- a/packages/interface-ipfs-core/src/object/patch/set-data.js +++ b/packages/interface-ipfs-core/src/object/patch/set-data.js @@ -3,6 +3,8 @@ const { Buffer } = require('buffer') const { getDescribe, getIt, expect } = require('../../utils/mocha') +const testTimeout = require('../../utils/test-timeout') +const CID = require('cids') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -24,6 +26,12 @@ module.exports = (common, options) => { after(() => common.clean()) + it('should respect timeout option when setting the data of an object', () => { + return testTimeout(() => ipfs.object.patch.setData(new CID('Qmd7qZS4T7xXtsNFdRoK1trfMs5zU94EpokQ9WFtxdPxsZ'), Buffer.from('derp'), { + timeout: 1 + })) + }) + it('should set data for an existing node', async () => { const obj = { Data: Buffer.from('patch test object'), diff --git a/packages/interface-ipfs-core/src/object/put.js b/packages/interface-ipfs-core/src/object/put.js index 912c108f13..8c84afc8d4 100644 --- a/packages/interface-ipfs-core/src/object/put.js +++ b/packages/interface-ipfs-core/src/object/put.js @@ -7,6 +7,7 @@ const DAGNode = dagPB.DAGNode const { nanoid } = require('nanoid') const { getDescribe, getIt, expect } = require('../utils/mocha') const { asDAGLink } = require('./utils') +const testTimeout = require('../utils/test-timeout') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -28,6 +29,12 @@ module.exports = (common, options) => { after(() => common.clean()) + it('should respect timeout option when putting an object', () => { + return testTimeout(() => ipfs.object.put({ Data: Buffer.from('derp') }, { + timeout: 1 + })) + }) + it('should put an object', async () => { const obj = { Data: Buffer.from(nanoid()), diff --git a/packages/interface-ipfs-core/src/object/stat.js b/packages/interface-ipfs-core/src/object/stat.js index 9192971247..c7d18a87e1 100644 --- a/packages/interface-ipfs-core/src/object/stat.js +++ b/packages/interface-ipfs-core/src/object/stat.js @@ -6,6 +6,8 @@ const dagPB = require('ipld-dag-pb') const DAGNode = dagPB.DAGNode const { getDescribe, getIt, expect } = require('../utils/mocha') const { asDAGLink } = require('./utils') +const testTimeout = require('../utils/test-timeout') +const CID = require('cids') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -27,6 +29,12 @@ module.exports = (common, options) => { after(() => common.clean()) + it('should respect timeout option when statting an object', () => { + return testTimeout(() => ipfs.object.stat(new CID('Qmd7qZS4T7xXtsNFdRoK1trfMs5zU94EpokQ9WFtxdPxsZ'), { + timeout: 1 + })) + }) + it('should get stats by multihash', async () => { const testObj = { Data: Buffer.from('get test object'), @@ -46,31 +54,6 @@ module.exports = (common, options) => { expect(expected).to.deep.equal(stats) }) - it('should respect timeout option', async () => { - const testObj = { - Data: Buffer.from('get test object'), - Links: [] - } - - await ipfs.object.put(testObj) - - const timeout = 2000 - const startTime = new Date() - const badCid = 'QmNggDXca24S6cMPEYHZjeuc4QRmofkRrAEqVL3MzzzzzZ' - - const err = await expect(ipfs.object.stat(badCid, { timeout })).to.be.rejected() - const timeForRequest = (new Date() - startTime) - - if (err.code) { - expect(err.code).to.equal('ERR_TIMEOUT') - } else { - expect(err.message).to.equal('failed to get block for QmNggDXca24S6cMPEYHZjeuc4QRmofkRrAEqVL3MzzzzzZ: context deadline exceeded') - } - - expect(timeForRequest).to.not.lessThan(timeout - 1000) - expect(timeForRequest).to.not.greaterThan(timeout + 1000) - }) - it('should get stats for object with links by multihash', async () => { const node1a = new DAGNode(Buffer.from('Some data 1')) const node2 = new DAGNode(Buffer.from('Some data 2')) diff --git a/packages/interface-ipfs-core/src/pin/add.js b/packages/interface-ipfs-core/src/pin/add.js index 5e4cb2f3db..df8a4a6fb2 100644 --- a/packages/interface-ipfs-core/src/pin/add.js +++ b/packages/interface-ipfs-core/src/pin/add.js @@ -4,6 +4,8 @@ const { fixtures } = require('./utils') const { getDescribe, getIt, expect } = require('../utils/mocha') const all = require('it-all') +const testTimeout = require('../utils/test-timeout') +const CID = require('cids') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -27,6 +29,12 @@ module.exports = (common, options) => { after(() => common.clean()) + it('should respect timeout option when pinning a block', () => { + return testTimeout(() => ipfs.pin.add(new CID('Qmd7qZS4T7xXtsNFdRoK1trfMs5zU94EpokQ9WFtxdPxsZ'), { + timeout: 1 + })) + }) + it('should add a pin', async () => { const pinset = await ipfs.pin.add(fixtures.files[0].cid, { recursive: false }) expect(pinset.map(p => p.cid.toString())).to.include(fixtures.files[0].cid) diff --git a/packages/interface-ipfs-core/src/pin/ls.js b/packages/interface-ipfs-core/src/pin/ls.js index ffdfe7986b..5aa9048f97 100644 --- a/packages/interface-ipfs-core/src/pin/ls.js +++ b/packages/interface-ipfs-core/src/pin/ls.js @@ -4,6 +4,7 @@ const { fixtures } = require('./utils') const { getDescribe, getIt, expect } = require('../utils/mocha') const all = require('it-all') +const testTimeout = require('../utils/test-timeout') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -35,6 +36,12 @@ module.exports = (common, options) => { after(() => common.clean()) + it('should respect timeout option when listing pins', () => { + return testTimeout(() => ipfs.pin.ls({ + timeout: 1 + })) + }) + // 1st, because ipfs.add pins automatically it('should list all recursive pins', async () => { const pinset = (await all(ipfs.pin.ls({ type: 'recursive' }))) diff --git a/packages/interface-ipfs-core/src/pin/rm.js b/packages/interface-ipfs-core/src/pin/rm.js index 7565381687..e89e70f697 100644 --- a/packages/interface-ipfs-core/src/pin/rm.js +++ b/packages/interface-ipfs-core/src/pin/rm.js @@ -4,6 +4,7 @@ const { fixtures } = require('./utils') const { getDescribe, getIt, expect } = require('../utils/mocha') const all = require('it-all') +const testTimeout = require('../utils/test-timeout') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -18,7 +19,7 @@ module.exports = (common, options) => { this.timeout(50 * 1000) let ipfs - before(async () => { + beforeEach(async () => { ipfs = (await common.spawn()).api await all(ipfs.add(fixtures.files[0].data, { pin: false })) await ipfs.pin.add(fixtures.files[0].cid, { recursive: true }) @@ -28,6 +29,13 @@ module.exports = (common, options) => { after(() => common.clean()) + it('should respect timeout option when unpinning a block', () => { + return testTimeout(() => ipfs.pin.rm(fixtures.files[0].cid, { + recursive: true, + timeout: 1 + })) + }) + it('should remove a recursive pin', async () => { const removedPinset = await ipfs.pin.rm(fixtures.files[0].cid, { recursive: true }) expect(removedPinset.map(p => p.cid.toString())).to.deep.equal([fixtures.files[0].cid]) diff --git a/packages/interface-ipfs-core/src/ping/ping.js b/packages/interface-ipfs-core/src/ping/ping.js index 22c0e09ea3..4a8879ef3f 100644 --- a/packages/interface-ipfs-core/src/ping/ping.js +++ b/packages/interface-ipfs-core/src/ping/ping.js @@ -4,7 +4,9 @@ const { getDescribe, getIt, expect } = require('../utils/mocha') const { expectIsPingResponse, isPong } = require('./utils') const all = require('it-all') +const drain = require('it-drain') const { isWebWorker } = require('ipfs-utils/src/env') +const testTimeout = require('../utils/test-timeout') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -30,6 +32,12 @@ module.exports = (common, options) => { after(() => common.clean()) + it('should respect timeout option when pinging a peer', () => { + return testTimeout(() => drain(ipfsA.ping(ipfsB.peerId.id, { + timeout: 1 + }))) + }) + it('should send the specified number of packets', async () => { const count = 3 const responses = await all(ipfsA.ping(ipfsB.peerId.id, { count })) diff --git a/packages/interface-ipfs-core/src/pubsub/ls.js b/packages/interface-ipfs-core/src/pubsub/ls.js index 85449bf02c..fbc918b32e 100644 --- a/packages/interface-ipfs-core/src/pubsub/ls.js +++ b/packages/interface-ipfs-core/src/pubsub/ls.js @@ -4,6 +4,7 @@ const { getTopic } = require('./utils') const { getDescribe, getIt, expect } = require('../utils/mocha') const delay = require('delay') +const testTimeout = require('../utils/test-timeout') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -33,6 +34,12 @@ module.exports = (common, options) => { after(() => common.clean()) + it('should respect timeout option when listing pubsub subscriptions', () => { + return testTimeout(() => ipfs.pubsub.ls({ + timeout: 1 + })) + }) + it('should return an empty list when no topics are subscribed', async () => { const topics = await ipfs.pubsub.ls() expect(topics.length).to.equal(0) diff --git a/packages/interface-ipfs-core/src/pubsub/peers.js b/packages/interface-ipfs-core/src/pubsub/peers.js index d417b53ee5..3b209c43c1 100644 --- a/packages/interface-ipfs-core/src/pubsub/peers.js +++ b/packages/interface-ipfs-core/src/pubsub/peers.js @@ -5,6 +5,7 @@ const { waitForPeers, getTopic } = require('./utils') const { getDescribe, getIt, expect } = require('../utils/mocha') const delay = require('delay') const { isWebWorker } = require('ipfs-utils/src/env') +const testTimeout = require('../utils/test-timeout') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -22,6 +23,7 @@ module.exports = (common, options) => { let ipfs2 let ipfs3 let subscribedTopics = [] + before(async () => { ipfs1 = (await common.spawn()).api // webworkers are not dialable because webrtc is not available @@ -50,6 +52,12 @@ module.exports = (common, options) => { after(() => common.clean()) + it('should respect timeout option when listing pubsub peers', () => { + return testTimeout(() => ipfs1.pubsub.peers(getTopic(), { + timeout: 1 + })) + }) + it('should not error when not subscribed to a topic', async () => { const topic = getTopic() const peers = await ipfs1.pubsub.peers(topic) diff --git a/packages/interface-ipfs-core/src/pubsub/publish.js b/packages/interface-ipfs-core/src/pubsub/publish.js index d4e0912959..f536f0c6bd 100644 --- a/packages/interface-ipfs-core/src/pubsub/publish.js +++ b/packages/interface-ipfs-core/src/pubsub/publish.js @@ -5,6 +5,7 @@ const { Buffer } = require('buffer') const { nanoid } = require('nanoid') const { getTopic } = require('./utils') const { getDescribe, getIt } = require('../utils/mocha') +const testTimeout = require('../utils/test-timeout') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -26,6 +27,12 @@ module.exports = (common, options) => { after(() => common.clean()) + it('should respect timeout option when publishing a pubsub message', () => { + return testTimeout(() => ipfs.pubsub.publish(getTopic(), 'derp', { + timeout: 1 + })) + }) + it('should publish message from string', () => { const topic = getTopic() return ipfs.pubsub.publish(topic, 'hello friend') diff --git a/packages/interface-ipfs-core/src/refs-local.js b/packages/interface-ipfs-core/src/refs-local.js index 9c41c7bcb1..d20851dee8 100644 --- a/packages/interface-ipfs-core/src/refs-local.js +++ b/packages/interface-ipfs-core/src/refs-local.js @@ -5,6 +5,8 @@ const { fixtures } = require('./utils') const { getDescribe, getIt, expect } = require('./utils/mocha') const all = require('it-all') const importer = require('ipfs-unixfs-importer') +const drain = require('it-drain') +const testTimeout = require('./utils/test-timeout') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -26,6 +28,12 @@ module.exports = (common, options) => { after(() => common.clean()) + it('should respect timeout option when listing local refs', () => { + return testTimeout(() => drain(ipfs.refs.local({ + timeout: 1 + }))) + }) + it('should get local refs', async function () { const content = (name) => ({ path: `test-folder/${name}`, diff --git a/packages/interface-ipfs-core/src/refs.js b/packages/interface-ipfs-core/src/refs.js index bd309872f2..8589ab435f 100644 --- a/packages/interface-ipfs-core/src/refs.js +++ b/packages/interface-ipfs-core/src/refs.js @@ -6,6 +6,8 @@ const { getDescribe, getIt, expect } = require('./utils/mocha') const loadFixture = require('aegir/fixtures') const CID = require('cids') const all = require('it-all') +const drain = require('it-drain') +const testTimeout = require('./utils/test-timeout') const dagPB = require('ipld-dag-pb') const DAGNode = dagPB.DAGNode @@ -70,6 +72,12 @@ module.exports = (common, options) => { }) } + it('should respect timeout option when listing refs', () => { + return testTimeout(() => drain(ipfs.refs('/ipfs/QmPDqvcuA4AkhBLBuh2y49yhUB98rCnxPxa3eVNC1kAbS1/foo/bar/baz.txt', { + timeout: 1 + }))) + }) + it('should get refs with cbor links', async function () { this.timeout(20 * 1000) diff --git a/packages/interface-ipfs-core/src/repo/gc.js b/packages/interface-ipfs-core/src/repo/gc.js index b6b8d9aabb..0c592379d2 100644 --- a/packages/interface-ipfs-core/src/repo/gc.js +++ b/packages/interface-ipfs-core/src/repo/gc.js @@ -5,6 +5,7 @@ const { Buffer } = require('buffer') const { getDescribe, getIt, expect } = require('../utils/mocha') const { DAGNode } = require('ipld-dag-pb') const all = require('it-all') +const testTimeout = require('../utils/test-timeout') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -24,6 +25,12 @@ module.exports = (common, options) => { after(() => common.clean()) + it('should respect timeout option when garbage collecting', () => { + return testTimeout(() => ipfs.repo.gc({ + timeout: 1 + })) + }) + it('should run garbage collection', async () => { const res = await all(ipfs.add(Buffer.from('apples'))) diff --git a/packages/interface-ipfs-core/src/repo/stat.js b/packages/interface-ipfs-core/src/repo/stat.js index ae9a002633..b766c7b219 100644 --- a/packages/interface-ipfs-core/src/repo/stat.js +++ b/packages/interface-ipfs-core/src/repo/stat.js @@ -3,6 +3,7 @@ const { expectIsRepo } = require('../stats/utils') const { getDescribe, getIt } = require('../utils/mocha') +const testTimeout = require('../utils/test-timeout') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -22,6 +23,12 @@ module.exports = (common, options) => { after(() => common.clean()) + it('should respect timeout option when getting repo stats', () => { + return testTimeout(() => ipfs.repo.stat({ + timeout: 1 + })) + }) + it('should get repo stats', async () => { const res = await ipfs.repo.stat() expectIsRepo(null, res) diff --git a/packages/interface-ipfs-core/src/repo/version.js b/packages/interface-ipfs-core/src/repo/version.js index 3010424c82..d431e434ee 100644 --- a/packages/interface-ipfs-core/src/repo/version.js +++ b/packages/interface-ipfs-core/src/repo/version.js @@ -2,6 +2,7 @@ 'use strict' const { getDescribe, getIt, expect } = require('../utils/mocha') +const testTimeout = require('../utils/test-timeout') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -21,6 +22,12 @@ module.exports = (common, options) => { after(() => common.clean()) + it('should respect timeout option when getting the repo version', () => { + return testTimeout(() => ipfs.repo.version({ + timeout: 1 + })) + }) + it('should get the repo version', async () => { const version = await ipfs.repo.version() expect(version).to.exist() diff --git a/packages/interface-ipfs-core/src/stats/bitswap.js b/packages/interface-ipfs-core/src/stats/bitswap.js index 3189cf225a..ad1da81f56 100644 --- a/packages/interface-ipfs-core/src/stats/bitswap.js +++ b/packages/interface-ipfs-core/src/stats/bitswap.js @@ -3,6 +3,7 @@ const { getDescribe, getIt } = require('../utils/mocha') const { expectIsBitswap } = require('./utils') +const testTimeout = require('../utils/test-timeout') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -22,6 +23,12 @@ module.exports = (common, options) => { after(() => common.clean()) + it('should respect timeout option when getting bitswap stats', () => { + return testTimeout(() => ipfs.stats.bitswap({ + timeout: 1 + })) + }) + it('should get bitswap stats', async () => { const res = await ipfs.stats.bitswap() expectIsBitswap(null, res) diff --git a/packages/interface-ipfs-core/src/stats/bw.js b/packages/interface-ipfs-core/src/stats/bw.js index 740fd7af96..d3e98d1d67 100644 --- a/packages/interface-ipfs-core/src/stats/bw.js +++ b/packages/interface-ipfs-core/src/stats/bw.js @@ -4,6 +4,7 @@ const { expectIsBandwidth } = require('./utils') const { getDescribe, getIt } = require('../utils/mocha') const last = require('it-last') +const testTimeout = require('../utils/test-timeout') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -23,6 +24,12 @@ module.exports = (common, options) => { after(() => common.clean()) + it('should respect timeout option when getting bandwith stats', () => { + return testTimeout(() => ipfs.stats.bw({ + timeout: 1 + })) + }) + it('should get bandwidth stats ', async () => { const res = await last(ipfs.stats.bw()) expectIsBandwidth(null, res) diff --git a/packages/interface-ipfs-core/src/stats/repo.js b/packages/interface-ipfs-core/src/stats/repo.js index d6972d5399..cc7d40e802 100644 --- a/packages/interface-ipfs-core/src/stats/repo.js +++ b/packages/interface-ipfs-core/src/stats/repo.js @@ -3,6 +3,7 @@ const { expectIsRepo } = require('./utils') const { getDescribe, getIt } = require('../utils/mocha') +const testTimeout = require('../utils/test-timeout') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -22,6 +23,12 @@ module.exports = (common, options) => { after(() => common.clean()) + it('should respect timeout option when getting repo stats', () => { + return testTimeout(() => ipfs.stats.repo({ + timeout: 1 + })) + }) + it('should get repo stats', async () => { const res = await ipfs.stats.repo() expectIsRepo(null, res) diff --git a/packages/interface-ipfs-core/src/swarm/addrs.js b/packages/interface-ipfs-core/src/swarm/addrs.js index 2f13b214b6..72446e27b0 100644 --- a/packages/interface-ipfs-core/src/swarm/addrs.js +++ b/packages/interface-ipfs-core/src/swarm/addrs.js @@ -5,6 +5,7 @@ const CID = require('cids') const Multiaddr = require('multiaddr') const { getDescribe, getIt, expect } = require('../utils/mocha') const { isWebWorker } = require('ipfs-utils/src/env') +const testTimeout = require('../utils/test-timeout') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -30,6 +31,12 @@ module.exports = (common, options) => { after(() => common.clean()) + it('should respect timeout option when listing swarm addresses', () => { + return testTimeout(() => ipfsA.swarm.addrs({ + timeout: 1 + })) + }) + it('should get a list of node addresses', async () => { const peerInfos = await ipfsA.swarm.addrs() expect(peerInfos).to.not.be.empty() diff --git a/packages/interface-ipfs-core/src/swarm/connect.js b/packages/interface-ipfs-core/src/swarm/connect.js index ac341ddc32..bc0219b8af 100644 --- a/packages/interface-ipfs-core/src/swarm/connect.js +++ b/packages/interface-ipfs-core/src/swarm/connect.js @@ -3,6 +3,7 @@ const { getDescribe, getIt, expect } = require('../utils/mocha') const { isWebWorker } = require('ipfs-utils/src/env') +const testTimeout = require('../utils/test-timeout') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -37,5 +38,11 @@ module.exports = (common, options) => { peers = await ipfsA.swarm.peers() expect(peers).to.have.length.above(0) }) + + it('should respect timeout option when connecting to a remote peer', () => { + return testTimeout(() => ipfsA.swarm.connect(ipfsB.peerId.addresses[0], { + timeout: 1 + })) + }) }) } diff --git a/packages/interface-ipfs-core/src/swarm/disconnect.js b/packages/interface-ipfs-core/src/swarm/disconnect.js index 3d0667d73b..606d4be1d7 100644 --- a/packages/interface-ipfs-core/src/swarm/disconnect.js +++ b/packages/interface-ipfs-core/src/swarm/disconnect.js @@ -3,6 +3,7 @@ const { getDescribe, getIt, expect } = require('../utils/mocha') const { isWebWorker } = require('ipfs-utils/src/env') +const testTimeout = require('../utils/test-timeout') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -23,6 +24,9 @@ module.exports = (common, options) => { ipfsA = (await common.spawn()).api // webworkers are not dialable because webrtc is not available ipfsB = (await common.spawn({ type: isWebWorker ? 'go' : undefined })).api + }) + + beforeEach(async () => { await ipfsA.swarm.connect(ipfsB.peerId.addresses[0]) }) @@ -39,5 +43,11 @@ module.exports = (common, options) => { peers = await ipfsA.swarm.peers() expect(peers).to.have.length(0) }) + + it('should respect timeout option when disconnecting from a remote peer', () => { + return testTimeout(() => ipfsA.swarm.disconnect(ipfsB.peerId.addresses[0], { + timeout: 1 + })) + }) }) } diff --git a/packages/interface-ipfs-core/src/swarm/local-addrs.js b/packages/interface-ipfs-core/src/swarm/local-addrs.js index 45da62461d..434bcb213e 100644 --- a/packages/interface-ipfs-core/src/swarm/local-addrs.js +++ b/packages/interface-ipfs-core/src/swarm/local-addrs.js @@ -3,6 +3,7 @@ const { getDescribe, getIt, expect } = require('../utils/mocha') const { isWebWorker } = require('ipfs-utils/src/env') +const testTimeout = require('../utils/test-timeout') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -24,6 +25,12 @@ module.exports = (common, options) => { after(() => common.clean()) + it('should respect timeout option when listing local addresses', () => { + return testTimeout(() => ipfs.swarm.localAddrs({ + timeout: 1 + })) + }) + it('should list local addresses the node is listening on', async () => { const multiaddrs = await ipfs.swarm.localAddrs() diff --git a/packages/interface-ipfs-core/src/swarm/peers.js b/packages/interface-ipfs-core/src/swarm/peers.js index b531726d84..12701a8cdd 100644 --- a/packages/interface-ipfs-core/src/swarm/peers.js +++ b/packages/interface-ipfs-core/src/swarm/peers.js @@ -6,6 +6,7 @@ const CID = require('cids') const delay = require('delay') const { isBrowser, isWebWorker } = require('ipfs-utils/src/env') const { getDescribe, getIt, expect } = require('../utils/mocha') +const testTimeout = require('../utils/test-timeout') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -33,6 +34,12 @@ module.exports = (common, options) => { after(() => common.clean()) + it('should respect timeout option when listing swarm peers', () => { + return testTimeout(() => ipfsA.swarm.peers({ + timeout: 1 + })) + }) + it('should list peers this node is connected to', async () => { const peers = await ipfsA.swarm.peers() expect(peers).to.have.length.above(0) diff --git a/packages/interface-ipfs-core/src/utils/test-timeout.js b/packages/interface-ipfs-core/src/utils/test-timeout.js new file mode 100644 index 0000000000..b95f7bb001 --- /dev/null +++ b/packages/interface-ipfs-core/src/utils/test-timeout.js @@ -0,0 +1,40 @@ +'use strict' + +const drain = require('it-drain') + +module.exports = (fn) => { + return new Promise((resolve, reject) => { + // some operations are either synchronous so cannot time out, or complete during + // processing of the microtask queue so the timeout timer doesn't fire. If this + // is the case this is more of a best-effort test.. + setTimeout(() => { + const start = Date.now() + let res = fn() + + if (res[Symbol.asyncIterator]) { + res = drain(res) + } + + res.then((result) => { + const timeTaken = Date.now() - start + + if (timeTaken < 100) { + // the implementation may be too fast to measure a time out reliably on node + // due to the event loop being blocked. if it took longer than 100ms though, + // it almost certainly did not time out + return resolve() + } + + reject(new Error(`API call did not time out after ${timeTaken}ms, got ${JSON.stringify(result, null, 2)}`)) + }, (err) => { + if (err.message.includes('timed out')) { + return resolve() + } + + const timeTaken = Date.now() - start + + reject(new Error(`Expected error to include 'timed out' after ${timeTaken}ms, got ${err.stack}`)) + }) + }, 10) + }) +} diff --git a/packages/ipfs-core-utils/package.json b/packages/ipfs-core-utils/package.json index 2f6f9c30b1..1d108ce0a7 100644 --- a/packages/ipfs-core-utils/package.json +++ b/packages/ipfs-core-utils/package.json @@ -33,7 +33,7 @@ "ipfs-utils": "^2.2.2" }, "devDependencies": { - "aegir": "^21.10.1", + "aegir": "^22.0.0", "chai": "^4.2.0", "chai-as-promised": "^7.1.1", "delay": "^4.3.0", diff --git a/packages/ipfs-http-client/README.md b/packages/ipfs-http-client/README.md index 8daf6dc3ff..b73a6c1c59 100644 --- a/packages/ipfs-http-client/README.md +++ b/packages/ipfs-http-client/README.md @@ -94,8 +94,6 @@ Both the Current and Active LTS versions of Node.js are supported. Please see [n All core API methods take _additional_ `options` specific to the HTTP API: * `headers` - An object or [Headers](https://developer.mozilla.org/en-US/docs/Web/API/Headers) instance that can be used to set custom HTTP headers. Note that this option can also be [configured globally](#custom-headers) via the constructor options. -* `signal` - An [`AbortSignal`](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal) that can be used to abort the request on demand. -* `timeout` - A number or string specifying a timeout for the request. If the timeout is reached before data is received a [`TimeoutError`](https://github.com/sindresorhus/ky/blob/2f37c3f999efb36db9108893b8b3d4b3a7f5ec45/index.js#L127-L132) is thrown. If a number is specified it is interpreted as milliseconds, if a string is passed, it is intepreted according to [`parse-duration`](https://www.npmjs.com/package/parse-duration). Note that this option can also be [configured globally](#global-timeouts) via the constructor options. * `searchParams` - An object or [`URLSearchParams`](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams) instance that can be used to add additional query parameters to the query string sent with each request. ### Instance Utils diff --git a/packages/ipfs-http-client/package.json b/packages/ipfs-http-client/package.json index 3569169ecd..243dcd4e31 100644 --- a/packages/ipfs-http-client/package.json +++ b/packages/ipfs-http-client/package.json @@ -40,6 +40,7 @@ }, "dependencies": { "abort-controller": "^3.0.0", + "any-signal": "^1.1.0", "bignumber.js": "^9.0.0", "buffer": "^5.6.0", "cids": "^0.8.0", @@ -67,11 +68,11 @@ "stream-to-it": "^0.2.0" }, "devDependencies": { - "aegir": "^21.10.1", + "aegir": "^22.0.0", "cross-env": "^7.0.0", "go-ipfs-dep": "0.4.23-3", "interface-ipfs-core": "^0.134.3", - "ipfsd-ctl": "^4.0.1", + "ipfsd-ctl": "^4.1.1", "it-all": "^1.0.1", "it-concat": "^1.0.0", "it-pipe": "^1.1.0", diff --git a/packages/ipfs-http-client/src/add.js b/packages/ipfs-http-client/src/add.js index 097bdefeeb..d399abb4a1 100644 --- a/packages/ipfs-http-client/src/add.js +++ b/packages/ipfs-http-client/src/add.js @@ -5,11 +5,17 @@ const toCamel = require('./lib/object-to-camel') const configure = require('./lib/configure') const multipartRequest = require('./lib/multipart-request') const toUrlSearchParams = require('./lib/to-url-search-params') +const anySignal = require('any-signal') +const AbortController = require('abort-controller') module.exports = configure((api) => { return async function * add (input, options = {}) { const progressFn = options.progress + // allow aborting requests on body errors + const controller = new AbortController() + const signal = anySignal([controller.signal, options.signal]) + const res = await api.post('add', { searchParams: toUrlSearchParams({ 'stream-channels': true, @@ -17,9 +23,9 @@ module.exports = configure((api) => { progress: Boolean(progressFn) }), timeout: options.timeout, - signal: options.signal, + signal, ...( - await multipartRequest(input, options.headers) + await multipartRequest(input, controller, options.headers) ) }) diff --git a/packages/ipfs-http-client/src/bitswap/wantlist.js b/packages/ipfs-http-client/src/bitswap/wantlist.js index d63d03ced4..d8357e7ac0 100644 --- a/packages/ipfs-http-client/src/bitswap/wantlist.js +++ b/packages/ipfs-http-client/src/bitswap/wantlist.js @@ -6,6 +6,11 @@ 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() } diff --git a/packages/ipfs-http-client/src/block/put.js b/packages/ipfs-http-client/src/block/put.js index 4e152f92a0..09888a815e 100644 --- a/packages/ipfs-http-client/src/block/put.js +++ b/packages/ipfs-http-client/src/block/put.js @@ -6,6 +6,8 @@ const multihash = require('multihashes') const multipartRequest = require('../lib/multipart-request') const configure = require('../lib/configure') const toUrlSearchParams = require('../lib/to-url-search-params') +const anySignal = require('any-signal') +const AbortController = require('abort-controller') module.exports = configure(api => { async function put (data, options = {}) { @@ -32,14 +34,18 @@ module.exports = configure(api => { delete options.cid } + // allow aborting requests on body errors + const controller = new AbortController() + const signal = anySignal([controller.signal, options.signal]) + let res try { const response = await api.post('block/put', { timeout: options.timeout, - signal: options.signal, + signal: signal, searchParams: toUrlSearchParams(options), ...( - await multipartRequest(data, options.headers) + await multipartRequest(data, controller, options.headers) ) }) res = await response.json() diff --git a/packages/ipfs-http-client/src/config/replace.js b/packages/ipfs-http-client/src/config/replace.js index fd688e139c..57fce31db6 100644 --- a/packages/ipfs-http-client/src/config/replace.js +++ b/packages/ipfs-http-client/src/config/replace.js @@ -4,15 +4,21 @@ const { Buffer } = require('buffer') const multipartRequest = require('../lib/multipart-request') const configure = require('../lib/configure') const toUrlSearchParams = require('../lib/to-url-search-params') +const anySignal = require('any-signal') +const AbortController = require('abort-controller') module.exports = configure(api => { return async (config, options = {}) => { + // allow aborting requests on body errors + const controller = new AbortController() + const signal = anySignal([controller.signal, options.signal]) + const res = await api.post('config/replace', { timeout: options.timeout, - signal: options.signal, + signal, searchParams: toUrlSearchParams(options), ...( - await multipartRequest(Buffer.from(JSON.stringify(config)), options.headers) + await multipartRequest(Buffer.from(JSON.stringify(config)), controller, options.headers) ) }) diff --git a/packages/ipfs-http-client/src/dag/put.js b/packages/ipfs-http-client/src/dag/put.js index 01ebdc31c9..a7d9165dfb 100644 --- a/packages/ipfs-http-client/src/dag/put.js +++ b/packages/ipfs-http-client/src/dag/put.js @@ -6,6 +6,8 @@ const multihash = require('multihashes') const configure = require('../lib/configure') const multipartRequest = require('../lib/multipart-request') const toUrlSearchParams = require('../lib/to-url-search-params') +const anySignal = require('any-signal') +const AbortController = require('abort-controller') module.exports = configure(api => { return async (dagNode, options = {}) => { @@ -43,12 +45,16 @@ module.exports = configure(api => { serialized = dagNode } + // allow aborting requests on body errors + const controller = new AbortController() + const signal = anySignal([controller.signal, options.signal]) + const res = await api.post('dag/put', { timeout: options.timeout, - signal: options.signal, + signal, searchParams: toUrlSearchParams(options), ...( - await multipartRequest(serialized, options.headers) + await multipartRequest(serialized, controller, options.headers) ) }) const data = await res.json() diff --git a/packages/ipfs-http-client/src/dag/resolve.js b/packages/ipfs-http-client/src/dag/resolve.js index 23b81adeef..acced6a42c 100644 --- a/packages/ipfs-http-client/src/dag/resolve.js +++ b/packages/ipfs-http-client/src/dag/resolve.js @@ -6,7 +6,7 @@ const toUrlSearchParams = require('../lib/to-url-search-params') module.exports = configure(api => { return async (cid, path, options = {}) => { - if (typeof path === 'object') { + if (path && typeof path === 'object') { options = path path = null } diff --git a/packages/ipfs-http-client/src/files/write.js b/packages/ipfs-http-client/src/files/write.js index 6f30618dd7..c3e72c9bb3 100644 --- a/packages/ipfs-http-client/src/files/write.js +++ b/packages/ipfs-http-client/src/files/write.js @@ -5,12 +5,18 @@ const mtimeToObject = require('../lib/mtime-to-object') const configure = require('../lib/configure') const multipartRequest = require('../lib/multipart-request') const toUrlSearchParams = require('../lib/to-url-search-params') +const anySignal = require('any-signal') +const AbortController = require('abort-controller') module.exports = configure(api => { return async (path, input, options = {}) => { + // allow aborting requests on body errors + const controller = new AbortController() + const signal = anySignal([controller.signal, options.signal]) + const res = await api.post('files/write', { timeout: options.timeout, - signal: options.signal, + signal, searchParams: toUrlSearchParams({ arg: path, streamChannels: true, @@ -23,7 +29,7 @@ module.exports = configure(api => { path: 'arg', mode: modeToString(options.mode), mtime: mtimeToObject(options.mtime) - }, options.headers) + }, controller, options.headers) ) }) diff --git a/packages/ipfs-http-client/src/lib/multipart-request.js b/packages/ipfs-http-client/src/lib/multipart-request.js index 111a873fef..9ae1cbdf57 100644 --- a/packages/ipfs-http-client/src/lib/multipart-request.js +++ b/packages/ipfs-http-client/src/lib/multipart-request.js @@ -7,7 +7,7 @@ const modeToString = require('../lib/mode-to-string') const mtimeToObject = require('../lib/mtime-to-object') const merge = require('merge-options').bind({ ignoreUndefined: true }) -async function multipartRequest (source, headers = {}, boundary = `-----------------------------${nanoid()}`) { +async function multipartRequest (source, abortController, headers = {}, boundary = `-----------------------------${nanoid()}`) { async function * streamFiles (source) { try { let index = 0 @@ -50,6 +50,9 @@ async function multipartRequest (source, headers = {}, boundary = `------------- index++ } + } catch (err) { + // workaround for https://github.com/node-fetch/node-fetch/issues/753 + abortController.abort(err) } finally { yield `\r\n--${boundary}--\r\n` } diff --git a/packages/ipfs-http-client/src/object/patch/add-link.js b/packages/ipfs-http-client/src/object/patch/add-link.js index a60248ab2b..f9f6eb8bf2 100644 --- a/packages/ipfs-http-client/src/object/patch/add-link.js +++ b/packages/ipfs-http-client/src/object/patch/add-link.js @@ -13,7 +13,7 @@ module.exports = configure(api => { searchParams: toUrlSearchParams({ arg: [ `${Buffer.isBuffer(cid) ? new CID(cid) : cid}`, - dLink.Name || dLink.name || null, + dLink.Name || dLink.name || '', (dLink.Hash || dLink.cid || '').toString() || null ], ...options diff --git a/packages/ipfs-http-client/src/object/patch/append-data.js b/packages/ipfs-http-client/src/object/patch/append-data.js index e41e436d97..0ef14f9a54 100644 --- a/packages/ipfs-http-client/src/object/patch/append-data.js +++ b/packages/ipfs-http-client/src/object/patch/append-data.js @@ -5,18 +5,24 @@ const CID = require('cids') const multipartRequest = require('../../lib/multipart-request') const configure = require('../../lib/configure') const toUrlSearchParams = require('../../lib/to-url-search-params') +const anySignal = require('any-signal') +const AbortController = require('abort-controller') module.exports = configure(api => { return async (cid, data, options = {}) => { + // allow aborting requests on body errors + const controller = new AbortController() + const signal = anySignal([controller.signal, options.signal]) + const res = await api.post('object/patch/append-data', { timeout: options.timeout, - signal: options.signal, + signal, searchParams: toUrlSearchParams({ arg: `${Buffer.isBuffer(cid) ? new CID(cid) : cid}`, ...options }), ...( - await multipartRequest(data, options.headers) + await multipartRequest(data, controller, options.headers) ) }) diff --git a/packages/ipfs-http-client/src/object/patch/set-data.js b/packages/ipfs-http-client/src/object/patch/set-data.js index 6764de3c6c..9609dff3a2 100644 --- a/packages/ipfs-http-client/src/object/patch/set-data.js +++ b/packages/ipfs-http-client/src/object/patch/set-data.js @@ -5,12 +5,18 @@ const CID = require('cids') const multipartRequest = require('../../lib/multipart-request') const configure = require('../../lib/configure') const toUrlSearchParams = require('../../lib/to-url-search-params') +const anySignal = require('any-signal') +const AbortController = require('abort-controller') module.exports = configure(api => { return async (cid, data, options = {}) => { + // allow aborting requests on body errors + const controller = new AbortController() + const signal = anySignal([controller.signal, options.signal]) + const { Hash } = await (await api.post('object/patch/set-data', { timeout: options.timeout, - signal: options.signal, + signal, searchParams: toUrlSearchParams({ arg: [ `${Buffer.isBuffer(cid) ? new CID(cid) : cid}` @@ -18,7 +24,7 @@ module.exports = configure(api => { ...options }), ...( - await multipartRequest(data, options.headers) + await multipartRequest(data, controller, options.headers) ) })).json() diff --git a/packages/ipfs-http-client/src/object/put.js b/packages/ipfs-http-client/src/object/put.js index a0c7bc86d2..34bf8eebe5 100644 --- a/packages/ipfs-http-client/src/object/put.js +++ b/packages/ipfs-http-client/src/object/put.js @@ -6,6 +6,8 @@ const { Buffer } = require('buffer') const multipartRequest = require('../lib/multipart-request') const configure = require('../lib/configure') const toUrlSearchParams = require('../lib/to-url-search-params') +const anySignal = require('any-signal') +const AbortController = require('abort-controller') module.exports = configure(api => { return async (obj, options = {}) => { @@ -41,15 +43,20 @@ module.exports = configure(api => { if (Buffer.isBuffer(obj) && options.enc) { buf = obj } else { + options.enc = 'json' buf = Buffer.from(JSON.stringify(tmpObj)) } + // allow aborting requests on body errors + const controller = new AbortController() + const signal = anySignal([controller.signal, options.signal]) + const res = await api.post('object/put', { timeout: options.timeout, - signal: options.signal, + signal, searchParams: toUrlSearchParams(options), ...( - await multipartRequest(buf, options.headers) + await multipartRequest(buf, controller, options.headers) ) }) diff --git a/packages/ipfs-http-client/src/object/stat.js b/packages/ipfs-http-client/src/object/stat.js index fbbab191b9..1b8bfeb878 100644 --- a/packages/ipfs-http-client/src/object/stat.js +++ b/packages/ipfs-http-client/src/object/stat.js @@ -7,24 +7,16 @@ const toUrlSearchParams = require('../lib/to-url-search-params') module.exports = configure(api => { return async (cid, options = {}) => { - let res - try { - res = await (await api.post('object/stat', { - timeout: options.timeout, - signal: options.signal, - searchParams: toUrlSearchParams({ - arg: `${Buffer.isBuffer(cid) ? new CID(cid) : cid}`, - ...options - }), - headers: options.headers - })).json() - } catch (err) { - if (err.name === 'TimeoutError') { - err.message = `failed to get block for ${Buffer.isBuffer(cid) ? new CID(cid) : cid}: context deadline exceeded` - } - throw err - } + const res = await api.post('object/stat', { + timeout: options.timeout, + signal: options.signal, + searchParams: toUrlSearchParams({ + arg: `${Buffer.isBuffer(cid) ? new CID(cid) : cid}`, + ...options + }), + headers: options.headers + }) - return res + return res.json() } }) diff --git a/packages/ipfs-http-client/src/pin/ls.js b/packages/ipfs-http-client/src/pin/ls.js index 1158ec394d..4ff1606f53 100644 --- a/packages/ipfs-http-client/src/pin/ls.js +++ b/packages/ipfs-http-client/src/pin/ls.js @@ -6,7 +6,7 @@ const toUrlSearchParams = require('../lib/to-url-search-params') module.exports = configure(api => { return async function * ls (path, options = {}) { - if (path && path.type) { + if (path && (path.type || path.timeout)) { options = path || {} path = [] } diff --git a/packages/ipfs-http-client/test/interface.spec.js b/packages/ipfs-http-client/test/interface.spec.js index 4d42102cb5..62ea3258d4 100644 --- a/packages/ipfs-http-client/test/interface.spec.js +++ b/packages/ipfs-http-client/test/interface.spec.js @@ -80,6 +80,10 @@ describe('interface-ipfs-core tests', () => { name: 'replace', reason: 'FIXME Waiting for fix on go-ipfs https://github.com/ipfs/js-ipfs-http-client/pull/307#discussion_r69281789 and https://github.com/ipfs/go-ipfs/issues/2927' }, + { + name: 'should respect timeout option when listing config profiles', + reason: 'TODO: Not implemented in go-ipfs' + }, { name: 'should list config profiles', reason: 'TODO: Not implemented in go-ipfs' @@ -159,6 +163,10 @@ describe('interface-ipfs-core tests', () => { name: 'should ls from outside of mfs', reason: 'TODO not implemented in go-ipfs yet' }, + { + name: 'should respect timeout option when changing the mode of a file', + reason: 'TODO not implemented in go-ipfs yet' + }, { name: 'should update the mode for a file', reason: 'TODO not implemented in go-ipfs yet' @@ -251,6 +259,10 @@ describe('interface-ipfs-core tests', () => { name: 'should respect metadata when copying from outside of mfs', reason: 'TODO not implemented in go-ipfs yet' }, + { + name: 'should respect timeout option when updating the modification time of files', + reason: 'TODO not implemented in go-ipfs yet' + }, { name: 'should have default mtime', reason: 'TODO not implemented in go-ipfs yet' diff --git a/packages/ipfs/.aegir.js b/packages/ipfs/.aegir.js index 2082c06348..b26f1c069f 100644 --- a/packages/ipfs/.aegir.js +++ b/packages/ipfs/.aegir.js @@ -23,7 +23,7 @@ module.exports = { served: true, included: false }], - browserNoActivityTimeout: 100 * 1000, + browserNoActivityTimeout: 100 * 1000 }, hooks: { node: { diff --git a/packages/ipfs/docs/MODULE.md b/packages/ipfs/docs/MODULE.md index 27f53e50e3..248394690a 100644 --- a/packages/ipfs/docs/MODULE.md +++ b/packages/ipfs/docs/MODULE.md @@ -21,7 +21,6 @@ Use the IPFS module as a dependency of your project to spawn in process instance - [`options.libp2p`](#optionslibp2p) - [Instance methods](#instance-methods) - [`node.start()`](#nodestart) - - [`node.stop()`](#nodestop) - [Static types and utils](#static-types-and-utils) - [Glob source](#glob-source) - [`globSource(path, [options])`](#globsourcepath-options) @@ -74,7 +73,7 @@ const node = await IPFS.create({ repo: '/var/ipfs/data' }) | Type | Default | |------|---------| -| boolean | `true` | +| `boolean` | `true` | `js-ipfs` comes bundled with a tool that automatically migrates your IPFS repository when a new version is available. @@ -112,7 +111,7 @@ Instead of a boolean, you may provide an object with custom initialization optio | Type | Default | |------|---------| -| boolean | `true` | +| `boolean` | `true` | If `false`, do not automatically start the IPFS node. Instead, you’ll need to manually call [`node.start()`](#nodestart) yourself. @@ -345,24 +344,6 @@ try { } ``` -#### `node.stop()` - -Close and stop listening for connections with other IPFS nodes, then release access to the node’s repo. - -This method is asynchronous and returns a promise. - -```js -const node = await IPFS.create() -console.log('Node is ready to use!') - -try { - await node.stop() - console.log('Node stopped!') -} catch (error) { - console.error('Node failed to stop!', error) -} -``` - ## Static types and utils Aside from the default export, `ipfs` exports various types and utilities that are included in the bundle: diff --git a/packages/ipfs/package.json b/packages/ipfs/package.json index a7c1d06639..e6003ec8a9 100644 --- a/packages/ipfs/package.json +++ b/packages/ipfs/package.json @@ -51,11 +51,11 @@ "test:interface": "aegir test -f test/core/interface.spec.js", "test:interface:http": "aegir test -f test/http-api/interface.js", "test:bootstrapers": "IPFS_TEST=bootstrapers aegir test -t browser -f test/bootstrapers.js", - "test:interop": "cross-env IPFS_JS_EXEC=$PWD/src/cli/bin.js IPFS_JS_MODULE=$PWD IPFS_REUSEPORT=false ipfs-interop", - "test:interop:node": "cross-env IPFS_JS_EXEC=$PWD/src/cli/bin.js IPFS_JS_MODULE=$PWD IPFS_REUSEPORT=false ipfs-interop -- -t node", - "test:interop:browser": "cross-env IPFS_JS_EXEC=$PWD/src/cli/bin.js IPFS_JS_MODULE=$PWD IPFS_REUSEPORT=false ipfs-interop -- -t browser", - "test:interop:electron-main": "cross-env IPFS_JS_EXEC=$PWD/src/cli/bin.js IPFS_JS_MODULE=$PWD IPFS_REUSEPORT=false ipfs-interop -- -t electron-main -f ./test/node.js", - "test:interop:electron-renderer": "cross-env IPFS_JS_EXEC=$PWD/src/cli/bin.js IPFS_JS_MODULE=$PWD IPFS_REUSEPORT=false ipfs-interop -- -t electron-renderer -f ./test/browser.js", + "test:interop": "cross-env IPFS_JS_EXEC=$PWD/src/cli/bin.js IPFS_JS_MODULE=$PWD IPFS_JS_HTTP_MODULE=$PWD/../ipfs-http-client IPFS_REUSEPORT=false ipfs-interop", + "test:interop:node": "cross-env IPFS_JS_EXEC=$PWD/src/cli/bin.js IPFS_JS_MODULE=$PWD IPFS_JS_HTTP_MODULE=$PWD/../ipfs-http-client IPFS_REUSEPORT=false ipfs-interop -- -t node", + "test:interop:browser": "cross-env IPFS_JS_EXEC=$PWD/src/cli/bin.js IPFS_JS_MODULE=$PWD IPFS_JS_HTTP_MODULE=$PWD/../ipfs-http-client IPFS_REUSEPORT=false ipfs-interop -- -t browser", + "test:interop:electron-main": "cross-env IPFS_JS_EXEC=$PWD/src/cli/bin.js IPFS_JS_MODULE=$PWD IPFS_JS_HTTP_MODULE=$PWD/../ipfs-http-client IPFS_REUSEPORT=false ipfs-interop -- -t electron-main -f ./test/node.js", + "test:interop:electron-renderer": "cross-env IPFS_JS_EXEC=$PWD/src/cli/bin.js IPFS_JS_MODULE=$PWD IPFS_JS_HTTP_MODULE=$PWD/../ipfs-http-client IPFS_REUSEPORT=false ipfs-interop -- -t electron-renderer -f ./test/browser.js", "test:external": "aegir test-dependant", "coverage": "nyc --reporter=text --reporter=lcov npm run test:node", "clean": "rm -rf ./dist", @@ -142,7 +142,7 @@ "libp2p-mplex": "^0.9.3", "libp2p-record": "^0.7.3", "libp2p-secio": "^0.12.2", - "libp2p-tcp": "^0.14.3", + "libp2p-tcp": "^0.14.5", "libp2p-webrtc-star": "^0.17.10", "libp2p-websockets": "^0.13.3", "mafmt": "^7.0.0", @@ -174,7 +174,7 @@ "yargs-promise": "^1.1.0" }, "devDependencies": { - "aegir": "^21.10.1", + "aegir": "^22.0.0", "base64url": "^3.0.1", "clear-module": "^4.0.0", "cross-env": "^7.0.0", @@ -183,8 +183,8 @@ "form-data": "^3.0.0", "go-ipfs-dep": "0.4.23-3", "interface-ipfs-core": "^0.134.3", - "ipfs-interop": "^1.0.1", - "ipfsd-ctl": "^4.0.1", + "ipfs-interop": "^1.0.3", + "ipfsd-ctl": "^4.1.1", "iso-random-stream": "^1.1.1", "it-first": "^1.0.1", "it-to-buffer": "^1.0.0", diff --git a/packages/ipfs/src/cli/commands/add.js b/packages/ipfs/src/cli/commands/add.js index d2580e0875..0a830f4d9a 100644 --- a/packages/ipfs/src/cli/commands/add.js +++ b/packages/ipfs/src/cli/commands/add.js @@ -13,6 +13,7 @@ const { } = require('../utils') const { cidToString } = require('../../utils/cid') const globSource = require('ipfs-utils/src/files/glob-source') +const parseDuration = require('parse-duration') async function getTotalBytes (paths) { const sizes = await Promise.all(paths.map(p => getFolderSize(p))) @@ -153,25 +154,57 @@ module.exports = { type: 'number', coerce: coerceMtimeNsecs, describe: 'Modification time fraction in nanoseconds' + }, + timeout: { + type: 'string', + coerce: parseDuration } }, - async handler (argv) { - const { ipfs, print, isDaemon, getStdin } = argv.ctx + async handler ({ + ctx: { ipfs, print, isDaemon, getStdin }, + trickle, + shardSplitThreshold, + cidVersion, + rawLeaves, + onlyHash, + hash, + wrapWithDirectory, + pin, + chunker, + preload, + fileImportConcurrency, + blockWriteConcurrency, + timeout, + quieter, + quiet, + silent, + progress, + file, + mtime, + mtimeNsecs, + recursive, + hidden, + preserveMode, + preserveMtime, + mode, + cidBase + }) { const options = { - trickle: argv.trickle, - shardSplitThreshold: argv.shardSplitThreshold, - cidVersion: argv.cidVersion, - rawLeaves: argv.rawLeaves, - onlyHash: argv.onlyHash, - hashAlg: argv.hash, - wrapWithDirectory: argv.wrapWithDirectory, - pin: argv.pin, - chunker: argv.chunker, - preload: argv.preload, - fileImportConcurrency: argv.fileImportConcurrency, - blockWriteConcurrency: argv.blockWriteConcurrency, - progress: () => {} + trickle, + shardSplitThreshold, + cidVersion, + rawLeaves, + onlyHash, + hashAlg: hash, + wrapWithDirectory, + pin, + chunker, + preload, + fileImportConcurrency, + blockWriteConcurrency, + progress: () => {}, + timeout } if (options.enableShardingExperiment && isDaemon) { @@ -181,12 +214,12 @@ module.exports = { let bar let log = print - if (argv.quieter || argv.quiet || argv.silent) { - argv.progress = false + if (quieter || quiet || silent) { + progress = false } - if (argv.progress && argv.file) { - const totalBytes = await getTotalBytes(argv.file) + if (progress && file) { + const totalBytes = await getTotalBytes(file) bar = createProgressBar(totalBytes, print) if (print.isTTY) { @@ -198,75 +231,69 @@ module.exports = { } } - let mtime - - if (argv.mtime != null) { + if (mtime != null) { mtime = { - secs: argv.mtime + secs: mtime } - if (argv.mtimeNsecs != null) { - mtime.nsecs = argv.mtimeNsecs + if (mtimeNsecs != null) { + mtime.nsecs = mtimeNsecs } } - const source = argv.file - ? globSource(argv.file, { - recursive: argv.recursive, - hidden: argv.hidden, - preserveMode: argv.preserveMode, - preserveMtime: argv.preserveMtime, - mode: argv.mode, + const source = file + ? globSource(file, { + recursive, + hidden, + preserveMode, + preserveMtime, + mode, mtime }) : { content: getStdin(), - mode: argv.mode, + mode, mtime } // Pipe to ipfs.add tagging with mode and mtime let finalCid try { - for await (const file of ipfs.add(source, options)) { - if (argv.silent) { + for await (const added of ipfs.add(source, options)) { + if (silent) { continue } - if (argv.quieter) { - finalCid = file.cid + if (quieter) { + finalCid = added.cid continue } - const cid = cidToString(file.cid, { base: argv.cidBase }) + const cid = cidToString(added.cid, { base: cidBase }) let message = cid - if (!argv.quiet) { + if (!quiet) { // print the hash twice if we are piping from stdin - message = `added ${cid} ${argv.file ? file.path || '' : cid}`.trim() + message = `added ${cid} ${file ? added.path || '' : cid}`.trim() } log(message) } } catch (err) { - if (bar) { - bar.terminate() - } - // Tweak the error message and add more relevant infor for the CLI if (err.code === 'ERR_DIR_NON_RECURSIVE') { err.message = `'${err.path}' is a directory, use the '-r' flag to specify directories` } throw err + } finally { + if (bar) { + bar.terminate() + } } - if (bar) { - bar.terminate() - } - - if (argv.quieter) { - log(cidToString(finalCid, { base: argv.cidBase })) + if (quieter) { + log(cidToString(finalCid, { base: cidBase })) } } } diff --git a/packages/ipfs/src/cli/commands/bitswap/stat.js b/packages/ipfs/src/cli/commands/bitswap/stat.js index 385d47d891..c6580b807f 100644 --- a/packages/ipfs/src/cli/commands/bitswap/stat.js +++ b/packages/ipfs/src/cli/commands/bitswap/stat.js @@ -3,6 +3,7 @@ const multibase = require('multibase') const { cidToString } = require('../../../utils/cid') const prettyBytes = require('pretty-bytes') +const parseDuration = require('parse-duration') module.exports = { command: 'stat', @@ -18,12 +19,19 @@ module.exports = { human: { type: 'boolean', default: false + }, + timeout: { + type: 'string', + coerce: parseDuration } }, - async handler ({ ctx, cidBase, human }) { + async handler ({ ctx, cidBase, human, timeout }) { const { ipfs, print } = ctx - const stats = await ipfs.bitswap.stat() + + const stats = await ipfs.bitswap.stat({ + timeout + }) if (human) { stats.blocksReceived = stats.blocksReceived.toNumber() diff --git a/packages/ipfs/src/cli/commands/bitswap/unwant.js b/packages/ipfs/src/cli/commands/bitswap/unwant.js index 171c162306..5aef62a73b 100644 --- a/packages/ipfs/src/cli/commands/bitswap/unwant.js +++ b/packages/ipfs/src/cli/commands/bitswap/unwant.js @@ -2,6 +2,7 @@ const multibase = require('multibase') const { cidToString } = require('../../../utils/cid') +const parseDuration = require('parse-duration') module.exports = { command: 'unwant ', @@ -18,11 +19,17 @@ module.exports = { describe: 'Number base to display CIDs in. Note: specifying a CID base for v0 CIDs will have no effect.', type: 'string', choices: multibase.names + }, + timeout: { + type: 'string', + coerce: parseDuration } }, - async handler ({ ctx, key, cidBase }) { + async handler ({ ctx, key, cidBase, timeout }) { const { ipfs, print } = ctx - await ipfs.bitswap.unwant(key) + await ipfs.bitswap.unwant(key, { + timeout + }) print(`Key ${cidToString(key, { base: cidBase, upgrade: false })} removed from wantlist`) } } diff --git a/packages/ipfs/src/cli/commands/bitswap/wantlist.js b/packages/ipfs/src/cli/commands/bitswap/wantlist.js index 951d8e7e64..d769e384fc 100644 --- a/packages/ipfs/src/cli/commands/bitswap/wantlist.js +++ b/packages/ipfs/src/cli/commands/bitswap/wantlist.js @@ -2,6 +2,7 @@ const multibase = require('multibase') const { cidToString } = require('../../../utils/cid') +const parseDuration = require('parse-duration') module.exports = { command: 'wantlist [peer]', @@ -18,12 +19,18 @@ module.exports = { describe: 'Number base to display CIDs in. Note: specifying a CID base for v0 CIDs will have no effect.', type: 'string', choices: multibase.names + }, + timeout: { + type: 'string', + coerce: parseDuration } }, - async handler ({ ctx, peer, cidBase }) { + async handler ({ ctx, peer, cidBase, timeout }) { const { ipfs, print } = ctx - const list = await ipfs.bitswap.wantlist(peer) + const list = await ipfs.bitswap.wantlist(peer, { + timeout + }) list.forEach(cid => print(cidToString(cid, { base: cidBase, upgrade: false }))) } } diff --git a/packages/ipfs/src/cli/commands/block/get.js b/packages/ipfs/src/cli/commands/block/get.js index 461298db04..2282cc2a56 100644 --- a/packages/ipfs/src/cli/commands/block/get.js +++ b/packages/ipfs/src/cli/commands/block/get.js @@ -1,15 +1,24 @@ 'use strict' +const parseDuration = require('parse-duration') + module.exports = { command: 'get ', describe: 'Get a raw IPFS block', - builder: {}, + builder: { + timeout: { + type: 'string', + coerce: parseDuration + } + }, - async handler ({ ctx, key }) { + async handler ({ ctx, key, timeout }) { const { ipfs, print } = ctx - const block = await ipfs.block.get(key) + const block = await ipfs.block.get(key, { + timeout + }) if (block) { print(block.data, false) } else { diff --git a/packages/ipfs/src/cli/commands/block/put.js b/packages/ipfs/src/cli/commands/block/put.js index 323d9ff188..d29c5e5deb 100644 --- a/packages/ipfs/src/cli/commands/block/put.js +++ b/packages/ipfs/src/cli/commands/block/put.js @@ -4,6 +4,7 @@ const fs = require('fs') const multibase = require('multibase') const concat = require('it-concat') const { cidToString } = require('../../../utils/cid') +const parseDuration = require('parse-duration') module.exports = { command: 'put [block]', @@ -26,26 +27,42 @@ module.exports = { }, version: { describe: 'cid version', - type: 'number' + type: 'number', + default: 0 }, 'cid-base': { describe: 'Number base to display CIDs in.', type: 'string', choices: multibase.names + }, + pin: { + describe: 'Pin this block recursively', + type: 'boolean', + default: false + }, + timeout: { + type: 'string', + coerce: parseDuration } }, - async handler (argv) { - const { ipfs, print, getStdin } = argv.ctx + async handler ({ ctx: { ipfs, print, getStdin }, block, timeout, format, mhtype, mhlen, version, cidBase, pin }) { let data - if (argv.block) { - data = fs.readFileSync(argv.block) + if (block) { + data = fs.readFileSync(block) } else { data = (await concat(getStdin())).slice() } - const { cid } = await ipfs.block.put(data, argv) - print(cidToString(cid, { base: argv.cidBase })) + const { cid } = await ipfs.block.put(data, { + timeout, + format, + mhtype, + mhlen, + version, + pin + }) + print(cidToString(cid, { base: cidBase })) } } diff --git a/packages/ipfs/src/cli/commands/block/rm.js b/packages/ipfs/src/cli/commands/block/rm.js index eb6d21905b..4efd88def5 100644 --- a/packages/ipfs/src/cli/commands/block/rm.js +++ b/packages/ipfs/src/cli/commands/block/rm.js @@ -1,5 +1,7 @@ 'use strict' +const parseDuration = require('parse-duration') + module.exports = { command: 'rm ', @@ -17,17 +19,22 @@ module.exports = { describe: 'Write minimal output', type: 'boolean', default: false + }, + timeout: { + type: 'string', + coerce: parseDuration } }, - async handler ({ ctx, hash, force, quiet }) { + async handler ({ ctx, hash, force, quiet, timeout }) { const { ipfs, print } = ctx let errored = false for await (const result of ipfs.block.rm(hash, { force, - quiet + quiet, + timeout })) { if (result.error) { errored = true diff --git a/packages/ipfs/src/cli/commands/block/stat.js b/packages/ipfs/src/cli/commands/block/stat.js index e7113b35b1..f02afb0f83 100644 --- a/packages/ipfs/src/cli/commands/block/stat.js +++ b/packages/ipfs/src/cli/commands/block/stat.js @@ -2,6 +2,7 @@ const multibase = require('multibase') const { cidToString } = require('../../../utils/cid') +const parseDuration = require('parse-duration') module.exports = { command: 'stat ', @@ -13,12 +14,18 @@ module.exports = { describe: 'Number base to display CIDs in.', type: 'string', choices: multibase.names + }, + timeout: { + type: 'string', + coerce: parseDuration } }, - async handler ({ ctx, key, cidBase }) { + async handler ({ ctx, key, cidBase, timeout }) { const { ipfs, print } = ctx - const stats = await ipfs.block.stat(key) + const stats = await ipfs.block.stat(key, { + timeout + }) print('Key: ' + cidToString(stats.cid, { base: cidBase })) print('Size: ' + stats.size) } diff --git a/packages/ipfs/src/cli/commands/bootstrap/add.js b/packages/ipfs/src/cli/commands/bootstrap/add.js index a8cbe21122..ea84d24e4e 100644 --- a/packages/ipfs/src/cli/commands/bootstrap/add.js +++ b/packages/ipfs/src/cli/commands/bootstrap/add.js @@ -1,5 +1,7 @@ 'use strict' +const parseDuration = require('parse-duration') + module.exports = { command: 'add []', @@ -10,12 +12,18 @@ module.exports = { describe: 'Add default bootstrap nodes.', type: 'boolean', default: false + }, + timeout: { + type: 'string', + coerce: parseDuration } }, - async handler (argv) { - const { ipfs, print } = argv.ctx - const list = await ipfs.bootstrap.add(argv.peer, { default: argv.default }) + async handler ({ ctx: { ipfs, print }, peer, default: defaultPeers, timeout }) { + const list = await ipfs.bootstrap.add(peer, { + default: defaultPeers, + timeout + }) list.Peers.forEach((peer) => print(peer)) } } diff --git a/packages/ipfs/src/cli/commands/bootstrap/list.js b/packages/ipfs/src/cli/commands/bootstrap/list.js index df99f8b2ba..70ced1eb6f 100644 --- a/packages/ipfs/src/cli/commands/bootstrap/list.js +++ b/packages/ipfs/src/cli/commands/bootstrap/list.js @@ -1,15 +1,23 @@ 'use strict' +const parseDuration = require('parse-duration') + module.exports = { command: 'list', describe: 'Show peers in the bootstrap list', - builder: {}, + builder: { + timeout: { + type: 'string', + coerce: parseDuration + } + }, - async handler (argv) { - const { ipfs, print } = argv.ctx - const list = await ipfs.bootstrap.list() + async handler ({ ctx: { ipfs, print }, timeout }) { + const list = await ipfs.bootstrap.list({ + timeout + }) list.Peers.forEach((node) => print(node)) } } diff --git a/packages/ipfs/src/cli/commands/bootstrap/rm.js b/packages/ipfs/src/cli/commands/bootstrap/rm.js index 9ff02f1a99..b19dfdf527 100644 --- a/packages/ipfs/src/cli/commands/bootstrap/rm.js +++ b/packages/ipfs/src/cli/commands/bootstrap/rm.js @@ -3,6 +3,7 @@ const debug = require('debug') const log = debug('cli:bootstrap') log.error = debug('cli:bootstrap:error') +const parseDuration = require('parse-duration') module.exports = { command: 'rm []', @@ -14,12 +15,18 @@ module.exports = { type: 'boolean', describe: 'Remove all bootstrap peers.', default: false + }, + timeout: { + type: 'string', + coerce: parseDuration } }, - async handler ({ ctx, all, peer }) { - const { ipfs, print } = ctx - const list = await ipfs.bootstrap.rm(peer, { all }) + async handler ({ ctx: { ipfs, print }, all, peer, timeout }) { + const list = await ipfs.bootstrap.rm(peer, { + all, + timeout + }) list.Peers.forEach((peer) => print(peer)) } } diff --git a/packages/ipfs/src/cli/commands/cat.js b/packages/ipfs/src/cli/commands/cat.js index bb3fbcfa79..5f9887b6e0 100644 --- a/packages/ipfs/src/cli/commands/cat.js +++ b/packages/ipfs/src/cli/commands/cat.js @@ -1,5 +1,7 @@ 'use strict' +const parseDuration = require('parse-duration') + module.exports = { command: 'cat ', @@ -15,13 +17,15 @@ module.exports = { alias: ['n', 'count'], type: 'integer', describe: 'Maximum number of bytes to read' + }, + timeout: { + type: 'string', + coerce: parseDuration } }, - async handler ({ ctx, ipfsPath, offset, length }) { - const { ipfs, print } = ctx - - for await (const buf of ipfs.cat(ipfsPath, { offset, length })) { + async handler ({ ctx: { ipfs, print }, ipfsPath, offset, length, timeout }) { + for await (const buf of ipfs.cat(ipfsPath, { offset, length, timeout })) { print.write(buf) } } diff --git a/packages/ipfs/src/cli/commands/config.js b/packages/ipfs/src/cli/commands/config.js index 3311148c05..b8e851ddb5 100644 --- a/packages/ipfs/src/cli/commands/config.js +++ b/packages/ipfs/src/cli/commands/config.js @@ -1,5 +1,7 @@ 'use strict' +const parseDuration = require('parse-duration') + module.exports = { command: 'config [value]', @@ -18,14 +20,18 @@ module.exports = { describe: 'Parse stringified JSON.', default: false }) + .option('timeout', { + type: 'string', + coerce: parseDuration + }) }, - async handler ({ ctx, value, bool, json, key }) { - const { ipfs, print } = ctx - + async handler ({ ctx: { ipfs, print }, value, bool, json, key, timeout }) { if (!value) { // Get the value of a given key - value = await ipfs.config.get(key) + value = await ipfs.config.get(key, { + timeout + }) if (typeof value === 'object') { print(JSON.stringify(value, null, 2)) @@ -45,7 +51,9 @@ module.exports = { } } - await ipfs.config.set(key, value) + await ipfs.config.set(key, value, { + timeout + }) } } } diff --git a/packages/ipfs/src/cli/commands/config/profile/apply.js b/packages/ipfs/src/cli/commands/config/profile/apply.js index 2bbc6aa2f3..353d91b07f 100644 --- a/packages/ipfs/src/cli/commands/config/profile/apply.js +++ b/packages/ipfs/src/cli/commands/config/profile/apply.js @@ -1,6 +1,7 @@ 'use strict' const JSONDiff = require('jsondiffpatch') +const parseDuration = require('parse-duration') module.exports = { command: 'apply ', @@ -12,12 +13,19 @@ module.exports = { type: 'boolean', describe: 'print difference between the current config and the config that would be generated.', default: false + }, + timeout: { + type: 'string', + coerce: parseDuration } }, - async handler ({ ctx, profile, dryRun }) { + async handler ({ ctx, profile, dryRun, timeout }) { const { print, ipfs, isDaemon } = ctx - const diff = await ipfs.config.profiles.apply(profile, { dryRun }) + const diff = await ipfs.config.profiles.apply(profile, { + dryRun, + timeout + }) const delta = JSONDiff.diff(diff.original, diff.updated) const res = JSONDiff.formatters.console.format(delta, diff.original) diff --git a/packages/ipfs/src/cli/commands/config/profile/ls.js b/packages/ipfs/src/cli/commands/config/profile/ls.js index a1f66bf9e3..a38f03700e 100644 --- a/packages/ipfs/src/cli/commands/config/profile/ls.js +++ b/packages/ipfs/src/cli/commands/config/profile/ls.js @@ -1,13 +1,23 @@ 'use strict' +const parseDuration = require('parse-duration') + module.exports = { command: 'ls', describe: 'List available config profiles', - async handler (argv) { - const { ipfs, print } = argv.ctx - for (const profile of await ipfs.config.profiles.list()) { + builder: { + timeout: { + type: 'string', + coerce: parseDuration + } + }, + + async handler ({ ctx: { ipfs, print }, timeout }) { + for (const profile of await ipfs.config.profiles.list({ + timeout + })) { print(`${profile.name}:\n ${profile.description}`) } } diff --git a/packages/ipfs/src/cli/commands/config/replace.js b/packages/ipfs/src/cli/commands/config/replace.js index f31d830e17..bfe9bc3756 100644 --- a/packages/ipfs/src/cli/commands/config/replace.js +++ b/packages/ipfs/src/cli/commands/config/replace.js @@ -2,20 +2,28 @@ const path = require('path') const fs = require('fs') +const parseDuration = require('parse-duration') module.exports = { command: 'replace ', describe: 'Replaces the config with ', - handler ({ ctx, file }) { - const { ipfs, isDaemon } = ctx + builder: { + timeout: { + type: 'string', + coerce: parseDuration + } + }, + handler ({ ctx: { ipfs, isDaemon }, file, timeout }) { const filePath = path.resolve(process.cwd(), file) const config = isDaemon ? filePath : JSON.parse(fs.readFileSync(filePath, 'utf8')) - return ipfs.config.replace(config) + return ipfs.config.replace(config, { + timeout + }) } } diff --git a/packages/ipfs/src/cli/commands/config/show.js b/packages/ipfs/src/cli/commands/config/show.js index 1a04556094..cd85c8c787 100644 --- a/packages/ipfs/src/cli/commands/config/show.js +++ b/packages/ipfs/src/cli/commands/config/show.js @@ -3,15 +3,24 @@ const debug = require('debug') const log = debug('cli:config') log.error = debug('cli:config:error') +const parseDuration = require('parse-duration') module.exports = { command: 'show', describe: 'Outputs the content of the config file', - async handler ({ ctx }) { - const { ipfs, print } = ctx - const config = await ipfs.config.get() + builder: { + timeout: { + type: 'string', + coerce: parseDuration + } + }, + + async handler ({ ctx: { ipfs, print }, timeout }) { + const config = await ipfs.config.get({ + timeout + }) print(JSON.stringify(config, null, 4)) } } diff --git a/packages/ipfs/src/cli/commands/dag/get.js b/packages/ipfs/src/cli/commands/dag/get.js index 863580c369..9d7f90d6fa 100644 --- a/packages/ipfs/src/cli/commands/dag/get.js +++ b/packages/ipfs/src/cli/commands/dag/get.js @@ -1,7 +1,9 @@ 'use strict' const CID = require('cids') +const parseDuration = require('parse-duration') const { Buffer } = require('buffer') + module.exports = { command: 'get ', @@ -11,18 +13,22 @@ module.exports = { 'local-resolve': { type: 'boolean', default: false + }, + timeout: { + type: 'string', + coerce: parseDuration } }, - async handler ({ ctx, cidpath, localResolve }) { - const { ipfs, print } = ctx + 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: localResolve + localResolve, + timeout } let result diff --git a/packages/ipfs/src/cli/commands/dag/put.js b/packages/ipfs/src/cli/commands/dag/put.js index 0506907aaa..0110fc545e 100644 --- a/packages/ipfs/src/cli/commands/dag/put.js +++ b/packages/ipfs/src/cli/commands/dag/put.js @@ -7,6 +7,7 @@ const dagPB = require('ipld-dag-pb') const concat = require('it-concat') const CID = require('cids') const { cidToString } = require('../../../utils/cid') +const parseDuration = require('parse-duration') const inputDecoders = { json: (buf) => JSON.parse(buf.toString()), @@ -77,11 +78,14 @@ module.exports = { type: 'boolean', default: false, describe: 'Only hash the content, do not write to the underlying block store' + }, + timeout: { + type: 'string', + coerce: parseDuration } }, - async handler ({ ctx, data, format, inputEncoding, pin, hashAlg, cidVersion, cidBase, preload, onlyHash }) { - const { ipfs, print, getStdin } = ctx + async handler ({ ctx: { ipfs, print, getStdin }, data, format, inputEncoding, pin, hashAlg, cidVersion, cidBase, preload, onlyHash, timeout }) { if (inputEncoding === 'cbor') { format = 'dag-cbor' } else if (inputEncoding === 'protobuf') { @@ -117,7 +121,8 @@ module.exports = { version: cidVersion, onlyHash, preload, - pin + pin, + timeout }) print(cidToString(cid, { base: cidBase })) diff --git a/packages/ipfs/src/cli/commands/dag/resolve.js b/packages/ipfs/src/cli/commands/dag/resolve.js index 66928c39ae..e5a183357e 100644 --- a/packages/ipfs/src/cli/commands/dag/resolve.js +++ b/packages/ipfs/src/cli/commands/dag/resolve.js @@ -1,6 +1,7 @@ 'use strict' const CID = require('cids') +const parseDuration = require('parse-duration') module.exports = { command: 'resolve ', @@ -10,12 +11,17 @@ module.exports = { builder: { ref: { type: 'string' + }, + timeout: { + type: 'string', + coerce: parseDuration } }, - async handler ({ ctx, ref }) { - const { ipfs, print } = ctx - const options = {} + async handler ({ ctx: { ipfs, print }, ref, timeout }) { + const options = { + timeout + } try { let lastCid diff --git a/packages/ipfs/src/cli/commands/dht/find-peer.js b/packages/ipfs/src/cli/commands/dht/find-peer.js index 60cec2a642..7dcc57dd48 100644 --- a/packages/ipfs/src/cli/commands/dht/find-peer.js +++ b/packages/ipfs/src/cli/commands/dht/find-peer.js @@ -1,13 +1,23 @@ 'use strict' +const parseDuration = require('parse-duration') + module.exports = { command: 'findpeer ', describe: 'Find the multiaddresses associated with a Peer ID.', - async handler ({ ctx, peerId }) { - const { ipfs, print } = ctx - const peer = await ipfs.dht.findPeer(peerId) + builder: { + timeout: { + type: 'string', + coerce: parseDuration + } + }, + + async handler ({ ctx: { ipfs, print }, peerId, timeout }) { + const peer = await ipfs.dht.findPeer(peerId, { + timeout + }) peer.addrs.forEach(addr => print(`${addr}`)) } } diff --git a/packages/ipfs/src/cli/commands/dht/find-providers.js b/packages/ipfs/src/cli/commands/dht/find-providers.js index 43869fb4ec..0061b25972 100644 --- a/packages/ipfs/src/cli/commands/dht/find-providers.js +++ b/packages/ipfs/src/cli/commands/dht/find-providers.js @@ -1,5 +1,7 @@ 'use strict' +const parseDuration = require('parse-duration') + module.exports = { command: 'findprovs ', @@ -11,12 +13,18 @@ module.exports = { describe: 'The number of providers to find. Default: 20.', default: 20, type: 'number' + }, + timeout: { + type: 'string', + coerce: parseDuration } }, - async handler ({ ctx, key, numProviders }) { - const { ipfs, print } = ctx - for await (const prov of ipfs.dht.findProvs(key, { numProviders })) { + async handler ({ ctx: { ipfs, print }, key, numProviders, timeout }) { + for await (const prov of ipfs.dht.findProvs(key, { + numProviders, + timeout + })) { print(prov.id.toString()) } } diff --git a/packages/ipfs/src/cli/commands/dht/get.js b/packages/ipfs/src/cli/commands/dht/get.js index b3580da7d0..712dced4c8 100644 --- a/packages/ipfs/src/cli/commands/dht/get.js +++ b/packages/ipfs/src/cli/commands/dht/get.js @@ -1,13 +1,23 @@ 'use strict' +const parseDuration = require('parse-duration') + module.exports = { command: 'get ', describe: 'Given a key, query the routing system for its best value.', - async handler ({ ctx, key }) { - const { ipfs, print } = ctx - const value = await ipfs.dht.get(key) + builder: { + timeout: { + type: 'string', + coerce: parseDuration + } + }, + + async handler ({ ctx: { ipfs, print }, key, timeout }) { + const value = await ipfs.dht.get(key, { + timeout + }) print(value) } } diff --git a/packages/ipfs/src/cli/commands/dht/provide.js b/packages/ipfs/src/cli/commands/dht/provide.js index ec35c0f5c1..5001f028af 100644 --- a/packages/ipfs/src/cli/commands/dht/provide.js +++ b/packages/ipfs/src/cli/commands/dht/provide.js @@ -1,5 +1,7 @@ 'use strict' +const parseDuration = require('parse-duration') + module.exports = { command: 'provide ', @@ -11,11 +13,17 @@ module.exports = { recursive: 'Recursively provide entire graph.', default: false, type: 'boolean' + }, + timeout: { + type: 'string', + coerce: parseDuration } }, - async handler ({ ctx, key, recursive }) { - const { ipfs } = ctx - await ipfs.dht.provide(key, { recursive }) + async handler ({ ctx: { ipfs }, key, recursive, timeout }) { + await ipfs.dht.provide(key, { + recursive, + timeout + }) } } diff --git a/packages/ipfs/src/cli/commands/dht/put.js b/packages/ipfs/src/cli/commands/dht/put.js index ef2ba4ff6b..ce078c5a39 100644 --- a/packages/ipfs/src/cli/commands/dht/put.js +++ b/packages/ipfs/src/cli/commands/dht/put.js @@ -1,12 +1,22 @@ 'use strict' +const parseDuration = require('parse-duration') + module.exports = { command: 'put ', describe: 'Write a key/value pair to the routing system.', - async handler ({ ctx, key, value }) { - const { ipfs } = ctx - await ipfs.dht.put(key, value) + builder: { + timeout: { + type: 'string', + coerce: parseDuration + } + }, + + async handler ({ ctx: { ipfs }, key, value, timeout }) { + await ipfs.dht.put(key, value, { + timeout + }) } } diff --git a/packages/ipfs/src/cli/commands/dht/query.js b/packages/ipfs/src/cli/commands/dht/query.js index d56e0ebc51..2c5a6d43f1 100644 --- a/packages/ipfs/src/cli/commands/dht/query.js +++ b/packages/ipfs/src/cli/commands/dht/query.js @@ -1,13 +1,23 @@ 'use strict' +const parseDuration = require('parse-duration') + module.exports = { command: 'query ', describe: 'Find the closest Peer IDs to a given Peer ID by querying the DHT.', - async handler ({ ctx, peerId }) { - const { ipfs, print } = ctx - for await (const result of ipfs.dht.query(peerId)) { + builder: { + timeout: { + type: 'string', + coerce: parseDuration + } + }, + + async handler ({ ctx: { ipfs, print }, peerId, timeout }) { + for await (const result of ipfs.dht.query(peerId, { + timeout + })) { print(result.id.toString()) } } diff --git a/packages/ipfs/src/cli/commands/dns.js b/packages/ipfs/src/cli/commands/dns.js index 37575d9fd3..baaf34b3e4 100644 --- a/packages/ipfs/src/cli/commands/dns.js +++ b/packages/ipfs/src/cli/commands/dns.js @@ -1,5 +1,7 @@ 'use strict' +const parseDuration = require('parse-duration') + module.exports = { command: 'dns ', @@ -14,13 +16,15 @@ module.exports = { }, format: { type: 'string' + }, + timeout: { + type: 'string', + coerce: parseDuration } }, - async handler ({ ctx, domain, recursive, format }) { - const { ipfs, print } = ctx - - const path = await ipfs.dns(domain, { recursive, format }) + async handler ({ ctx: { ipfs, print }, domain, recursive, format, timeout }) { + const path = await ipfs.dns(domain, { recursive, format, timeout }) print(path) } } diff --git a/packages/ipfs/src/cli/commands/files/chmod.js b/packages/ipfs/src/cli/commands/files/chmod.js index 7c405d1ff5..a78c538110 100644 --- a/packages/ipfs/src/cli/commands/files/chmod.js +++ b/packages/ipfs/src/cli/commands/files/chmod.js @@ -4,6 +4,7 @@ const { asBoolean, asOctal } = require('../../utils') +const parseDuration = require('parse-duration') module.exports = { command: 'chmod [mode] [path]', @@ -44,25 +45,29 @@ module.exports = { type: 'number', default: 1000, describe: 'If a directory has more links than this, it will be transformed into a hamt-sharded-directory' + }, + timeout: { + type: 'string', + coerce: parseDuration } }, - handler (argv) { - const { - ctx: { ipfs }, - path, - mode, - recursive, - hashAlg, - flush, - shardSplitThreshold - } = argv - + handler ({ + ctx: { ipfs }, + path, + mode, + recursive, + hashAlg, + flush, + shardSplitThreshold, + timeout + }) { return ipfs.files.chmod(path, mode, { recursive, hashAlg, flush, - shardSplitThreshold + shardSplitThreshold, + timeout }) } } diff --git a/packages/ipfs/src/cli/commands/files/cp.js b/packages/ipfs/src/cli/commands/files/cp.js index 41af91118d..4e527b0a50 100644 --- a/packages/ipfs/src/cli/commands/files/cp.js +++ b/packages/ipfs/src/cli/commands/files/cp.js @@ -3,6 +3,7 @@ const { asBoolean } = require('../../utils') +const parseDuration = require('parse-duration') module.exports = { command: 'cp ', @@ -34,25 +35,29 @@ module.exports = { type: 'number', default: 1000, describe: 'If a directory has more links than this, it will be transformed into a hamt-sharded-directory' + }, + timeout: { + type: 'string', + coerce: parseDuration } }, - handler (argv) { - const { - ctx: { ipfs }, - source, - dest, - parents, - flush, - hashAlg, - shardSplitThreshold - } = argv - + handler ({ + ctx: { ipfs }, + source, + dest, + parents, + flush, + hashAlg, + shardSplitThreshold, + timeout + }) { return ipfs.files.cp(source, dest, { parents, flush, hashAlg, - shardSplitThreshold + shardSplitThreshold, + timeout }) } } diff --git a/packages/ipfs/src/cli/commands/files/flush.js b/packages/ipfs/src/cli/commands/files/flush.js index b80b6628f0..01ad738364 100644 --- a/packages/ipfs/src/cli/commands/files/flush.js +++ b/packages/ipfs/src/cli/commands/files/flush.js @@ -1,5 +1,7 @@ 'use strict' +const parseDuration = require('parse-duration') + module.exports = { command: 'flush [path]', @@ -8,17 +10,22 @@ module.exports = { builder: { 'cid-base': { describe: 'CID base to use.' + }, + timeout: { + type: 'string', + coerce: parseDuration } }, - async handler (argv) { - const { - ctx: { ipfs, print }, - path, - cidBase - } = argv - - let cid = await ipfs.files.flush(path || '/', {}) + async handler ({ + ctx: { ipfs, print }, + path, + cidBase, + timeout + }) { + let cid = await ipfs.files.flush(path || '/', { + timeout + }) if (cidBase && cidBase !== 'base58btc' && cid.version === 0) { cid = cid.toV1() diff --git a/packages/ipfs/src/cli/commands/files/ls.js b/packages/ipfs/src/cli/commands/files/ls.js index 99a0ed4671..e374c14733 100644 --- a/packages/ipfs/src/cli/commands/files/ls.js +++ b/packages/ipfs/src/cli/commands/files/ls.js @@ -6,6 +6,7 @@ const { } = require('../../utils') const formatMode = require('ipfs-core-utils/src/files/format-mode') const formatMtime = require('ipfs-core-utils/src/files/format-mtime') +const parseDuration = require('parse-duration') module.exports = { command: 'ls [path]', @@ -29,18 +30,21 @@ module.exports = { }, 'cid-base': { describe: 'CID base to use.' + }, + timeout: { + type: 'string', + coerce: parseDuration } }, - async handler (argv) { - const { - ctx: { ipfs, print }, - path, - long, - sort, - cidBase - } = argv - + async handler ({ + ctx: { ipfs, print }, + path, + long, + sort, + cidBase, + timeout + }) { const printListing = file => { if (long) { print(`${formatMode(file.mode, file.type === 1)}\t${formatMtime(file.mtime)}\t${file.name}\t${file.cid.toString(cidBase)}\t${file.size}`) @@ -51,7 +55,9 @@ module.exports = { // https://github.com/ipfs/go-ipfs/issues/5181 if (sort) { - let files = await all(ipfs.files.ls(path || '/')) + let files = await all(ipfs.files.ls(path || '/', { + timeout + })) files = files.sort((a, b) => { return a.name.localeCompare(b.name) @@ -61,7 +67,9 @@ module.exports = { return } - for await (const file of ipfs.files.ls(path || '/')) { + for await (const file of ipfs.files.ls(path || '/', { + timeout + })) { printListing(file) } } diff --git a/packages/ipfs/src/cli/commands/files/mkdir.js b/packages/ipfs/src/cli/commands/files/mkdir.js index 56c8291c91..cfc18078fe 100644 --- a/packages/ipfs/src/cli/commands/files/mkdir.js +++ b/packages/ipfs/src/cli/commands/files/mkdir.js @@ -7,6 +7,7 @@ const { coerceMtime, coerceMtimeNsecs } = require('../../utils') +const parseDuration = require('parse-duration') module.exports = { command: 'mkdir ', @@ -59,23 +60,26 @@ module.exports = { type: 'number', coerce: coerceMtimeNsecs, describe: 'Modification time fraction in nanoseconds' + }, + timeout: { + type: 'string', + coerce: parseDuration } }, - handler (argv) { - const { - ctx: { ipfs }, - path, - parents, - cidVersion, - hashAlg, - flush, - shardSplitThreshold, - mode, - mtime, - mtimeNsecs - } = argv - + handler ({ + ctx: { ipfs }, + path, + parents, + cidVersion, + hashAlg, + flush, + shardSplitThreshold, + mode, + mtime, + mtimeNsecs, + timeout + }) { return ipfs.files.mkdir(path, { parents, cidVersion, @@ -83,7 +87,8 @@ module.exports = { flush, shardSplitThreshold, mode, - mtime: asMtimeFromSeconds(mtime, mtimeNsecs) + mtime: asMtimeFromSeconds(mtime, mtimeNsecs), + timeout }) } } diff --git a/packages/ipfs/src/cli/commands/files/mv.js b/packages/ipfs/src/cli/commands/files/mv.js index 6ea6217ac6..9add4cae6f 100644 --- a/packages/ipfs/src/cli/commands/files/mv.js +++ b/packages/ipfs/src/cli/commands/files/mv.js @@ -3,6 +3,7 @@ const { asBoolean } = require('../../utils') +const parseDuration = require('parse-duration') module.exports = { command: 'mv ', @@ -47,29 +48,33 @@ module.exports = { type: 'number', default: 1000, describe: 'If a directory has more links than this, it will be transformed into a hamt-sharded-directory' + }, + timeout: { + type: 'string', + coerce: parseDuration } }, - handler (argv) { - const { - ctx: { ipfs }, - source, - dest, - parents, - recursive, - cidVersion, - hashAlg, - flush, - shardSplitThreshold - } = argv - + handler ({ + ctx: { ipfs }, + source, + dest, + parents, + recursive, + cidVersion, + hashAlg, + flush, + shardSplitThreshold, + timeout + }) { return ipfs.files.mv(source, dest, { parents, recursive, cidVersion, hashAlg, flush, - shardSplitThreshold + shardSplitThreshold, + timeout }) } } diff --git a/packages/ipfs/src/cli/commands/files/read.js b/packages/ipfs/src/cli/commands/files/read.js index 9c3922ca80..e46a5ed176 100644 --- a/packages/ipfs/src/cli/commands/files/read.js +++ b/packages/ipfs/src/cli/commands/files/read.js @@ -1,5 +1,7 @@ 'use strict' +const parseDuration = require('parse-duration') + module.exports = { command: 'read ', @@ -15,20 +17,24 @@ module.exports = { alias: 'l', type: 'number', describe: 'Write only this number of bytes' + }, + timeout: { + type: 'string', + coerce: parseDuration } }, - async handler (argv) { - const { - ctx: { ipfs, print }, - path, - offset, - length - } = argv - + async handler ({ + ctx: { ipfs, print }, + path, + offset, + length, + timeout + }) { for await (const buffer of ipfs.files.read(path, { offset, - length + length, + timeout })) { print(buffer, false) } diff --git a/packages/ipfs/src/cli/commands/files/rm.js b/packages/ipfs/src/cli/commands/files/rm.js index c304c7cdc3..480d8e6cc6 100644 --- a/packages/ipfs/src/cli/commands/files/rm.js +++ b/packages/ipfs/src/cli/commands/files/rm.js @@ -3,6 +3,7 @@ const { asBoolean } = require('../../utils') +const parseDuration = require('parse-duration') module.exports = { command: 'rm ', @@ -16,18 +17,22 @@ module.exports = { default: false, coerce: asBoolean, describe: 'Remove directories recursively' + }, + timeout: { + type: 'string', + coerce: parseDuration } }, - handler (argv) { - const { - ctx: { ipfs }, - path, - recursive - } = argv - + handler ({ + ctx: { ipfs }, + path, + recursive, + timeout + }) { return ipfs.files.rm(path, { - recursive + recursive, + timeout }) } } diff --git a/packages/ipfs/src/cli/commands/files/stat.js b/packages/ipfs/src/cli/commands/files/stat.js index 7f588f5409..a4723891dc 100644 --- a/packages/ipfs/src/cli/commands/files/stat.js +++ b/packages/ipfs/src/cli/commands/files/stat.js @@ -5,6 +5,7 @@ const { } = require('../../utils') const formatMode = require('ipfs-core-utils/src/files/format-mode') const formatMtime = require('ipfs-core-utils/src/files/format-mtime') +const parseDuration = require('parse-duration') module.exports = { command: 'stat [path]', @@ -47,22 +48,26 @@ Mtime: `, }, 'cid-base': { describe: 'CID base to use.' + }, + timeout: { + type: 'string', + coerce: parseDuration } }, - handler (argv) { - const { - ctx: { ipfs, print }, - path, - format, - hash, - size, - withLocal, - cidBase - } = argv - + handler ({ + ctx: { ipfs, print }, + path, + format, + hash, + size, + withLocal, + cidBase, + timeout + }) { return ipfs.files.stat(path, { - withLocal + withLocal, + timeout }) .then((stats) => { if (hash) { diff --git a/packages/ipfs/src/cli/commands/files/touch.js b/packages/ipfs/src/cli/commands/files/touch.js index 871ece5433..7eb017a9a4 100644 --- a/packages/ipfs/src/cli/commands/files/touch.js +++ b/packages/ipfs/src/cli/commands/files/touch.js @@ -6,6 +6,7 @@ const { coerceMtime, coerceMtimeNsecs } = require('../../utils') +const parseDuration = require('parse-duration') module.exports = { command: 'touch [path]', @@ -47,27 +48,31 @@ module.exports = { type: 'number', default: 1000, describe: 'If a directory has more links than this, it will be transformed into a hamt-sharded-directory' + }, + timeout: { + type: 'string', + coerce: parseDuration } }, - handler (argv) { - const { - ctx: { ipfs }, - path, - flush, - cidVersion, - hashAlg, - shardSplitThreshold, - mtime, - mtimeNsecs - } = argv - + handler ({ + ctx: { ipfs }, + path, + flush, + cidVersion, + hashAlg, + shardSplitThreshold, + mtime, + mtimeNsecs, + timeout + }) { return ipfs.files.touch(path, { mtime: asMtimeFromSeconds(mtime, mtimeNsecs), flush, cidVersion, hashAlg, - shardSplitThreshold + shardSplitThreshold, + timeout }) } } diff --git a/packages/ipfs/src/cli/commands/files/write.js b/packages/ipfs/src/cli/commands/files/write.js index a30db31091..cb2213324e 100644 --- a/packages/ipfs/src/cli/commands/files/write.js +++ b/packages/ipfs/src/cli/commands/files/write.js @@ -7,6 +7,7 @@ const { coerceMtime, coerceMtimeNsecs } = require('../../utils') +const parseDuration = require('parse-duration') module.exports = { command: 'write ', @@ -99,31 +100,34 @@ module.exports = { type: 'number', coerce: coerceMtimeNsecs, describe: 'Modification time fraction in nanoseconds' + }, + timeout: { + type: 'string', + coerce: parseDuration } }, - async handler (argv) { - const { - ctx: { ipfs, getStdin }, - path, - offset, - length, - create, - truncate, - rawLeaves, - reduceSingleLeafToSelf, - cidVersion, - hashAlg, - parents, - progress, - strategy, - flush, - shardSplitThreshold, - mode, - mtime, - mtimeNsecs - } = argv - + async handler ({ + ctx: { ipfs, getStdin }, + path, + offset, + length, + create, + truncate, + rawLeaves, + reduceSingleLeafToSelf, + cidVersion, + hashAlg, + parents, + progress, + strategy, + flush, + shardSplitThreshold, + mode, + mtime, + mtimeNsecs, + timeout + }) { await ipfs.files.write(path, getStdin(), { offset, length, @@ -139,7 +143,8 @@ module.exports = { flush, shardSplitThreshold, mode, - mtime: asMtimeFromSeconds(mtime, mtimeNsecs) + mtime: asMtimeFromSeconds(mtime, mtimeNsecs), + timeout }) } } diff --git a/packages/ipfs/src/cli/commands/get.js b/packages/ipfs/src/cli/commands/get.js index 9279f14096..8a4a2b0493 100644 --- a/packages/ipfs/src/cli/commands/get.js +++ b/packages/ipfs/src/cli/commands/get.js @@ -5,6 +5,7 @@ const path = require('path') const toIterable = require('stream-to-it') const pipe = require('it-pipe') const { map } = require('streaming-iterables') +const parseDuration = require('parse-duration') module.exports = { command: 'get ', @@ -16,15 +17,19 @@ module.exports = { alias: 'o', type: 'string', default: process.cwd() + }, + timeout: { + type: 'string', + coerce: parseDuration } }, - async handler ({ ctx, ipfsPath, output }) { - const { ipfs, print } = ctx - + async handler ({ ctx: { ipfs, print }, ipfsPath, output, timeout }) { print(`Saving file(s) ${ipfsPath}`) - for await (const file of ipfs.get(ipfsPath)) { + for await (const file of ipfs.get(ipfsPath, { + timeout + })) { const fullFilePath = path.join(output, file.path) if (file.content) { diff --git a/packages/ipfs/src/cli/commands/id.js b/packages/ipfs/src/cli/commands/id.js index 11f10fdb40..bef5c472c4 100644 --- a/packages/ipfs/src/cli/commands/id.js +++ b/packages/ipfs/src/cli/commands/id.js @@ -1,5 +1,7 @@ 'use strict' +const parseDuration = require('parse-duration') + module.exports = { command: 'id', @@ -10,12 +12,17 @@ module.exports = { alias: 'f', type: 'string', describe: 'Print Node ID info in the given format. Allowed tokens: ' + }, + timeout: { + type: 'string', + coerce: parseDuration } }, - async handler ({ ctx, format }) { - const { ipfs, print } = ctx - const id = await ipfs.id() + async handler ({ ctx: { ipfs, print }, format, timeout }) { + const id = await ipfs.id({ + timeout + }) if (format) { print(format diff --git a/packages/ipfs/src/cli/commands/key/export.js b/packages/ipfs/src/cli/commands/key/export.js index 6f2f665271..3c65586be9 100644 --- a/packages/ipfs/src/cli/commands/key/export.js +++ b/packages/ipfs/src/cli/commands/key/export.js @@ -1,6 +1,7 @@ 'use strict' const fs = require('fs') +const parseDuration = require('parse-duration') module.exports = { command: 'export ', @@ -19,12 +20,18 @@ module.exports = { describe: 'Output file', type: 'string', default: 'stdout' + }, + timeout: { + type: 'string', + coerce: parseDuration } }, - async handler ({ ctx, name, passout, output }) { + async handler ({ ctx, name, passout, output, timeout }) { const { ipfs } = ctx - const pem = await ipfs.key.export(name, passout) + const pem = await ipfs.key.export(name, passout, { + timeout + }) if (output === 'stdout') { process.stdout.write(pem) } else { diff --git a/packages/ipfs/src/cli/commands/key/gen.js b/packages/ipfs/src/cli/commands/key/gen.js index c69db130b7..4f90f43bc4 100644 --- a/packages/ipfs/src/cli/commands/key/gen.js +++ b/packages/ipfs/src/cli/commands/key/gen.js @@ -1,5 +1,7 @@ 'use strict' +const parseDuration = require('parse-duration') + module.exports = { command: 'gen ', @@ -16,16 +18,19 @@ module.exports = { describe: 'size of the key to generate.', default: 2048, type: 'number' + }, + timeout: { + type: 'string', + coerce: parseDuration } }, - async handler (argv) { - const { ipfs, print } = argv.ctx - const opts = { - type: argv.type, - size: argv.size - } - const key = await ipfs.key.gen(argv.name, opts) + async handler ({ ctx: { ipfs, print }, name, type, size, timeout }) { + const key = await ipfs.key.gen(name, { + type, + size, + timeout + }) print(`generated ${key.id} ${key.name}`) } } diff --git a/packages/ipfs/src/cli/commands/key/import.js b/packages/ipfs/src/cli/commands/key/import.js index 7fb230f58d..724ed8f120 100644 --- a/packages/ipfs/src/cli/commands/key/import.js +++ b/packages/ipfs/src/cli/commands/key/import.js @@ -1,6 +1,7 @@ 'use strict' const fs = require('fs') +const parseDuration = require('parse-duration') module.exports = { command: 'import ', @@ -19,12 +20,17 @@ module.exports = { type: 'string', demandOption: true, coerce: ('input', input => fs.readFileSync(input, 'utf8')) + }, + timeout: { + type: 'string', + coerce: parseDuration } }, - async handler (argv) { - const { ipfs, print } = argv.ctx - const key = await ipfs.key.import(argv.name, argv.input, argv.passin) + async handler ({ ctx: { ipfs, print }, name, input, passin, timeout }) { + const key = await ipfs.key.import(name, input, passin, { + timeout + }) print(`imported ${key.id} ${key.name}`) } } diff --git a/packages/ipfs/src/cli/commands/key/list.js b/packages/ipfs/src/cli/commands/key/list.js index 5ad3b61247..063f73fbd5 100644 --- a/packages/ipfs/src/cli/commands/key/list.js +++ b/packages/ipfs/src/cli/commands/key/list.js @@ -1,13 +1,23 @@ 'use strict' +const parseDuration = require('parse-duration') + module.exports = { command: 'list', describe: 'List all local keys', - async handler (argv) { - const { ipfs, print } = argv.ctx - const keys = await ipfs.key.list() + builder: { + timeout: { + type: 'string', + coerce: parseDuration + } + }, + + async handler ({ ctx: { ipfs, print }, timeout }) { + const keys = await ipfs.key.list({ + timeout + }) keys.forEach((ki) => print(`${ki.id} ${ki.name}`)) } } diff --git a/packages/ipfs/src/cli/commands/key/rename.js b/packages/ipfs/src/cli/commands/key/rename.js index 471cee1d74..8eb31a46ca 100644 --- a/packages/ipfs/src/cli/commands/key/rename.js +++ b/packages/ipfs/src/cli/commands/key/rename.js @@ -1,13 +1,23 @@ 'use strict' +const parseDuration = require('parse-duration') + module.exports = { command: 'rename ', describe: 'Rename a key', - async handler (argv) { - const { ipfs, print } = argv.ctx - const res = await ipfs.key.rename(argv.name, argv.newName) + builder: { + timeout: { + type: 'string', + coerce: parseDuration + } + }, + + async handler ({ ctx: { ipfs, print }, name, newName, timeout }) { + const res = await ipfs.key.rename(name, newName, { + timeout + }) print(`renamed to ${res.id} ${res.now}`) } } diff --git a/packages/ipfs/src/cli/commands/key/rm.js b/packages/ipfs/src/cli/commands/key/rm.js index 46a0fd28cf..65e7c5e908 100644 --- a/packages/ipfs/src/cli/commands/key/rm.js +++ b/packages/ipfs/src/cli/commands/key/rm.js @@ -1,13 +1,23 @@ 'use strict' +const parseDuration = require('parse-duration') + module.exports = { command: 'rm ', describe: 'Remove a key', - async handler (argv) { - const { ipfs, print } = argv.ctx - const key = await ipfs.key.rm(argv.name) + builder: { + timeout: { + type: 'string', + coerce: parseDuration + } + }, + + async handler ({ ctx: { ipfs, print }, name, timeout }) { + const key = await ipfs.key.rm(name, { + timeout + }) print(`${key.id} ${key.name}`) } } diff --git a/packages/ipfs/src/cli/commands/ls.js b/packages/ipfs/src/cli/commands/ls.js index 353bc9d594..330030b7f2 100644 --- a/packages/ipfs/src/cli/commands/ls.js +++ b/packages/ipfs/src/cli/commands/ls.js @@ -5,6 +5,7 @@ const { rightpad } = require('../utils') const { cidToString } = require('../../utils/cid') const formatMode = require('ipfs-core-utils/src/files/format-mode') const formatMtime = require('ipfs-core-utils/src/files/format-mtime') +const parseDuration = require('parse-duration') module.exports = { command: 'ls ', @@ -33,12 +34,14 @@ module.exports = { describe: 'Number base to display CIDs in.', type: 'string', choices: multibase.names + }, + timeout: { + type: 'string', + coerce: parseDuration } }, - async handler ({ ctx, key, recursive, headers, cidBase }) { - const { ipfs, print } = ctx - + async handler ({ ctx: { ipfs, print }, key, recursive, headers, cidBase, timeout }) { // replace multiple slashes key = key.replace(/\/(\/+)/g, '/') @@ -74,7 +77,7 @@ module.exports = { ) } - for await (const link of ipfs.ls(key, { recursive })) { + for await (const link of ipfs.ls(key, { recursive, timeout })) { const mode = formatMode(link.mode, link.type === 'dir') const mtime = formatMtime(link.mtime) const cid = cidToString(link.cid, { base: cidBase }) diff --git a/packages/ipfs/src/cli/commands/name/publish.js b/packages/ipfs/src/cli/commands/name/publish.js index ddc09bf6b5..a8f82c6dca 100644 --- a/packages/ipfs/src/cli/commands/name/publish.js +++ b/packages/ipfs/src/cli/commands/name/publish.js @@ -1,5 +1,7 @@ 'use strict' +const parseDuration = require('parse-duration') + module.exports = { command: 'publish ', @@ -28,12 +30,21 @@ module.exports = { describe: 'Time duration this record should be cached for (caution: experimental).', default: '', type: 'string' + }, + timeout: { + type: 'string', + coerce: parseDuration } }, - async handler ({ ctx, ipfsPath, resolve, lifetime, key, ttl }) { - const { ipfs, print } = ctx - const result = await ipfs.name.publish(ipfsPath, { resolve, lifetime, key, ttl }) + async handler ({ ctx: { ipfs, print }, ipfsPath, resolve, lifetime, key, ttl, timeout }) { + const result = await ipfs.name.publish(ipfsPath, { + resolve, + lifetime, + key, + ttl, + timeout + }) print(`Published to ${result.name}: ${result.value}`) } } diff --git a/packages/ipfs/src/cli/commands/name/pubsub/cancel.js b/packages/ipfs/src/cli/commands/name/pubsub/cancel.js index 20c0d165ee..29da84b925 100644 --- a/packages/ipfs/src/cli/commands/name/pubsub/cancel.js +++ b/packages/ipfs/src/cli/commands/name/pubsub/cancel.js @@ -1,13 +1,23 @@ 'use strict' +const parseDuration = require('parse-duration') + module.exports = { command: 'cancel ', describe: 'Cancel a name subscription.', - async handler (argv) { - const { ipfs, print } = argv.ctx - const result = await ipfs.name.pubsub.cancel(argv.name) + builder: { + timeout: { + type: 'string', + coerce: parseDuration + } + }, + + async handler ({ ctx: { ipfs, print }, name, timeout }) { + const result = await ipfs.name.pubsub.cancel(name, { + timeout + }) print(result.canceled ? 'canceled' : 'no subscription') } } diff --git a/packages/ipfs/src/cli/commands/name/pubsub/state.js b/packages/ipfs/src/cli/commands/name/pubsub/state.js index 7e09c65d97..ef08aed8fb 100644 --- a/packages/ipfs/src/cli/commands/name/pubsub/state.js +++ b/packages/ipfs/src/cli/commands/name/pubsub/state.js @@ -1,13 +1,23 @@ 'use strict' +const parseDuration = require('parse-duration') + module.exports = { command: 'state', describe: 'Query the state of IPNS pubsub.', - async handler (argv) { - const { ipfs, print } = argv.ctx - const result = await ipfs.name.pubsub.state() + builder: { + timeout: { + type: 'string', + coerce: parseDuration + } + }, + + async handler ({ ctx: { ipfs, print }, timeout }) { + const result = await ipfs.name.pubsub.state({ + timeout + }) print(result.enabled ? 'enabled' : 'disabled') } } diff --git a/packages/ipfs/src/cli/commands/name/pubsub/subs.js b/packages/ipfs/src/cli/commands/name/pubsub/subs.js index 76ddcbee72..c5b77000d6 100644 --- a/packages/ipfs/src/cli/commands/name/pubsub/subs.js +++ b/packages/ipfs/src/cli/commands/name/pubsub/subs.js @@ -1,13 +1,23 @@ 'use strict' +const parseDuration = require('parse-duration') + module.exports = { command: 'subs', describe: 'Show current name subscriptions.', - async handler (argv) { - const { ipfs, print } = argv.ctx - const result = await ipfs.name.pubsub.subs() + builder: { + timeout: { + type: 'string', + coerce: parseDuration + } + }, + + async handler ({ ctx: { ipfs, print }, timeout }) { + const result = await ipfs.name.pubsub.subs({ + timeout + }) result.forEach(s => print(s)) } } diff --git a/packages/ipfs/src/cli/commands/name/resolve.js b/packages/ipfs/src/cli/commands/name/resolve.js index e16d8b19db..4affef1f2a 100644 --- a/packages/ipfs/src/cli/commands/name/resolve.js +++ b/packages/ipfs/src/cli/commands/name/resolve.js @@ -1,5 +1,7 @@ 'use strict' +const parseDuration = require('parse-duration') + module.exports = { command: 'resolve []', @@ -23,14 +25,17 @@ module.exports = { alias: 's', describe: 'Stream entries as they are found.', default: false + }, + timeout: { + type: 'string', + coerce: parseDuration } }, - async handler ({ ctx, nocache, recursive, name, stream }) { - const { ipfs, print } = ctx + async handler ({ ctx: { ipfs, print }, nocache, recursive, name, stream, timeout }) { let bestValue - for await (const value of ipfs.name.resolve(name, { nocache, recursive })) { + for await (const value of ipfs.name.resolve(name, { nocache, recursive, timeout })) { bestValue = value if (stream) print(value) } diff --git a/packages/ipfs/src/cli/commands/object/data.js b/packages/ipfs/src/cli/commands/object/data.js index 92424d87f5..e28c3b61bb 100644 --- a/packages/ipfs/src/cli/commands/object/data.js +++ b/packages/ipfs/src/cli/commands/object/data.js @@ -1,13 +1,21 @@ 'use strict' +const parseDuration = require('parse-duration') + module.exports = { command: 'data ', describe: 'Outputs the raw bytes in an IPFS object', - async handler (argv) { - const { ipfs, print } = argv.ctx - const data = await ipfs.object.data(argv.key, { enc: 'base58' }) + builder: { + timeout: { + type: 'string', + coerce: parseDuration + } + }, + + async handler ({ ctx: { ipfs, print }, key, timeout }) { + const data = await ipfs.object.data(key, { enc: 'base58', timeout }) print(data, false) } } diff --git a/packages/ipfs/src/cli/commands/object/get.js b/packages/ipfs/src/cli/commands/object/get.js index e01c82d543..d1f5b70c0a 100644 --- a/packages/ipfs/src/cli/commands/object/get.js +++ b/packages/ipfs/src/cli/commands/object/get.js @@ -2,6 +2,7 @@ const multibase = require('multibase') const { cidToString } = require('../../../utils/cid') +const parseDuration = require('parse-duration') const { Buffer } = require('buffer') module.exports = { @@ -18,12 +19,15 @@ module.exports = { describe: 'Number base to display CIDs in. Note: specifying a CID base for v0 CIDs will have no effect.', type: 'string', choices: multibase.names + }, + timeout: { + type: 'string', + coerce: parseDuration } }, - async handler ({ ctx, key, dataEncoding, cidBase }) { - const { ipfs, print } = ctx - const node = await ipfs.object.get(key, { enc: 'base58' }) + async handler ({ ctx: { ipfs, print }, key, dataEncoding, cidBase, timeout }) { + const node = await ipfs.object.get(key, { enc: 'base58', timeout }) let data = node.Data || '' if (Buffer.isBuffer(data)) { diff --git a/packages/ipfs/src/cli/commands/object/links.js b/packages/ipfs/src/cli/commands/object/links.js index 0d85900022..d2704b489b 100644 --- a/packages/ipfs/src/cli/commands/object/links.js +++ b/packages/ipfs/src/cli/commands/object/links.js @@ -2,6 +2,7 @@ const multibase = require('multibase') const { cidToString } = require('../../../utils/cid') +const parseDuration = require('parse-duration') module.exports = { command: 'links ', @@ -13,12 +14,15 @@ module.exports = { describe: 'Number base to display CIDs in. Note: specifying a CID base for v0 CIDs will have no effect.', type: 'string', choices: multibase.names + }, + timeout: { + type: 'string', + coerce: parseDuration } }, - async handler ({ ctx, key, cidBase }) { - const { ipfs, print } = ctx - const links = await ipfs.object.links(key, { enc: 'base58' }) + async handler ({ ctx: { ipfs, print }, key, cidBase, timeout }) { + const links = await ipfs.object.links(key, { enc: 'base58', timeout }) links.forEach((link) => { const cidStr = cidToString(link.Hash, { base: cidBase, upgrade: false }) diff --git a/packages/ipfs/src/cli/commands/object/new.js b/packages/ipfs/src/cli/commands/object/new.js index c010acca2a..f03a1dc2da 100644 --- a/packages/ipfs/src/cli/commands/object/new.js +++ b/packages/ipfs/src/cli/commands/object/new.js @@ -2,6 +2,7 @@ const multibase = require('multibase') const { cidToString } = require('../../../utils/cid') +const parseDuration = require('parse-duration') module.exports = { command: 'new [