[
  {
    "path": ".aegir.js",
    "content": "'use strict'\n\nconst createServer = require('ipfsd-ctl').createServer\nconst EchoServer = require('interface-ipfs-core/src/utils/echo-http-server')\nconst server = createServer({\n  host: '127.0.0.1',\n  port: 43134\n}, {\n  type: 'go',\n  ipfsHttpModule: require('./'),\n  ipfsBin: require('go-ipfs-dep').path()\n})\nconst echoServer = EchoServer.createServer()\n\nmodule.exports = {\n  bundlesize: { maxSize: '90kB' },\n  webpack: {\n    resolve: {\n      mainFields: ['browser', 'main']\n    }\n  },\n  karma: {\n    files: [{\n      pattern: 'node_modules/interface-ipfs-core/test/fixtures/**/*',\n      watched: false,\n      served: true,\n      included: false\n    }],\n    browserNoActivityTimeout: 210 * 1000,\n    singleRun: true\n  },\n  hooks: {\n    node: {\n      pre: () => echoServer.start(),\n      post: () => echoServer.stop()\n    },\n    browser: {\n      pre: () => {\n        return Promise.all([\n          server.start(),\n          echoServer.start()\n        ])\n      },\n      post: () => {\n        return Promise.all([\n          server.stop(),\n          echoServer.stop()\n        ])\n      }\n    }\n  }\n}\n"
  },
  {
    "path": ".gitattributes",
    "content": "* text=auto\ntest/fixtures/** text eol=lf\n"
  },
  {
    "path": ".gitignore",
    "content": "package-lock.json\nyarn.lock\ndocs\n\n**/node_modules\n**/*.log\ntest/setup/tmp-disposable-nodes-addrs.json\ndist\ncoverage\n.nyc_output\n**/*.swp\nexamples/sub-module/**/bundle.js\nexamples/sub-module/**/*-minified.js\nexamples/sub-module/*-bundle.js\n"
  },
  {
    "path": ".travis.yml",
    "content": "language: node_js\ncache: npm\n\nbranches:\n  only:\n  - master\n  - /^release\\/.*$/\n\nstages:\n  - check\n  - test\n  - cov\n\nnode_js:\n  - '12'\n  - '10'\n\nos:\n  - linux\n  - osx\n  - windows\n\nscript: npx nyc -s npm run test:node -- --bail\nafter_success: npx nyc report --reporter=text-lcov > coverage.lcov && npx codecov\n\njobs:\n  include:\n    - stage: check\n      script:\n        - npx aegir build --bundlesize\n        - npx aegir dependency-check\n        - npm run lint\n\n    - stage: test\n      name: chrome\n      addons:\n        chrome: stable\n      script: npx aegir test -t browser\n\n    - stage: test\n      name: chrome webworker\n      addons:\n        chrome: stable\n      script: npx aegir test -t webworker\n\n    - stage: test\n      name: firefox\n      addons:\n        firefox: latest\n      script: npx aegir test -t browser -- --browsers FirefoxHeadless\n\n    - stage: test\n      name: firefox webworker\n      addons:\n        firefox: latest\n      script: npx aegir test -t webworker -- --browsers FirefoxHeadless\n\n    - stage: test\n      name: electron-main\n      os: osx\n      script:\n        - npx aegir test -t electron-main --bail\n\n    - stage: test\n      name: electron-renderer\n      os: osx\n      script:\n        - npx aegir test -t electron-renderer --bail\n\nnotifications:\n  email: false\n"
  },
  {
    "path": "CHANGELOG.md",
    "content": "<a name=\"42.0.0\"></a>\n# [42.0.0](https://github.com/ipfs/js-ipfs-http-client/compare/v42.0.0-pre.2...v42.0.0) (2020-02-04)\n\nThere are significant and breaking API changes in this release. Please see the [migration guide](https://gist.github.com/alanshaw/04b2ddc35a6fff25c040c011ac6acf26).\n\n### Bug Fixes\n\n* interface tests ([#1233](https://github.com/ipfs/js-ipfs-http-client/issues/1233)) ([d3eee0d](https://github.com/ipfs/js-ipfs-http-client/commit/d3eee0d))\n\n### Features\n\n* `add` results now include `mode` and `mtime` properties if they were set.\n\n* `files.chmod` has been added. See the [core interface docs](https://github.com/ipfs/interface-js-ipfs-core/blob/master/SPEC/FILES.md#fileschmod) for info.\n\n*  `files.flush` now returns the root CID for the path that was flushed (`/` by default)\n\n* `files.ls` results now include `mode` and `mtime` properties if they were set. See the [core interface docs](https://github.com/ipfs/interface-js-ipfs-core/blob/master/SPEC/FILES.md#ls) for more info.\n\n* `files.mkdir` now accepts `mode` and `mtime` options to allow setting mode and mtime metadata. See the [core interface docs](https://github.com/ipfs/interface-js-ipfs-core/blob/master/SPEC/FILES.md#filesmkdir) for more info.\n\n* `files.stat` result now includes `mode` and `mtime` properties if they were set. See the [core interface docs](https://github.com/ipfs/interface-js-ipfs-core/blob/master/SPEC/FILES.md#filesstat) for more info.\n\n* `files.touch` has been added. See the [core interface docs](https://github.com/ipfs/interface-js-ipfs-core/blob/master/SPEC/FILES.md#filestouch) for info.\n\n* `files.write` now accepts `mode` and `mtime` options to allow setting mode and mtime metadata. See the [core interface docs](https://github.com/ipfs/interface-js-ipfs-core/blob/master/SPEC/FILES.md#fileswrite) for more info.\n\n* `object.get` now accepts a `timeout` option. It will cause the method to throw with a `TimeoutError` if no data is received within the timeout window. It can be passed as a `number` or a `string`. If a `number` is passed it is interpreted as milliseconds, if a string is passed it is interpreted as a [human readable duration](https://www.npmjs.com/package/parse-duration).\n\n* `pin.add` now accepts a `timeout` option. It will cause the method to throw with a `TimeoutError` if no data is received within the timeout window. It can be passed as a `number` or a `string`. If a `number` is passed it is interpreted as milliseconds, if a string is passed it is interpreted as a [human readable duration](https://www.npmjs.com/package/parse-duration).\n\n* `refs` now accepts a `timeout` option. It will cause the method to throw with a `TimeoutError` if no data is received within the timeout window. It can be passed as a `number` or a `string`. If a `number` is passed it is interpreted as milliseconds, if a string is passed it is interpreted as a [human readable duration](https://www.npmjs.com/package/parse-duration).\n\n### BREAKING CHANGES\n\n* Callbacks are no longer supported on any API methods. Please use a utility such as [`callbackify`](https://www.npmjs.com/package/callbackify) on API methods that return Promises to emulate previous behaviour. See the [migration guide](https://gist.github.com/alanshaw/04b2ddc35a6fff25c040c011ac6acf26#migrating-from-callbacks) for more info.\n\n* `add` now returns an async iterable.\n\n* `add` now accepts `mode` and `mtime` options on inputs to allow setting mode and mtime metadata for added files. See the [core interface docs](https://github.com/ipfs/interface-js-ipfs-core/blob/master/SPEC/FILES.md#add) for more info.\n\n* `add` results now contain a `cid` property (a [CID instance](https://github.com/multiformats/js-cid)) instead of a string `hash` property.\n\n* `addReadableStream`, `addPullStream` have been removed. Please see the [migration guide](https://gist.github.com/alanshaw/04b2ddc35a6fff25c040c011ac6acf26#migrating-to-async-iterables) for more info.\n\n* `addFromStream` has been removed. Use `add` instead.\n\n* `addFromFs` has been removed. Please use the exported `globSource` utility and pass the result to `add`. See the [glob source documentation](https://github.com/ipfs/js-ipfs-http-client#glob-source) for more details and an example.\n\n* `addFromURL` has been removed. Please use the exported `urlSource` utility and pass the result to `add`. See the [URL source documentation](https://github.com/ipfs/js-ipfs-http-client#url-source) for more details and an example.\n\n* `bitswap.stat` result has changed - `wantlist` and values are now an array of [CID](https://github.com/multiformats/js-cid) instances and `peers` is now a `string[]` of peer IDs.\n\n* `bitswap.wantlist` now returns an array of [CID](https://github.com/multiformats/js-cid) instances.\n\n* `block.rm` now returns an async iterable.\n\n* `block.rm` now yields objects of `{ cid: CID, error: Error }`.\n\n* `block.stat` result now contains a `cid` property (whose value is a [CID instance](https://github.com/multiformats/js-cid)) instead of a `key` property.\n\n* `dht.findProvs`, `dht.provide`, `dht.put` and `dht.query` now all return an async iterable.\n\n* `dht.findPeer`, `dht.findProvs`, `dht.provide`, `dht.put` and `dht.query` now yield/return an object `{ id: string, addrs: Multiaddr[] }` instead of a `PeerInfo` instance(s).\n\n* `files.lsPullStream` and `files.lsReadableStream` have been removed. Please see the [migration guide](https://gist.github.com/alanshaw/04b2ddc35a6fff25c040c011ac6acf26#migrating-to-async-iterables) for more info.\n\n* `files.ls` now returns an async iterable.\n\n* `files.ls` results now contain a `cid` property (whose value is a [CID instance](https://github.com/multiformats/js-cid)) instead of a `hash` property.\n\n* `files.ls` no longer takes a `long` option (in core) - you will receive all data by default.\n\n* `files.readPullStream` and `files.readReadableStream` have been removed. Please see the [migration guide](https://gist.github.com/alanshaw/04b2ddc35a6fff25c040c011ac6acf26#migrating-to-async-iterables) for more info.\n\n* `files.read` now returns an async iterable.\n\n* `files.stat` result now contains a `cid` property (whose value is a [CID instance](https://github.com/multiformats/js-cid)) instead of a `hash` property.\n\n* `get` now returns an async iterable. The `content` property value for objects yielded from the iterator is now an async iterable that yields [`BufferList`](https://github.com/rvagg/bl) objects.\n\n* `id` result has changed, the `addresses` property is now a `Multiaddr[]`\n\n* `name.resolve` now returns an async iterable. It yields increasingly more accurate resolved values as they are discovered until the best value is selected from the quorum of 16. The \"best\" resolved value is the last item yielded from the iterator. If you are interested only in this best value you could use `it-last` to extract it like so:\n\n    ```js\n    const last = require('it-last')\n    await last(ipfs.name.resolve('/ipns/QmHash'))\n    ```\n\n* `ls` now returns an async iterable.\n\n* `ls` results now contain a `cid` property (whose value is a [CID instance](https://github.com/multiformats/js-cid)) instead of a `hash` property.\n\n* `ls` results now include `mode` and `mtime` properties if they were set. See the [core interface docs](https://github.com/ipfs/interface-js-ipfs-core/blob/master/SPEC/FILES.md#ls) for more info.\n\n* `pin.add` results now contain a `cid` property (a [CID instance](https://github.com/multiformats/js-cid)) instead of a string `hash` property.\n\n* `pin.ls` now returns an async iterable.\n\n* `pin.ls` results now contain a `cid` property (a [CID instance](https://github.com/multiformats/js-cid)) instead of a string `hash` property.\n\n* `pin.rm` results now contain a `cid` property (a [CID instance](https://github.com/multiformats/js-cid)) instead of a string `hash` property.\n\n* `ping` now returns an async iterable.\n\n* `refs` and `refs.local` now return an async iterable.\n\n* `repo.gc` now returns an async iterable.\n\n* `stats.bw` now returns an async iterable.\n\n* `swarm.peers` now returns an array of objects with a `peer` property that is a `string`, instead of a `PeerId` instance.\n\n* `swarm.addrs` now returns an array of objects `{ id: string, addrs: Multiaddr[] }` instead of `PeerInfo` instances.\n\n* The protocol _name_ for peer IDs in multiaddrs has changed from 'ipfs' to 'p2p'. There's no changes to data on the wire but this change is seen when multiaddrs are converted to strings.\n\n\n\n<a name=\"42.0.0-pre.0\"></a>\n# [42.0.0-pre.0](https://github.com/ipfs/js-ipfs-http-client/compare/v41.0.1...v42.0.0-pre.0) (2020-01-23)\n\n\n\n<a name=\"41.0.1\"></a>\n## [41.0.1](https://github.com/ipfs/js-ipfs-http-client/compare/v41.0.0...v41.0.1) (2020-01-23)\n\n\n\n<a name=\"41.0.0\"></a>\n# [41.0.0](https://github.com/ipfs/js-ipfs-http-client/compare/v40.2.1...v41.0.0) (2020-01-12)\n\n\n### Bug Fixes\n\n* return CIDs from files.flush ([#1216](https://github.com/ipfs/js-ipfs-http-client/issues/1216)) ([13f8d7a](https://github.com/ipfs/js-ipfs-http-client/commit/13f8d7a))\n\n\n### Code Refactoring\n\n* removes format option ([#1218](https://github.com/ipfs/js-ipfs-http-client/issues/1218)) ([4ef26cd](https://github.com/ipfs/js-ipfs-http-client/commit/4ef26cd))\n\n\n### BREAKING CHANGES\n\n* `format` option is no longer supported as everything is `dag-pb` all\nof the time.\n\nFollows on from https://github.com/ipfs/js-ipfs-mfs/pull/69\n\n\n\n<a name=\"40.2.1\"></a>\n## [40.2.1](https://github.com/ipfs/js-ipfs-http-client/compare/v40.2.0...v40.2.1) (2020-01-09)\n\n\n\n<a name=\"40.2.0\"></a>\n# [40.2.0](https://github.com/ipfs/js-ipfs-http-client/compare/v40.1.0...v40.2.0) (2020-01-09)\n\n\n### Features\n\n* support UnixFSv1.5 metadata ([#1186](https://github.com/ipfs/js-ipfs-http-client/issues/1186)) ([da9d17a](https://github.com/ipfs/js-ipfs-http-client/commit/da9d17a))\n\n\n\n<a name=\"40.1.0\"></a>\n# [40.1.0](https://github.com/ipfs/js-ipfs-http-client/compare/v40.0.1...v40.1.0) (2019-12-10)\n\n\n### Features\n\n* expose import concurrency controls ([#1187](https://github.com/ipfs/js-ipfs-http-client/issues/1187)) ([47093d5](https://github.com/ipfs/js-ipfs-http-client/commit/47093d5))\n\n\n\n<a name=\"40.0.1\"></a>\n## [40.0.1](https://github.com/ipfs/js-ipfs-http-client/compare/v40.0.0...v40.0.1) (2019-11-27)\n\n\n### Bug Fixes\n\n* pin ls with multiple CIDs ([#1184](https://github.com/ipfs/js-ipfs-http-client/issues/1184)) ([2f3763f](https://github.com/ipfs/js-ipfs-http-client/commit/2f3763f))\n\n\n\n<a name=\"40.0.0\"></a>\n# [40.0.0](https://github.com/ipfs/js-ipfs-http-client/compare/v39.0.2...v40.0.0) (2019-11-22)\n\n\n### Code Refactoring\n\n* async await roundup ([#1173](https://github.com/ipfs/js-ipfs-http-client/issues/1173)) ([3e5967a](https://github.com/ipfs/js-ipfs-http-client/commit/3e5967a)), closes [#1103](https://github.com/ipfs/js-ipfs-http-client/issues/1103)\n* convert config API to async await ([#1155](https://github.com/ipfs/js-ipfs-http-client/issues/1155)) ([621973c](https://github.com/ipfs/js-ipfs-http-client/commit/621973c))\n* move files to root level ([#1150](https://github.com/ipfs/js-ipfs-http-client/issues/1150)) ([559a97d](https://github.com/ipfs/js-ipfs-http-client/commit/559a97d))\n\n\n### Features\n\n* support name.resolve of peerid as cid ([#1145](https://github.com/ipfs/js-ipfs-http-client/issues/1145)) ([2d9afc8](https://github.com/ipfs/js-ipfs-http-client/commit/2d9afc8))\n\n\n### Reverts\n\n* chore: update multiaddr to version 7.2.0 ([#1136](https://github.com/ipfs/js-ipfs-http-client/issues/1136)) ([#1143](https://github.com/ipfs/js-ipfs-http-client/issues/1143)) ([4131d09](https://github.com/ipfs/js-ipfs-http-client/commit/4131d09))\n\n\n### BREAKING CHANGES\n\n* The `log.tail` method now returns an async iterator that yields log messages. Use it like:\n    ```js\n    for await (const message of ipfs.log.tail()) {\n      console.log(message)\n    }\n    ```\n* The response to a call to `log.level` now returns an object that has camel cased keys. i.e. `Message` and `Error` properties have changed to `message` and `error`.\n* Dropped support for go-ipfs <= 0.4.4 in `swarm.peers` response.\n* The signature for `ipfs.mount` has changed from `ipfs.mount([ipfsPath], [ipnsPath])` to `ipfs.mount([options])`. Where `options` is an optional object that may contain two boolean properties `ipfsPath` and `ipnsPath`. The response object has also changed to be camel case. See https://docs.ipfs.io/reference/api/http/#api-v0-mount.\n* Default ping `count` of 1 in client has been removed. The default ping count is now whatever the IPFS node defaults it to (currently 10). If you specifically need 1 ping message then please pass `count: 1` in options for `ipfs.ping()`.\n* Multi parameter constructor options are no longer supported. To create a new IPFS HTTP client, pass a single parameter to the constructor. The parameter can be one of:\n    * String, formatted as one of:\n        * Multiaddr e.g. /ip4/127.0.0.1/tcp/5001\n        * URL e.g. http://127.0.0.1:5001\n    * [Multiaddr](https://www.npmjs.com/package/multiaddr) instance\n    * Object, in format of either:\n        * Address and path e.g. `{ apiAddr: '/ip4/127.0.0.1/tcp/5001': apiPath: '/api/v0' }` (Note: `apiAddr` can also be a string in URL form or a Multiaddr instance)\n        * Node.js style address e.g. `{ host: '127.0.0.1', port: 5001, protocol: 'http' }`\n* Errors returned from request failures are now all [`HTTPError`](https://github.com/sindresorhus/ky/blob/c0d9d2bb07e4c122a08f019b39e9c55a4c9324f3/index.js#L117-L123)s which carry a `response` property. This is a [`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response) that can be used to inspect _all_ information relating to the HTTP response. This means that the `err.status` or `err.statusCode` property should now be accessed via `err.response.status`.\n* files in `src/files-regular` have moved to `src`. The `src/files-mfs` directory has been renamed to `src/files`. If you were previously requiring files from these directories e.g. `require('ipfs-http-client/src/files-regular/add')` then please be aware that they have moved.\n* Kebab case options are no longer supported. Please use camel case option names as defined in the [`interface-ipfs-core`](https://github.com/ipfs/interface-js-ipfs-core/tree/master/SPEC) docs. e.g. the `allow-offline` option to `name.publish` should be passed as `allowOffline`.\n  * Note that you can pass [additional query string parameters](https://github.com/ipfs/js-ipfs-http-client#additional-options) in the `searchParams` option available to all API methods.\n\n\n\n<a name=\"39.0.2\"></a>\n## [39.0.2](https://github.com/ipfs/js-ipfs-http-client/compare/v39.0.1...v39.0.2) (2019-10-23)\n\n\n### Bug Fixes\n\n* use non-strict equivalence for options.preload ([#1134](https://github.com/ipfs/js-ipfs-http-client/issues/1134)) ([432e1e8](https://github.com/ipfs/js-ipfs-http-client/commit/432e1e8))\n\n\n\n<a name=\"39.0.1\"></a>\n## [39.0.1](https://github.com/ipfs/js-ipfs-http-client/compare/v39.0.0...v39.0.1) (2019-10-21)\n\n\n### Bug Fixes\n\n* expose preload argument ([#1129](https://github.com/ipfs/js-ipfs-http-client/issues/1129)) ([c82b031](https://github.com/ipfs/js-ipfs-http-client/commit/c82b031))\n* increase default timeout and respect value passed to `ky.extend` ([#1130](https://github.com/ipfs/js-ipfs-http-client/issues/1130)) ([25b6043](https://github.com/ipfs/js-ipfs-http-client/commit/25b6043))\n\n\n\n<a name=\"39.0.0\"></a>\n# [39.0.0](https://github.com/ipfs/js-ipfs-http-client/compare/v38.2.0...v39.0.0) (2019-10-15)\n\n\n\n<a name=\"38.2.0\"></a>\n# [38.2.0](https://github.com/ipfs/js-ipfs-http-client/compare/v38.1.0...v38.2.0) (2019-10-06)\n\n\n### Features\n\n* adds ipfs.block.rm method ([#1123](https://github.com/ipfs/js-ipfs-http-client/issues/1123)) ([2f0eff7](https://github.com/ipfs/js-ipfs-http-client/commit/2f0eff7))\n\n\n\n<a name=\"38.1.0\"></a>\n# [38.1.0](https://github.com/ipfs/js-ipfs-http-client/compare/v38.0.1...v38.1.0) (2019-10-04)\n\n\n### Bug Fixes\n\n* get correct remote node config ([5b53e22](https://github.com/ipfs/js-ipfs-http-client/commit/5b53e22))\n* pull in preconfigured chai from interface tests ([93765c1](https://github.com/ipfs/js-ipfs-http-client/commit/93765c1))\n\n\n### Features\n\n* add methods for listing config profiles ([1c3d92a](https://github.com/ipfs/js-ipfs-http-client/commit/1c3d92a))\n\n\n### BREAKING CHANGES\n\n* Configuration profiles API has changed:\n    ```javascript\n    Promise<{oldCfg, newCfg}> ipfs.config.profile(name, opts)\n\n    // is now\n    Promise<{old, new}> ipfs.config.profiles.apply(name, opts)\n    ```\n\n* Possibly contentious; Adds `callbackify` as a dependency, see https://github.com/ipfs/js-ipfs/issues/2506\nfor discussion.\n\n\n\n<a name=\"38.0.1\"></a>\n## [38.0.1](https://github.com/ipfs/js-ipfs-http-client/compare/v38.0.0...v38.0.1) (2019-10-04)\n\n\n### Bug Fixes\n\n* pull in preconfigured chai from interface tests ([6a7eb8a](https://github.com/ipfs/js-ipfs-http-client/commit/6a7eb8a))\n\n\n\n<a name=\"38.0.0\"></a>\n# [38.0.0](https://github.com/ipfs/js-ipfs-http-client/compare/v37.0.3...v38.0.0) (2019-09-25)\n\n\n\n<a name=\"37.0.3\"></a>\n## [37.0.3](https://github.com/ipfs/js-ipfs-http-client/compare/v37.0.2...v37.0.3) (2019-09-25)\n\n\n\n<a name=\"37.0.2\"></a>\n## [37.0.2](https://github.com/ipfs/js-ipfs-http-client/compare/v37.0.1...v37.0.2) (2019-09-20)\n\n\n### Bug Fixes\n\n* only do the big file workaround in node and electron main ([077c997](https://github.com/ipfs/js-ipfs-http-client/commit/077c997))\n\n\n\n<a name=\"37.0.1\"></a>\n## [37.0.1](https://github.com/ipfs/js-ipfs-http-client/compare/v37.0.0...v37.0.1) (2019-09-17)\n\n\n\n<a name=\"37.0.0\"></a>\n# [37.0.0](https://github.com/ipfs/js-ipfs-http-client/compare/v36.1.0...v37.0.0) (2019-09-17)\n\n\n### Bug Fixes\n\n* big downloads in electron ([9c9aac8](https://github.com/ipfs/js-ipfs-http-client/commit/9c9aac8))\n\n\n\n<a name=\"36.1.0\"></a>\n# [36.1.0](https://github.com/ipfs/js-ipfs-http-client/compare/v36.0.0...v36.1.0) (2019-09-17)\n\n\n### Bug Fixes\n\n* fix electron renderer tests and a couple more bugs ([#1105](https://github.com/ipfs/js-ipfs-http-client/issues/1105)) ([a631a21](https://github.com/ipfs/js-ipfs-http-client/commit/a631a21))\n\n\n\n<a name=\"36.0.0\"></a>\n# [36.0.0](https://github.com/ipfs/js-ipfs-http-client/compare/v35.1.0...v36.0.0) (2019-09-11)\n\n\n\n<a name=\"35.1.0\"></a>\n# [35.1.0](https://github.com/ipfs/js-ipfs-http-client/compare/v35.0.0...v35.1.0) (2019-09-04)\n\n\n### Features\n\n* add config profile endpoint ([#1030](https://github.com/ipfs/js-ipfs-http-client/issues/1030)) ([3aaa3ee](https://github.com/ipfs/js-ipfs-http-client/commit/3aaa3ee))\n\n\n\n<a name=\"35.0.0\"></a>\n# [35.0.0](https://github.com/ipfs/js-ipfs-http-client/compare/v34.0.0...v35.0.0) (2019-09-04)\n\n### BREAKING CHANGES\n\nKebab case options (e.g. `wrap-with-directory`) are no longer supported in `ipfs.add`. Use camel case instead (e.g. `wrapWithDirectory`).\n\n<a name=\"34.0.0\"></a>\n# [34.0.0](https://github.com/ipfs/js-ipfs-http-client/compare/v33.1.1...v34.0.0) (2019-08-29)\n\n\n### Bug Fixes\n\n* **package:** update err-code to version 2.0.0 ([#1053](https://github.com/ipfs/js-ipfs-http-client/issues/1053)) ([3515070](https://github.com/ipfs/js-ipfs-http-client/commit/3515070))\n\n\n### Features\n\n* browser pubsub ([#1059](https://github.com/ipfs/js-ipfs-http-client/issues/1059)) ([3764d06](https://github.com/ipfs/js-ipfs-http-client/commit/3764d06))\n* expose pin and preload arguments ([#1079](https://github.com/ipfs/js-ipfs-http-client/issues/1079)) ([e3ed6e9](https://github.com/ipfs/js-ipfs-http-client/commit/e3ed6e9))\n* support adding files via async iterator ([#1078](https://github.com/ipfs/js-ipfs-http-client/issues/1078)) ([377042b](https://github.com/ipfs/js-ipfs-http-client/commit/377042b))\n\n\n\n<a name=\"33.1.1\"></a>\n## [33.1.1](https://github.com/ipfs/js-ipfs-http-client/compare/v33.1.0...v33.1.1) (2019-07-26)\n\n\n### Bug Fixes\n\n* allow passing timeout option to object stat ([#1055](https://github.com/ipfs/js-ipfs-http-client/issues/1055)) ([92b0594](https://github.com/ipfs/js-ipfs-http-client/commit/92b0594))\n\n\n\n<a name=\"33.1.0\"></a>\n# [33.1.0](https://github.com/ipfs/js-ipfs-http-client/compare/v33.0.2...v33.1.0) (2019-07-11)\n\n\n### Bug Fixes\n\n* changelog for 33.x does not include breaking change ([cd41a16](https://github.com/ipfs/js-ipfs-http-client/commit/cd41a16))\n* invalid multipart/form-data ([#948](https://github.com/ipfs/js-ipfs-http-client/issues/948)) ([9e6dfe7](https://github.com/ipfs/js-ipfs-http-client/commit/9e6dfe7)), closes [/tools.ietf.org/html/rfc7578#section-4](https://github.com//tools.ietf.org/html/rfc7578/issues/section-4)\n\n\n### Features\n\n* add support for js-ipfs dag api and also some tests ([#957](https://github.com/ipfs/js-ipfs-http-client/issues/957)) ([8f378a3](https://github.com/ipfs/js-ipfs-http-client/commit/8f378a3))\n\n\n\n<a name=\"33.0.2\"></a>\n## [33.0.2](https://github.com/ipfs/js-ipfs-http-client/compare/v33.0.1...v33.0.2) (2019-07-11)\n\n\n### Bug Fixes\n\n* make findprovs return all responses ([#1041](https://github.com/ipfs/js-ipfs-http-client/issues/1041)) ([63103bd](https://github.com/ipfs/js-ipfs-http-client/commit/63103bd))\n\n\n\n<a name=\"33.0.1\"></a>\n## [33.0.1](https://github.com/ipfs/js-ipfs-http-client/compare/v33.0.0...v33.0.1) (2019-07-10)\n\n\n### Bug Fixes\n\n* response for findpeer and findprovs ([#1039](https://github.com/ipfs/js-ipfs-http-client/issues/1039)) ([5252f50](https://github.com/ipfs/js-ipfs-http-client/commit/5252f50))\n\n\n\n<a name=\"33.0.0\"></a>\n# [33.0.0](https://github.com/ipfs/js-ipfs-http-client/compare/v32.0.1...v33.0.0) (2019-07-10)\n\n\n### Bug Fixes\n\n* link to ipfs.io ([70cdf25](https://github.com/ipfs/js-ipfs-http-client/commit/70cdf25))\n* prepare for aegir release ([#1021](https://github.com/ipfs/js-ipfs-http-client/issues/1021)) ([806b206](https://github.com/ipfs/js-ipfs-http-client/commit/806b206))\n* sometimes no Addrs element is present in the response ([#1037](https://github.com/ipfs/js-ipfs-http-client/issues/1037)) ([a74b8f7](https://github.com/ipfs/js-ipfs-http-client/commit/a74b8f7))\n* **package:** update bignumber.js to version 9.0.0 ([#1024](https://github.com/ipfs/js-ipfs-http-client/issues/1024)) ([a04edac](https://github.com/ipfs/js-ipfs-http-client/commit/a04edac))\n\n### BREAKING CHANGES\n\n`repo.gc` response objects have changed to `{ err, cid }`, where `err` is an `Error` instance and `cid` is a [`CID`](https://github.com/multiformats/js-cid) instance.\n\n\n\n<a name=\"32.0.1\"></a>\n## [32.0.1](https://github.com/ipfs/js-ipfs-http-client/compare/v32.0.0...v32.0.1) (2019-05-21)\n\n\n### Bug Fixes\n\n* error reporting for non-JSON responses ([#1016](https://github.com/ipfs/js-ipfs-http-client/issues/1016)) ([4251c88](https://github.com/ipfs/js-ipfs-http-client/commit/4251c88)), closes [#912](https://github.com/ipfs/js-ipfs-http-client/issues/912) [#1000](https://github.com/ipfs/js-ipfs-http-client/issues/1000) [#1001](https://github.com/ipfs/js-ipfs-http-client/issues/1001)\n* send trickle param to trigger trickle dag builder ([#1015](https://github.com/ipfs/js-ipfs-http-client/issues/1015)) ([a28b009](https://github.com/ipfs/js-ipfs-http-client/commit/a28b009))\n\n\n\n<a name=\"32.0.0\"></a>\n# [32.0.0](https://github.com/ipfs/js-ipfs-http-client/compare/v31.1.0...v32.0.0) (2019-05-21)\n\n\n### Bug Fixes\n\n* handle empty array return value in dht.findProvs ([#1003](https://github.com/ipfs/js-ipfs-http-client/issues/1003)) ([15ab7c5](https://github.com/ipfs/js-ipfs-http-client/commit/15ab7c5))\n\n\n### Chores\n\n* update ipld formats ([#1010](https://github.com/ipfs/js-ipfs-http-client/issues/1010)) ([a423d7f](https://github.com/ipfs/js-ipfs-http-client/commit/a423d7f))\n\n\n### BREAKING CHANGES\n\n* The default string encoding for version 1 CIDs has changed to `base32`.\n\nIPLD formats have been updated to the latest versions. IPLD nodes returned by `ipfs.dag` and `ipfs.object` commands have significant breaking changes. If you are using these commands in your application you are likely to encounter the following changes to `dag-pb` nodes (the default node type that IPFS creates):\n\n* `DAGNode` properties have been renamed as follows:\n    * `data` => `Data`\n    * `links` => `Links`\n    * `size` => `size` (Note: no change)\n* `DAGLink` properties have been renamed as follows:\n    * `cid` => `Hash`\n    * `name` => `Name`\n    * `size` => `Tsize`\n\nSee CHANGELOGs for each IPLD format for it's respective changes, you can read more about the [`dag-pb` changes in the CHANGELOG](https://github.com/ipld/js-ipld-dag-pb/blob/master)\n\nLicense: MIT\nSigned-off-by: Alan Shaw <alan.shaw@protocol.ai>\n\n\n\n<a name=\"31.1.0\"></a>\n# [31.1.0](https://github.com/ipfs/js-ipfs-http-client/compare/v31.0.2...v31.1.0) (2019-05-16)\n\n\n### Features\n\n* add support for File DOM API to files-regular ([#986](https://github.com/ipfs/js-ipfs-http-client/issues/986)) ([7b49f7e](https://github.com/ipfs/js-ipfs-http-client/commit/7b49f7e))\n\n\n\n<a name=\"31.0.2\"></a>\n## [31.0.2](https://github.com/ipfs/js-ipfs-http-client/compare/v31.0.1...v31.0.2) (2019-05-16)\n\n\n### Bug Fixes\n\n* error handling for refs/refs local ([#997](https://github.com/ipfs/js-ipfs-http-client/issues/997)) ([391351d](https://github.com/ipfs/js-ipfs-http-client/commit/391351d))\n\n\n\n<a name=\"31.0.1\"></a>\n## [31.0.1](https://github.com/ipfs/js-ipfs-http-client/compare/v31.0.0...v31.0.1) (2019-05-15)\n\n\n### Bug Fixes\n\n* config set with number ([#998](https://github.com/ipfs/js-ipfs-http-client/issues/998)) ([4f21bef](https://github.com/ipfs/js-ipfs-http-client/commit/4f21bef)), closes [#881](https://github.com/ipfs/js-ipfs-http-client/issues/881)\n\n\n\n<a name=\"31.0.0\"></a>\n# [31.0.0](https://github.com/ipfs/js-ipfs-http-client/compare/v30.1.4...v31.0.0) (2019-05-13)\n\n\n### Features\n\n* refs endpoint ([#978](https://github.com/ipfs/js-ipfs-http-client/issues/978)) ([a741e10](https://github.com/ipfs/js-ipfs-http-client/commit/a741e10))\n\n\n### BREAKING CHANGES\n\n* ipfs.refs now returns objects with camelCase properties not PascalCase properties. i.e. `{ ref, err }` not `{ Ref, Err }`\n\n\n\n<a name=\"30.1.4\"></a>\n## [30.1.4](https://github.com/ipfs/js-ipfs-http-client/compare/v30.1.3...v30.1.4) (2019-04-29)\n\n\n### Bug Fixes\n\n* uncaught error: stream.push() after EOF ([#980](https://github.com/ipfs/js-ipfs-http-client/issues/980)) ([cc677f0](https://github.com/ipfs/js-ipfs-http-client/commit/cc677f0)), closes [#967](https://github.com/ipfs/js-ipfs-http-client/issues/967)\n* update Babel in upload-file-via-browser example ([#968](https://github.com/ipfs/js-ipfs-http-client/issues/968)) ([#970](https://github.com/ipfs/js-ipfs-http-client/issues/970)) ([17d49de](https://github.com/ipfs/js-ipfs-http-client/commit/17d49de))\n\n\n\n<a name=\"30.1.3\"></a>\n## [30.1.3](https://github.com/ipfs/js-ipfs-http-client/compare/v30.1.2...v30.1.3) (2019-04-11)\n\n\n### Bug Fixes\n\n* fix missing buffer bundling with browserify ([#966](https://github.com/ipfs/js-ipfs-http-client/issues/966)) ([944a64b](https://github.com/ipfs/js-ipfs-http-client/commit/944a64b)), closes [#964](https://github.com/ipfs/js-ipfs-http-client/issues/964)\n\n\n\n<a name=\"30.1.2\"></a>\n## [30.1.2](https://github.com/ipfs/js-ipfs-http-client/compare/v30.1.1...v30.1.2) (2019-04-09)\n\n\n### Bug Fixes\n\n* https multiaddr support in constructor ([#965](https://github.com/ipfs/js-ipfs-http-client/issues/965)) ([5da0bcd](https://github.com/ipfs/js-ipfs-http-client/commit/5da0bcd))\n\n\n\n<a name=\"30.1.1\"></a>\n## [30.1.1](https://github.com/ipfs/js-ipfs-http-client/compare/v30.1.0...v30.1.1) (2019-03-28)\n\n\n\n<a name=\"30.1.0\"></a>\n# [30.1.0](https://github.com/ipfs/js-ipfs-http-client/compare/v30.0.0...v30.1.0) (2019-03-15)\n\n\n### Bug Fixes\n\n* dht.findProvs.js handle valid hash but no providers ([#950](https://github.com/ipfs/js-ipfs-http-client/issues/950)) ([c3cde76](https://github.com/ipfs/js-ipfs-http-client/commit/c3cde76))\n\n\n### Features\n\n* provide access to multicodec ([#954](https://github.com/ipfs/js-ipfs-http-client/issues/954)) ([0c109ab](https://github.com/ipfs/js-ipfs-http-client/commit/0c109ab))\n\n\n### Performance Improvements\n\n* reduce bundle size ([#915](https://github.com/ipfs/js-ipfs-http-client/issues/915)) ([87dff04](https://github.com/ipfs/js-ipfs-http-client/commit/87dff04))\n\n\n\n<a name=\"30.0.0\"></a>\n# [30.0.0](https://github.com/ipfs/js-ipfs-http-client/compare/v29.1.1...v30.0.0) (2019-03-13)\n\n\n### Bug Fixes\n\n* windows travis build ([#952](https://github.com/ipfs/js-ipfs-http-client/issues/952)) ([05f2f6c](https://github.com/ipfs/js-ipfs-http-client/commit/05f2f6c))\n\n\n### Code Refactoring\n\n* export types and utilities statically ([#951](https://github.com/ipfs/js-ipfs-http-client/issues/951)) ([d1e99e7](https://github.com/ipfs/js-ipfs-http-client/commit/d1e99e7)), closes [#902](https://github.com/ipfs/js-ipfs-http-client/issues/902)\n\n\n### Features\n\n* pubsub unsubscribe all ([#956](https://github.com/ipfs/js-ipfs-http-client/issues/956)) ([a57a411](https://github.com/ipfs/js-ipfs-http-client/commit/a57a411))\n\n\n### BREAKING CHANGES\n\n* `ipfs.util.isIPFS` has moved to a static export and should be accessed via `const { isIPFS } = require('ipfs-http-client')`.\n\nThe modules available under `ipfs.types.*` have also become static exports.\n\n`ipfs.util.crypto` has been removed as it is not a dependency of `ipfs-http-client` so reduces the bundle size. If you need to use libp2p crypto primitives then please see the [js-libp2p-crypto](https://github.com/libp2p/js-libp2p-crypto) project for info on how to use it in your project.\n\nFinally `ipfs.util.getEndpointConfig` is now a direct instance method, `ipfs.getEndpointConfig`\n\nLicense: MIT\nSigned-off-by: Alan Shaw <alan.shaw@protocol.ai>\n\n\n\n<a name=\"29.1.1\"></a>\n## [29.1.1](https://github.com/ipfs/js-ipfs-http-client/compare/v29.1.0...v29.1.1) (2019-02-13)\n\n\n### Performance Improvements\n\n* use test profile ([#942](https://github.com/ipfs/js-ipfs-http-client/issues/942)) ([2c90620](https://github.com/ipfs/js-ipfs-http-client/commit/2c90620))\n\n\n\n<a name=\"29.1.0\"></a>\n# [29.1.0](https://github.com/ipfs/js-ipfs-http-client/compare/v29.0.1...v29.1.0) (2019-01-29)\n\n\n### Bug Fixes\n\n* throw on invalid multiaddr to constructor ([#934](https://github.com/ipfs/js-ipfs-http-client/issues/934)) ([bcbf0d2](https://github.com/ipfs/js-ipfs-http-client/commit/bcbf0d2))\n\n\n### Features\n\n* return protocol from getEndpointConfig ([#935](https://github.com/ipfs/js-ipfs-http-client/issues/935)) ([12ddaa3](https://github.com/ipfs/js-ipfs-http-client/commit/12ddaa3))\n\n\n\n<a name=\"29.0.1\"></a>\n## [29.0.1](https://github.com/ipfs/js-ipfs-http-client/compare/v29.0.0...v29.0.1) (2019-01-24)\n\n\n### Bug Fixes\n\n* bundle in meteor ([#931](https://github.com/ipfs/js-ipfs-http-client/issues/931)) ([431c442](https://github.com/ipfs/js-ipfs-http-client/commit/431c442)), closes [#10411](https://github.com/ipfs/js-ipfs-http-client/issues/10411)\n\n\n\n<a name=\"29.0.0\"></a>\n# [29.0.0](https://github.com/ipfs/js-ipfs-http-client/compare/v28.1.2...v29.0.0) (2019-01-15)\n\n\n### Code Refactoring\n\n* switch to bignumber.js ([#927](https://github.com/ipfs/js-ipfs-http-client/issues/927)) ([1a54ae5](https://github.com/ipfs/js-ipfs-http-client/commit/1a54ae5))\n\n\n### BREAKING CHANGES\n\n* All API methods that returned [`big.js`](https://github.com/MikeMcl/big.js/) instances now return [`bignumber.js`](https://github.com/MikeMcl/bignumber.js/) instances.\n\nLicense: MIT\nSigned-off-by: Alan Shaw <alan.shaw@protocol.ai>\n\n\n\n<a name=\"28.1.2\"></a>\n## [28.1.2](https://github.com/ipfs/js-ipfs-http-client/compare/v28.1.1...v28.1.2) (2019-01-14)\n\n\n\n<a name=\"28.1.1\"></a>\n## [28.1.1](https://github.com/ipfs/js-ipfs-http-client/compare/v28.1.0...v28.1.1) (2019-01-04)\n\n\n\n<a name=\"28.1.0\"></a>\n# [28.1.0](https://github.com/ipfs/js-ipfs-http-client/compare/v28.0.3...v28.1.0) (2018-12-16)\n\n\n### Features\n\n* add cidBase option to resolve ([#893](https://github.com/ipfs/js-ipfs-http-client/issues/893)) ([ec6285d](https://github.com/ipfs/js-ipfs-http-client/commit/ec6285d))\n\n\n\n<a name=\"28.0.3\"></a>\n## [28.0.3](https://github.com/ipfs/js-ipfs-http-client/compare/v28.0.2...v28.0.3) (2018-12-15)\n\n\n### Bug Fixes\n\n* re-allow passing path to ls ([#914](https://github.com/ipfs/js-ipfs-http-client/issues/914)) ([442bcdd](https://github.com/ipfs/js-ipfs-http-client/commit/442bcdd))\n\n\n\n<a name=\"28.0.2\"></a>\n## [28.0.2](https://github.com/ipfs/js-ipfs-http-client/compare/v28.0.1...v28.0.2) (2018-12-14)\n\n\n\n<a name=\"28.0.1\"></a>\n## [28.0.1](https://github.com/ipfs/js-ipfs-http-client/compare/v28.0.0...v28.0.1) (2018-12-13)\n\n\n### Bug Fixes\n\n* disable just the rule we're breaking ([bed2687](https://github.com/ipfs/js-ipfs-http-client/commit/bed2687))\n* properly serialize CID instances ([45b344c](https://github.com/ipfs/js-ipfs-http-client/commit/45b344c))\n* skip test that go-ipfs cannot pass ([0e15761](https://github.com/ipfs/js-ipfs-http-client/commit/0e15761))\n\n\n\n<a name=\"28.0.0\"></a>\n# [28.0.0](https://github.com/ipfs/js-ipfs-http-client/compare/v27.1.0...v28.0.0) (2018-12-11)\n\n\n### Bug Fixes\n\n* case for addFromURL ([#907](https://github.com/ipfs/js-ipfs-http-client/issues/907)) ([99ac7be](https://github.com/ipfs/js-ipfs-http-client/commit/99ac7be))\n\n\n### Code Refactoring\n\n* dht api ([#890](https://github.com/ipfs/js-ipfs-http-client/issues/890)) ([05a84a4](https://github.com/ipfs/js-ipfs-http-client/commit/05a84a4))\n\n\n### BREAKING CHANGES\n\n* DHT API methods renamed and return types changed\n\n* `ipfs.dht.findprovs` renamed to `ipfs.dht.findProvs` and returns an array of [PeerInfo](https://github.com/libp2p/js-peer-info)\n* `ipfs.dht.findpeer` renamed to `ipfs.dht.findPeer` and returns a [PeerInfo](https://github.com/libp2p/js-peer-info)\n* `ipfs.dht.query` now returns an array of [PeerId](https://github.com/libp2p/js-peer-id)\n* [More info](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/DHT.md)\n\n\n\n<a name=\"27.1.0\"></a>\n# [27.1.0](https://github.com/ipfs/js-ipfs-http-client/compare/v27.0.0...v27.1.0) (2018-12-05)\n\n\n### Bug Fixes\n\n* add docs for breaking change ([#898](https://github.com/ipfs/js-ipfs-http-client/issues/898)) ([3e794ac](https://github.com/ipfs/js-ipfs-http-client/commit/3e794ac))\n\n\n### Features\n\n* add files.ls*Stream methods ([#903](https://github.com/ipfs/js-ipfs-http-client/issues/903)) ([705855e](https://github.com/ipfs/js-ipfs-http-client/commit/705855e))\n\n\n\n<a name=\"27.0.0\"></a>\n# [27.0.0](https://github.com/ipfs/js-ipfs-http-client/compare/v26.1.2...v27.0.0) (2018-11-28)\n\n\n### Bug Fixes\n\n* also retry with misnemed format \"dag-cbor\" as \"cbor\" ([#888](https://github.com/ipfs/js-ipfs-http-client/issues/888)) ([348a144](https://github.com/ipfs/js-ipfs-http-client/commit/348a144))\n* better input validation for add ([#876](https://github.com/ipfs/js-ipfs-http-client/issues/876)) ([315b7f7](https://github.com/ipfs/js-ipfs-http-client/commit/315b7f7))\n* fix log.tail by calling add after listening for events ([#882](https://github.com/ipfs/js-ipfs-http-client/issues/882)) ([da35b0f](https://github.com/ipfs/js-ipfs-http-client/commit/da35b0f))\n* handle peer-info validation errors ([#887](https://github.com/ipfs/js-ipfs-http-client/issues/887)) ([6e6d7a2](https://github.com/ipfs/js-ipfs-http-client/commit/6e6d7a2)), closes [#885](https://github.com/ipfs/js-ipfs-http-client/issues/885)\n* updates ipld-dag-pb dep to version without .cid properties ([#889](https://github.com/ipfs/js-ipfs-http-client/issues/889)) ([ac30a82](https://github.com/ipfs/js-ipfs-http-client/commit/ac30a82))\n\n\n### Code Refactoring\n\n* object API write methods now return CIDs ([#896](https://github.com/ipfs/js-ipfs-http-client/issues/896)) ([38bed14](https://github.com/ipfs/js-ipfs-http-client/commit/38bed14))\n* rename library to ipfs-http-client ([#897](https://github.com/ipfs/js-ipfs-http-client/issues/897)) ([d40cb6c](https://github.com/ipfs/js-ipfs-http-client/commit/d40cb6c))\n* updated files API ([#878](https://github.com/ipfs/js-ipfs-http-client/issues/878)) ([39f4733](https://github.com/ipfs/js-ipfs-http-client/commit/39f4733))\n\n\n### BREAKING CHANGES\n\n* the `ipfs-api` library has been renamed to `ipfs-http-client`.\n\nNow install via `npm install ipfs-http-client`.\n\nNote that in the browser build the object attached to `window` is now `window.IpfsHttpClient`.\n\nLicense: MIT\nSigned-off-by: Alan Shaw <alan.shaw@protocol.ai>\n\n* Object API refactor.\n\nObject API methods that write DAG nodes now return a CID instead of a DAG node. Affected methods:\n\n* `ipfs.object.new`\n* `ipfs.object.patch.addLink`\n* `ipfs.object.patch.appendData`\n* `ipfs.object.patch.rmLink`\n* `ipfs.object.patch.setData`\n* `ipfs.object.put`\n\nExample:\n\n```js\n// Before\nconst dagNode = await ipfs.object.new()\n```\n\n```js\n// After\nconst cid = await ipfs.object.new() // now returns a CID\nconst dagNode = await ipfs.object.get(cid) // fetch the DAG node that was created\n```\n\nIMPORTANT: `DAGNode` instances, which are part of the IPLD dag-pb format have been refactored.\n\nThese instances no longer have `multihash`, `cid` or `serialized` properties.\n\nThis effects the following API methods that return these types of objects:\n\n* `ipfs.object.get`\n* `ipfs.dag.get`\n\nSee https://github.com/ipld/js-ipld-dag-pb/pull/99 for more information.\n\nLicense: MIT\nSigned-off-by: Alan Shaw <alan.shaw@protocol.ai>\n\n* Files API methods `add*`, `cat*`, `get*` have moved from `files` to the root namespace.\n\nSpecifically, the following changes have been made:\n\n* `ipfs.files.add` => `ipfs.add`\n* `ipfs.files.addPullStream` => `ipfs.addPullStream`\n* `ipfs.files.addReadableStream` => `ipfs.addReadableStream`\n* `ipfs.files.cat` => `ipfs.cat`\n* `ipfs.files.catPullStream` => `ipfs.catPullStream`\n* `ipfs.files.catReadableStream` => `ipfs.catReadableStream`\n* `ipfs.files.get` => `ipfs.get`\n* `ipfs.files.getPullStream` => `ipfs.getPullStream`\n* `ipfs.files.getReadableStream` => `ipfs.getReadableStream`\n\nAdditionally, `addFromFs`, `addFromURL`, `addFromStream` have moved from `util` to the root namespace:\n\n* `ipfs.util.addFromFs` => `ipfs.addFromFs`\n* `ipfs.util.addFromURL` => `ipfs.addFromURL`\n* `ipfs.util.addFromStream` => `ipfs.addFromStream`\n\nLicense: MIT\nSigned-off-by: Alan Shaw <alan.shaw@protocol.ai>\n\n* Previously `swarm.peers` would throw an uncaught error if any peer in the response could not have its peerId or multiaddr validated.\n\nThis change catches errors that occur while validating the peer info. The returned array will contain an entry for every peer in the ipfs response. peer-info objects that couldn't be validated, now have an `error` property and a `rawPeerInfo` property. This at least means the count of peers in the response will be accurate, and there the info is available to the caller.\n\nThis means that callers now have to deal with peer-info objects that may\nnot have a `peer` or `addr` property.\n\nAdds `nock` tests to exercice the code under different error conditions. Doing so uncovered a bug in our legacy go-ipfs <= 0.4.4 peer info parsing, which is also fixed. The code was trying to decapusalate the peerId from the multiaddr, but doing so trims the peerId rather than returning it.\n\nLicense: MIT\nSigned-off-by: Oli Evans <oli@tableflip.io>\n\n\n<a name=\"26.1.2\"></a>\n## [26.1.2](https://github.com/ipfs/js-ipfs-http-client/compare/v26.1.0...v26.1.2) (2018-11-03)\n\n\n### Features\n\n* go-ipfs 0.4.18 ([e3e4d6c](https://github.com/ipfs/js-ipfs-http-client/commit/e3e4d6c))\n* upload example works with big files ([62b844f](https://github.com/ipfs/js-ipfs-http-client/commit/62b844f))\n\n\n\n<a name=\"26.1.1\"></a>\n## [26.1.1](https://github.com/ipfs/js-ipfs-http-client/compare/v26.1.0...v26.1.1) (2018-11-03)\n\n\n### Features\n\n* go-ipfs 0.4.18 ([9178e7d](https://github.com/ipfs/js-ipfs-http-client/commit/9178e7d))\n\n\n\n<a name=\"26.1.0\"></a>\n# [26.1.0](https://github.com/ipfs/js-ipfs-http-client/compare/v26.0.3...v26.1.0) (2018-10-31)\n\n\n### Bug Fixes\n\n* make ping not mix errors with responses ([#883](https://github.com/ipfs/js-ipfs-http-client/issues/883)) ([80725f2](https://github.com/ipfs/js-ipfs-http-client/commit/80725f2))\n\n\n\n<a name=\"26.0.3\"></a>\n## [26.0.3](https://github.com/ipfs/js-ipfs-http-client/compare/v26.0.2...v26.0.3) (2018-10-31)\n\n\n\n<a name=\"26.0.2\"></a>\n## [26.0.2](https://github.com/ipfs/js-ipfs-http-client/compare/v26.0.0...v26.0.2) (2018-10-31)\n\n\n### Bug Fixes\n\n* pin.ls ignored opts when hash was present ([#875](https://github.com/ipfs/js-ipfs-http-client/issues/875)) ([0b46750](https://github.com/ipfs/js-ipfs-http-client/commit/0b46750)), closes [/github.com/ipfs-shipyard/ipfs-companion/issues/360#issuecomment-427525801](https://github.com//github.com/ipfs-shipyard/ipfs-companion/issues/360/issues/issuecomment-427525801)\n\n\n\n<a name=\"26.0.1\"></a>\n## [26.0.1](https://github.com/ipfs/js-ipfs-http-client/compare/v26.0.0...v26.0.1) (2018-10-30)\n\n\n\n<a name=\"26.0.0\"></a>\n# [26.0.0](https://github.com/ipfs/js-ipfs-http-client/compare/v25.0.0...v26.0.0) (2018-10-30)\n\n\n### Bug Fixes\n\n* add missing and remove unused dependencies ([#879](https://github.com/ipfs/js-ipfs-http-client/issues/879)) ([979d8b5](https://github.com/ipfs/js-ipfs-http-client/commit/979d8b5))\n\n\n### Chores\n\n* remove ipld formats re-export ([#872](https://github.com/ipfs/js-ipfs-http-client/issues/872)) ([c534375](https://github.com/ipfs/js-ipfs-http-client/commit/c534375))\n* update to ipld-dag-cbor 0.13 ([0652ac0](https://github.com/ipfs/js-ipfs-http-client/commit/0652ac0))\n\n\n### Features\n\n* ipns over pubsub ([#846](https://github.com/ipfs/js-ipfs-http-client/issues/846)) ([ef49e95](https://github.com/ipfs/js-ipfs-http-client/commit/ef49e95))\n\n\n### BREAKING CHANGES\n\n* dag-cbor nodes now represent links as CID objects\n\nThe API for [dag-cbor](https://github.com/ipld/js-ipld-dag-cbor) changed.\nLinks are no longer represented as JSON objects (`{\"/\": \"base-encoded-cid\"}`,\nbut as [CID objects](https://github.com/ipld/js-cid). `ipfs.dag.get()` and\nnow always return links as CID objects. `ipfs.dag.put()` also expects links\nto be represented as CID objects. The old-style JSON objects representation\nis still supported, but deprecated.\n\nPrior to this change:\n\n```js\nconst cid = new CID('QmXed8RihWcWFXRRmfSRG9yFjEbXNxu1bDwgCFAN8Dxcq5')\n// Link as JSON object representation\nconst putCid = await ipfs.dag.put({link: {'/': cid.toBaseEncodedString()}})\nconst result = await ipfs.dag.get(putCid)\nconsole.log(result.value)\n\n```\n\nOutput:\n\n```js\n{ link:\n   { '/':\n      <Buffer 12 20 8a…> } }\n```\n\nNow:\n\n```js\nconst cid = new CID('QmXed8RihWcWFXRRmfSRG9yFjEbXNxu1bDwgCFAN8Dxcq5')\n// Link as CID object\nconst putCid = await ipfs.dag.put({link: cid})\nconst result = await ipfs.dag.get(putCid)\nconsole.log(result.value)\n```\n\nOutput:\n\n```js\n{ link:\n   CID {\n     codec: 'dag-pb',\n     version: 0,\n     multihash:\n      <Buffer 12 20 8a…> } }\n```\n\nSee https://github.com/ipld/ipld/issues/44 for more information on why this\nchange was made.\n* remove `types.dagCBOR` and `types.dagPB` from public API\n\nIf you need the `ipld-dag-cbor` or `ipld-dag-pb` module in the Browser,\nyou need to bundle them yourself.\n\n\n\n<a name=\"25.0.0\"></a>\n# [25.0.0](https://github.com/ipfs/js-ipfs-http-client/compare/v24.0.2...v25.0.0) (2018-10-15)\n\n\n### Bug Fixes\n\n* >150mb bodies no longer crashing Chromium ([#868](https://github.com/ipfs/js-ipfs-http-client/issues/868)) ([180da77](https://github.com/ipfs/js-ipfs-http-client/commit/180da77)), closes [#654](https://github.com/ipfs/js-ipfs-http-client/issues/654)\n* add bl module to package dependencies ([#853](https://github.com/ipfs/js-ipfs-http-client/issues/853)) ([#854](https://github.com/ipfs/js-ipfs-http-client/issues/854)) ([834934f](https://github.com/ipfs/js-ipfs-http-client/commit/834934f))\n* add lodash dependency ([#873](https://github.com/ipfs/js-ipfs-http-client/issues/873)) ([c510cb7](https://github.com/ipfs/js-ipfs-http-client/commit/c510cb7)), closes [#870](https://github.com/ipfs/js-ipfs-http-client/issues/870)\n\n\n\n<a name=\"24.0.2\"></a>\n## [24.0.2](https://github.com/ipfs/js-ipfs-http-client/compare/v24.0.1...v24.0.2) (2018-09-21)\n\n\n### Bug Fixes\n\n* block.put options ([#844](https://github.com/ipfs/js-ipfs-http-client/issues/844)) ([e290a38](https://github.com/ipfs/js-ipfs-http-client/commit/e290a38))\n\n\n\n<a name=\"24.0.1\"></a>\n## [24.0.1](https://github.com/ipfs/js-ipfs-http-client/compare/v24.0.0...v24.0.1) (2018-08-21)\n\n\n\n<a name=\"24.0.0\"></a>\n# [24.0.0](https://github.com/ipfs/js-ipfs-http-client/compare/v23.0.0...v24.0.0) (2018-08-15)\n\n\n### Bug Fixes\n\n* add test data to IPFS before fetching it ([#832](https://github.com/ipfs/js-ipfs-http-client/issues/832)) ([b2a77d6](https://github.com/ipfs/js-ipfs-http-client/commit/b2a77d6))\n* BREAKING CHANGE use data-encoding arg so data is not corrupted ([#806](https://github.com/ipfs/js-ipfs-http-client/issues/806)) ([553c3fb](https://github.com/ipfs/js-ipfs-http-client/commit/553c3fb))\n* dag.get return error on missing multicodec ([#831](https://github.com/ipfs/js-ipfs-http-client/issues/831)) ([ff7c7e5](https://github.com/ipfs/js-ipfs-http-client/commit/ff7c7e5))\n* remove external urls from addFromURL tests ([#834](https://github.com/ipfs/js-ipfs-http-client/issues/834)) ([7cf7998](https://github.com/ipfs/js-ipfs-http-client/commit/7cf7998)), closes [#803](https://github.com/ipfs/js-ipfs-http-client/issues/803)\n\n\n### BREAKING CHANGES\n\n* Requires go-ipfs 0.4.17 as it allows for specifying the data encoding format when requesting object data.\n\n\n\n<a name=\"23.0.0\"></a>\n# [23.0.0](https://github.com/ipfs/js-ipfs-http-client/compare/v22.3.0...v23.0.0) (2018-08-06)\n\n\n### Bug Fixes\n\n* config get ([#825](https://github.com/ipfs/js-ipfs-http-client/issues/825)) ([ef5a4a3](https://github.com/ipfs/js-ipfs-http-client/commit/ef5a4a3))\n\n\n### Features\n\n* add resolve cmd ([#826](https://github.com/ipfs/js-ipfs-http-client/issues/826)) ([c7ad0e4](https://github.com/ipfs/js-ipfs-http-client/commit/c7ad0e4))\n\n\n\n<a name=\"22.3.0\"></a>\n# [22.3.0](https://github.com/ipfs/js-ipfs-http-client/compare/v22.2.4...v22.3.0) (2018-08-02)\n\n\n### Bug Fixes\n\n* config.set rejects buffer values ([#800](https://github.com/ipfs/js-ipfs-http-client/issues/800)) ([f3e6bf1](https://github.com/ipfs/js-ipfs-http-client/commit/f3e6bf1))\n\n\n### Features\n\n* compatible with go-ipfs 0.4.16 ([8536ee4](https://github.com/ipfs/js-ipfs-http-client/commit/8536ee4))\n* expose mfs files.read*Stream methods ([#823](https://github.com/ipfs/js-ipfs-http-client/issues/823)) ([70c9df1](https://github.com/ipfs/js-ipfs-http-client/commit/70c9df1))\n\n\n\n<a name=\"22.2.4\"></a>\n## [22.2.4](https://github.com/ipfs/js-ipfs-http-client/compare/v22.2.3...v22.2.4) (2018-07-17)\n\n\n### Bug Fixes\n\n* increase browserNoActivityTimeout to account for before ([328e338](https://github.com/ipfs/js-ipfs-http-client/commit/328e338))\n* increase timeout for .name after all ([3dc4313](https://github.com/ipfs/js-ipfs-http-client/commit/3dc4313))\n* missing debug dependency fixes [#809](https://github.com/ipfs/js-ipfs-http-client/issues/809) ([#810](https://github.com/ipfs/js-ipfs-http-client/issues/810)) ([0f1fe95](https://github.com/ipfs/js-ipfs-http-client/commit/0f1fe95))\n\n\n\n<a name=\"22.2.3\"></a>\n## [22.2.3](https://github.com/ipfs/js-ipfs-http-client/compare/v22.2.2...v22.2.3) (2018-07-10)\n\n\n### Bug Fixes\n\n* Request logging broken in Electron ([#808](https://github.com/ipfs/js-ipfs-http-client/issues/808)) ([52298ae](https://github.com/ipfs/js-ipfs-http-client/commit/52298ae))\n\n\n\n<a name=\"22.2.2\"></a>\n## [22.2.2](https://github.com/ipfs/js-ipfs-http-client/compare/v22.2.1...v22.2.2) (2018-07-05)\n\n\n### Bug Fixes\n\n* ignore response body for some mfs commands ([#805](https://github.com/ipfs/js-ipfs-http-client/issues/805)) ([b604a64](https://github.com/ipfs/js-ipfs-http-client/commit/b604a64))\n\n\n### Features\n\n* modular interface tests ([#785](https://github.com/ipfs/js-ipfs-http-client/issues/785)) ([2426072](https://github.com/ipfs/js-ipfs-http-client/commit/2426072)), closes [#339](https://github.com/ipfs/js-ipfs-http-client/issues/339) [#802](https://github.com/ipfs/js-ipfs-http-client/issues/802) [#801](https://github.com/ipfs/js-ipfs-http-client/issues/801)\n\n\n\n<a name=\"22.2.1\"></a>\n## [22.2.1](https://github.com/ipfs/js-ipfs-http-client/compare/v22.2.0...v22.2.1) (2018-06-29)\n\n\n### Bug Fixes\n\n* res.req only in Node.js, in browser use res.url instead ([#798](https://github.com/ipfs/js-ipfs-http-client/issues/798)) ([e8a5ab9](https://github.com/ipfs/js-ipfs-http-client/commit/e8a5ab9))\n\n\n\n<a name=\"22.2.0\"></a>\n# [22.2.0](https://github.com/ipfs/js-ipfs-http-client/compare/v22.1.1...v22.2.0) (2018-06-29)\n\n\n### Features\n\n* logs path & querystring for requests ([#796](https://github.com/ipfs/js-ipfs-http-client/issues/796)) ([4e55d19](https://github.com/ipfs/js-ipfs-http-client/commit/4e55d19))\n\n\n\n<a name=\"22.1.1\"></a>\n## [22.1.1](https://github.com/ipfs/js-ipfs-http-client/compare/v22.1.0...v22.1.1) (2018-06-25)\n\n\n### Bug Fixes\n\n* get block with empty data ([#789](https://github.com/ipfs/js-ipfs-http-client/issues/789)) ([88edd83](https://github.com/ipfs/js-ipfs-http-client/commit/88edd83))\n\n\n\n<a name=\"22.1.0\"></a>\n# [22.1.0](https://github.com/ipfs/js-ipfs-http-client/compare/v22.0.2...v22.1.0) (2018-06-18)\n\n\n### Features\n\n* add support for custom headers to send-request ([#741](https://github.com/ipfs/js-ipfs-http-client/issues/741)) ([7fb2e07](https://github.com/ipfs/js-ipfs-http-client/commit/7fb2e07))\n* implement bitswap wantlist peer ID param and bitswap unwant ([#761](https://github.com/ipfs/js-ipfs-http-client/issues/761)) ([73a153e](https://github.com/ipfs/js-ipfs-http-client/commit/73a153e))\n\n\n\n<a name=\"22.0.2\"></a>\n## [22.0.2](https://github.com/ipfs/js-ipfs-http-client/compare/v22.0.1...v22.0.2) (2018-06-14)\n\n\n### Bug Fixes\n\n* json-loader error in upload-file-via-browser example ([#784](https://github.com/ipfs/js-ipfs-http-client/issues/784)) ([5e7b7c4](https://github.com/ipfs/js-ipfs-http-client/commit/5e7b7c4))\n\n\n\n<a name=\"22.0.1\"></a>\n## [22.0.1](https://github.com/ipfs/js-ipfs-http-client/compare/v22.0.0...v22.0.1) (2018-05-30)\n\n\n### Bug Fixes\n\n* configure webpack to not use esmodules in dependencies ([dc14333](https://github.com/ipfs/js-ipfs-http-client/commit/dc14333))\n* correctly differentiate pong responses ([4ad25a3](https://github.com/ipfs/js-ipfs-http-client/commit/4ad25a3))\n* util.addFromURL with URL-escaped file ([a3bd811](https://github.com/ipfs/js-ipfs-http-client/commit/a3bd811))\n\n\n\n<a name=\"22.0.0\"></a>\n# [22.0.0](https://github.com/ipfs/js-ipfs-http-client/compare/v21.0.0...v22.0.0) (2018-05-20)\n\n\n### Bug Fixes\n\n* callback from unsub after stream ends ([51a80f2](https://github.com/ipfs/js-ipfs-http-client/commit/51a80f2))\n* do not fail stop node if failed start node ([533760f](https://github.com/ipfs/js-ipfs-http-client/commit/533760f))\n* **ping:** convert the ping messages to lowercase ([632af40](https://github.com/ipfs/js-ipfs-http-client/commit/632af40))\n* more robust ping tests ([fc6d301](https://github.com/ipfs/js-ipfs-http-client/commit/fc6d301))\n* remove .only ([0e21c8a](https://github.com/ipfs/js-ipfs-http-client/commit/0e21c8a))\n* result.Peers can be null, ensure callback is called ([f5f2e83](https://github.com/ipfs/js-ipfs-http-client/commit/f5f2e83))\n* update asserted error message ([17c1f1c](https://github.com/ipfs/js-ipfs-http-client/commit/17c1f1c))\n* use async/setImmediate vs process.nextTick ([faa51b4](https://github.com/ipfs/js-ipfs-http-client/commit/faa51b4))\n\n\n\n<a name=\"21.0.0\"></a>\n# [21.0.0](https://github.com/ipfs/js-ipfs-http-client/compare/v20.2.1...v21.0.0) (2018-05-12)\n\n\n### Bug Fixes\n\n* make pubsub.unsubscribe async and alter pubsub.subscribe signature ([b98f8f3](https://github.com/ipfs/js-ipfs-http-client/commit/b98f8f3))\n\n\n### BREAKING CHANGES\n\n* pubsub.unsubscribe is now async and argument order for pubsub.subscribe has changed\n\nLicense: MIT\nSigned-off-by: Alan Shaw <alan@tableflip.io>\n\n\n\n<a name=\"20.2.1\"></a>\n## [20.2.1](https://github.com/ipfs/js-ipfs-http-client/compare/v20.2.0...v20.2.1) (2018-05-06)\n\n\n\n<a name=\"20.2.0\"></a>\n# [20.2.0](https://github.com/ipfs/js-ipfs-http-client/compare/v20.0.1...v20.2.0) (2018-04-30)\n\n\n### Bug Fixes\n\n* adding files by pull stream ([2fa16c5](https://github.com/ipfs/js-ipfs-http-client/commit/2fa16c5))\n* handle request errors in addFromURL ([7c5cea5](https://github.com/ipfs/js-ipfs-http-client/commit/7c5cea5))\n* increase timeout for name.publish and fix setup code ([ceb1106](https://github.com/ipfs/js-ipfs-http-client/commit/ceb1106))\n* ipfs add url wrap doesn't work ([#750](https://github.com/ipfs/js-ipfs-http-client/issues/750)) ([f6f1bf0](https://github.com/ipfs/js-ipfs-http-client/commit/f6f1bf0))\n\n\n### Features\n\n* Add offset/length arguments to files.cat ([17967c1](https://github.com/ipfs/js-ipfs-http-client/commit/17967c1))\n* get it ready for release ([#751](https://github.com/ipfs/js-ipfs-http-client/issues/751)) ([1885af4](https://github.com/ipfs/js-ipfs-http-client/commit/1885af4))\n\n\n\n<a name=\"20.1.0\"></a>\n# [20.1.0](https://github.com/ipfs/js-ipfs-http-client/compare/v20.0.1...v20.1.0) (2018-04-30)\n\n\n### Bug Fixes\n\n* adding files by pull stream ([2fa16c5](https://github.com/ipfs/js-ipfs-http-client/commit/2fa16c5))\n* handle request errors in addFromURL ([7c5cea5](https://github.com/ipfs/js-ipfs-http-client/commit/7c5cea5))\n* increase timeout for name.publish and fix setup code ([ceb1106](https://github.com/ipfs/js-ipfs-http-client/commit/ceb1106))\n* ipfs add url wrap doesn't work ([#750](https://github.com/ipfs/js-ipfs-http-client/issues/750)) ([f6f1bf0](https://github.com/ipfs/js-ipfs-http-client/commit/f6f1bf0))\n\n\n### Features\n\n* Add offset/length arguments to files.cat ([17967c1](https://github.com/ipfs/js-ipfs-http-client/commit/17967c1))\n* get it ready for release ([#751](https://github.com/ipfs/js-ipfs-http-client/issues/751)) ([1885af4](https://github.com/ipfs/js-ipfs-http-client/commit/1885af4))\n\n\n\n<a name=\"20.0.1\"></a>\n## [20.0.1](https://github.com/ipfs/js-ipfs-http-client/compare/v20.0.0...v20.0.1) (2018-04-12)\n\n\n\n<a name=\"20.0.0\"></a>\n# [20.0.0](https://github.com/ipfs/js-ipfs-http-client/compare/v19.0.0...v20.0.0) (2018-04-05)\n\n\n### Bug Fixes\n\n* **dag:** js-ipld format resolver take the raw block ([2683c7e](https://github.com/ipfs/js-ipfs-http-client/commit/2683c7e))\n* **dag:** path logic for DAG get was wrong ([d2b203b](https://github.com/ipfs/js-ipfs-http-client/commit/d2b203b))\n* **dag:** use SendOneFile for dag put ([9c37213](https://github.com/ipfs/js-ipfs-http-client/commit/9c37213))\n\n\n### Features\n\n* dag.put ([9463d3a](https://github.com/ipfs/js-ipfs-http-client/commit/9463d3a))\n* **dag:** proper get implementation ([7ba0343](https://github.com/ipfs/js-ipfs-http-client/commit/7ba0343))\n* **dag:** rebase, use waterfall for put ([ad9eab8](https://github.com/ipfs/js-ipfs-http-client/commit/ad9eab8))\n* **dag:** update option names to reflect go-ipfs API ([9bf1c6c](https://github.com/ipfs/js-ipfs-http-client/commit/9bf1c6c))\n* Provide access to bundled libraries when in browser ([#732](https://github.com/ipfs/js-ipfs-http-client/issues/732)) ([994bdad](https://github.com/ipfs/js-ipfs-http-client/commit/994bdad)), closes [#406](https://github.com/ipfs/js-ipfs-http-client/issues/406)\n* public-readonly-method-for-getting-host-and-port ([41d32e3](https://github.com/ipfs/js-ipfs-http-client/commit/41d32e3)), closes [#580](https://github.com/ipfs/js-ipfs-http-client/issues/580)\n* Wrap with dir ([#730](https://github.com/ipfs/js-ipfs-http-client/issues/730)) ([160860e](https://github.com/ipfs/js-ipfs-http-client/commit/160860e))\n\n\n\n<a name=\"19.0.0\"></a>\n# [19.0.0](https://github.com/ipfs/js-ipfs-http-client/compare/v18.2.1...v19.0.0) (2018-03-28)\n\n\n### Bug Fixes\n\n* **bitswap:** 0.4.14 returns empty array instead of null ([5e37a54](https://github.com/ipfs/js-ipfs-http-client/commit/5e37a54))\n* **ping:** tests were failing and there it was missing to catch when count and n are used at the same time ([2181568](https://github.com/ipfs/js-ipfs-http-client/commit/2181568))\n\n\n### Features\n\n* streamable ping and optional packet number ([#723](https://github.com/ipfs/js-ipfs-http-client/issues/723)) ([3f3ce8a](https://github.com/ipfs/js-ipfs-http-client/commit/3f3ce8a))\n\n\n\n<a name=\"18.2.1\"></a>\n## [18.2.1](https://github.com/ipfs/js-ipfs-http-client/compare/v18.2.0...v18.2.1) (2018-03-22)\n\n\n### Features\n\n* add ability to files.cat with a cid instance ([aeeb94e](https://github.com/ipfs/js-ipfs-http-client/commit/aeeb94e))\n\n\n\n<a name=\"18.2.0\"></a>\n# [18.2.0](https://github.com/ipfs/js-ipfs-http-client/compare/v18.1.2...v18.2.0) (2018-03-16)\n\n\n### Bug Fixes\n\n* disable Browser test on Windows ([385a6c3](https://github.com/ipfs/js-ipfs-http-client/commit/385a6c3))\n* don't create one webpack bundle for every test file ([3967e96](https://github.com/ipfs/js-ipfs-http-client/commit/3967e96))\n* last fixes for green ([#719](https://github.com/ipfs/js-ipfs-http-client/issues/719)) ([658bad2](https://github.com/ipfs/js-ipfs-http-client/commit/658bad2))\n* set the FileResultStreamConverter explicitly ([dfad55e](https://github.com/ipfs/js-ipfs-http-client/commit/dfad55e)), closes [#696](https://github.com/ipfs/js-ipfs-http-client/issues/696)\n* use a different remote server for test ([1fc15a5](https://github.com/ipfs/js-ipfs-http-client/commit/1fc15a5))\n\n\n### Features\n\n* --only-hash ([#717](https://github.com/ipfs/js-ipfs-http-client/issues/717)) ([1137401](https://github.com/ipfs/js-ipfs-http-client/commit/1137401)), closes [#700](https://github.com/ipfs/js-ipfs-http-client/issues/700)\n* add support for ipfs files stat --with-local ([#695](https://github.com/ipfs/js-ipfs-http-client/issues/695)) ([b08f21a](https://github.com/ipfs/js-ipfs-http-client/commit/b08f21a))\n\n\n\n<a name=\"18.1.2\"></a>\n## [18.1.2](https://github.com/ipfs/js-ipfs-http-client/compare/v18.1.1...v18.1.2) (2018-03-09)\n\n\n### Bug Fixes\n\n* regression on files.add and update deps ([#709](https://github.com/ipfs/js-ipfs-http-client/issues/709)) ([85cc2a8](https://github.com/ipfs/js-ipfs-http-client/commit/85cc2a8))\n* remove argument from .stats.bw* ([#699](https://github.com/ipfs/js-ipfs-http-client/issues/699)) ([f81dce5](https://github.com/ipfs/js-ipfs-http-client/commit/f81dce5))\n\n\n\n<a name=\"18.1.1\"></a>\n## [18.1.1](https://github.com/ipfs/js-ipfs-http-client/compare/v18.0.0...v18.1.1) (2018-02-20)\n\n\n### Features\n\n* support recursive ipfs ls  ([cfe95f6](https://github.com/ipfs/js-ipfs-http-client/commit/cfe95f6))\n\n\n\n<a name=\"18.1.0\"></a>\n# [18.1.0](https://github.com/ipfs/js-ipfs-http-client/compare/v18.0.0...v18.1.0) (2018-02-20)\n\n\n### Features\n\n* support recursive ipfs ls  ([cfe95f6](https://github.com/ipfs/js-ipfs-http-client/commit/cfe95f6))\n\n\n\n<a name=\"18.0.0\"></a>\n# [18.0.0](https://github.com/ipfs/js-ipfs-http-client/compare/v17.5.0...v18.0.0) (2018-02-14)\n\n\n### Bug Fixes\n\n* exception when dir is empty ([#680](https://github.com/ipfs/js-ipfs-http-client/issues/680)) ([ec04f6e](https://github.com/ipfs/js-ipfs-http-client/commit/ec04f6e))\n* support all the Buffer shims and load fixtures correctly ([066988f](https://github.com/ipfs/js-ipfs-http-client/commit/066988f))\n* update stats API ([#684](https://github.com/ipfs/js-ipfs-http-client/issues/684)) ([4f7999d](https://github.com/ipfs/js-ipfs-http-client/commit/4f7999d))\n\n\n### Features\n\n* (breaking change) stats spec, spec repo, stream to value on files read ([#679](https://github.com/ipfs/js-ipfs-http-client/issues/679)) ([118456e](https://github.com/ipfs/js-ipfs-http-client/commit/118456e))\n* **breaking change:** use stream on stats.bw ([#686](https://github.com/ipfs/js-ipfs-http-client/issues/686)) ([895760e](https://github.com/ipfs/js-ipfs-http-client/commit/895760e))\n* ipfs.stop ([5091115](https://github.com/ipfs/js-ipfs-http-client/commit/5091115))\n\n\n\n<a name=\"17.5.0\"></a>\n# [17.5.0](https://github.com/ipfs/js-ipfs-http-client/compare/v17.3.0...v17.5.0) (2018-01-24)\n\n\n### Bug Fixes\n\n* normalize stats fields ([#669](https://github.com/ipfs/js-ipfs-http-client/issues/669)) ([5803d39](https://github.com/ipfs/js-ipfs-http-client/commit/5803d39))\n\n\n### Features\n\n* /api/v0/repo/version ([#676](https://github.com/ipfs/js-ipfs-http-client/issues/676)) ([ecf70b9](https://github.com/ipfs/js-ipfs-http-client/commit/ecf70b9))\n* integrate new ipfsd-ctl ([2b1820b](https://github.com/ipfs/js-ipfs-http-client/commit/2b1820b))\n\n\n\n<a name=\"17.4.0\"></a>\n# [17.4.0](https://github.com/ipfs/js-ipfs-http-client/compare/v17.3.0...v17.4.0) (2018-01-24)\n\n\n### Bug Fixes\n\n* normalize stats fields ([#669](https://github.com/ipfs/js-ipfs-http-client/issues/669)) ([5803d39](https://github.com/ipfs/js-ipfs-http-client/commit/5803d39))\n\n\n### Features\n\n* integrate new ipfsd-ctl ([2b1820b](https://github.com/ipfs/js-ipfs-http-client/commit/2b1820b))\n\n\n\n<a name=\"17.3.0\"></a>\n# [17.3.0](https://github.com/ipfs/js-ipfs-http-client/compare/v17.2.7...v17.3.0) (2018-01-12)\n\n\n### Features\n\n* /api/v0/dns ([#665](https://github.com/ipfs/js-ipfs-http-client/issues/665)) ([81016bb](https://github.com/ipfs/js-ipfs-http-client/commit/81016bb))\n\n\n\n<a name=\"17.2.7\"></a>\n## [17.2.7](https://github.com/ipfs/js-ipfs-http-client/compare/v17.2.6...v17.2.7) (2018-01-11)\n\n\n### Bug Fixes\n\n* name and key tests ([#661](https://github.com/ipfs/js-ipfs-http-client/issues/661)) ([5ab1d02](https://github.com/ipfs/js-ipfs-http-client/commit/5ab1d02))\n\n\n### Features\n\n* normalize KEY API ([#659](https://github.com/ipfs/js-ipfs-http-client/issues/659)) ([1b10821](https://github.com/ipfs/js-ipfs-http-client/commit/1b10821))\n* normalize NAME API ([#658](https://github.com/ipfs/js-ipfs-http-client/issues/658)) ([9b8ef48](https://github.com/ipfs/js-ipfs-http-client/commit/9b8ef48))\n\n\n\n<a name=\"17.2.6\"></a>\n## [17.2.6](https://github.com/ipfs/js-ipfs-http-client/compare/v17.2.5...v17.2.6) (2017-12-28)\n\n\n### Features\n\n* support key/export and key/import ([#653](https://github.com/ipfs/js-ipfs-http-client/issues/653)) ([496f08e](https://github.com/ipfs/js-ipfs-http-client/commit/496f08e))\n\n\n\n<a name=\"17.2.5\"></a>\n## [17.2.5](https://github.com/ipfs/js-ipfs-http-client/compare/v17.2.4...v17.2.5) (2017-12-20)\n\n\n### Bug Fixes\n\n* **files.add:** handle weird directory names ([#646](https://github.com/ipfs/js-ipfs-http-client/issues/646)) ([012b86c](https://github.com/ipfs/js-ipfs-http-client/commit/012b86c))\n\n\n### Features\n\n* add files/flush ([#643](https://github.com/ipfs/js-ipfs-http-client/issues/643)) ([5c254eb](https://github.com/ipfs/js-ipfs-http-client/commit/5c254eb))\n* support key/rm and key/rename ([#641](https://github.com/ipfs/js-ipfs-http-client/issues/641)) ([113030a](https://github.com/ipfs/js-ipfs-http-client/commit/113030a))\n\n\n\n<a name=\"17.2.4\"></a>\n## [17.2.4](https://github.com/ipfs/js-ipfs-http-client/compare/v17.2.3...v17.2.4) (2017-12-06)\n\n\n### Bug Fixes\n\n* stats/bw uses stream ([#640](https://github.com/ipfs/js-ipfs-http-client/issues/640)) ([c4e922e](https://github.com/ipfs/js-ipfs-http-client/commit/c4e922e))\n\n\n\n<a name=\"17.2.3\"></a>\n## [17.2.3](https://github.com/ipfs/js-ipfs-http-client/compare/v17.2.2...v17.2.3) (2017-12-05)\n\n\n\n<a name=\"17.2.2\"></a>\n## [17.2.2](https://github.com/ipfs/js-ipfs-http-client/compare/v17.2.1...v17.2.2) (2017-12-05)\n\n\n\n<a name=\"17.2.1\"></a>\n## [17.2.1](https://github.com/ipfs/js-ipfs-http-client/compare/v17.2.0...v17.2.1) (2017-12-05)\n\n\n### Features\n\n* add the stat commands ([#639](https://github.com/ipfs/js-ipfs-http-client/issues/639)) ([76c3068](https://github.com/ipfs/js-ipfs-http-client/commit/76c3068))\n\n\n\n<a name=\"17.2.0\"></a>\n# [17.2.0](https://github.com/ipfs/js-ipfs-http-client/compare/v17.1.3...v17.2.0) (2017-12-01)\n\n\n### Bug Fixes\n\n* propagate trailer errors correctly ([#636](https://github.com/ipfs/js-ipfs-http-client/issues/636)) ([62d733e](https://github.com/ipfs/js-ipfs-http-client/commit/62d733e))\n\n\n\n<a name=\"17.1.3\"></a>\n## [17.1.3](https://github.com/ipfs/js-ipfs-http-client/compare/v17.1.2...v17.1.3) (2017-11-23)\n\n\n\n<a name=\"17.1.2\"></a>\n## [17.1.2](https://github.com/ipfs/js-ipfs-http-client/compare/v17.1.1...v17.1.2) (2017-11-22)\n\n\n### Bug Fixes\n\n* config.replace ([#634](https://github.com/ipfs/js-ipfs-http-client/issues/634)) ([79d79c5](https://github.com/ipfs/js-ipfs-http-client/commit/79d79c5)), closes [#633](https://github.com/ipfs/js-ipfs-http-client/issues/633)\n\n\n\n<a name=\"17.1.1\"></a>\n## [17.1.1](https://github.com/ipfs/js-ipfs-http-client/compare/v17.1.0...v17.1.1) (2017-11-22)\n\n\n### Bug Fixes\n\n* pubsub do not eat error messages ([#632](https://github.com/ipfs/js-ipfs-http-client/issues/632)) ([5a1bf9b](https://github.com/ipfs/js-ipfs-http-client/commit/5a1bf9b))\n\n\n\n<a name=\"17.1.0\"></a>\n# [17.1.0](https://github.com/ipfs/js-ipfs-http-client/compare/v17.0.1...v17.1.0) (2017-11-20)\n\n\n### Features\n\n* send files HTTP request should stream ([#629](https://github.com/ipfs/js-ipfs-http-client/issues/629)) ([dae62cb](https://github.com/ipfs/js-ipfs-http-client/commit/dae62cb))\n\n\n\n<a name=\"17.0.1\"></a>\n## [17.0.1](https://github.com/ipfs/js-ipfs-http-client/compare/v17.0.0...v17.0.1) (2017-11-20)\n\n\n### Bug Fixes\n\n* allow topicCIDs from older peers ([#631](https://github.com/ipfs/js-ipfs-http-client/issues/631)) ([fe7cc22](https://github.com/ipfs/js-ipfs-http-client/commit/fe7cc22))\n\n\n\n<a name=\"17.0.0\"></a>\n# [17.0.0](https://github.com/ipfs/js-ipfs-http-client/compare/v16.0.0...v17.0.0) (2017-11-17)\n\n\n### Features\n\n* Implementing the new interfaces ([#619](https://github.com/ipfs/js-ipfs-http-client/issues/619)) ([e1b38bf](https://github.com/ipfs/js-ipfs-http-client/commit/e1b38bf))\n\n\n\n<a name=\"16.0.0\"></a>\n# [16.0.0](https://github.com/ipfs/js-ipfs-http-client/compare/v15.1.0...v16.0.0) (2017-11-16)\n\n\n### Bug Fixes\n\n* pubsub message fields ([#627](https://github.com/ipfs/js-ipfs-http-client/issues/627)) ([470777d](https://github.com/ipfs/js-ipfs-http-client/commit/470777d))\n\n\n\n<a name=\"15.1.0\"></a>\n# [15.1.0](https://github.com/ipfs/js-ipfs-http-client/compare/v15.0.2...v15.1.0) (2017-11-14)\n\n\n### Bug Fixes\n\n* adapting HTTP API to the interface-ipfs-core spec ([#625](https://github.com/ipfs/js-ipfs-http-client/issues/625)) ([8e58225](https://github.com/ipfs/js-ipfs-http-client/commit/8e58225))\n\n\n### Features\n\n* windows interop ([#624](https://github.com/ipfs/js-ipfs-http-client/issues/624)) ([40557d0](https://github.com/ipfs/js-ipfs-http-client/commit/40557d0))\n\n\n\n<a name=\"15.0.2\"></a>\n## [15.0.2](https://github.com/ipfs/js-ipfs-http-client/compare/v15.0.1...v15.0.2) (2017-11-13)\n\n\n\n<a name=\"15.0.1\"></a>\n## [15.0.1](https://github.com/ipfs/js-ipfs-http-client/compare/v15.0.0...v15.0.1) (2017-10-22)\n\n\n\n<a name=\"15.0.0\"></a>\n# [15.0.0](https://github.com/ipfs/js-ipfs-http-client/compare/v14.3.7...v15.0.0) (2017-10-22)\n\n\n### Features\n\n* update pin API to match interface-ipfs-core ([9102643](https://github.com/ipfs/js-ipfs-http-client/commit/9102643))\n\n\n\n<a name=\"14.3.7\"></a>\n## [14.3.7](https://github.com/ipfs/js-ipfs-http-client/compare/v14.3.6...v14.3.7) (2017-10-18)\n\n\n\n<a name=\"14.3.6\"></a>\n## [14.3.6](https://github.com/ipfs/js-ipfs-http-client/compare/v14.3.5...v14.3.6) (2017-10-18)\n\n\n### Bug Fixes\n\n* pass the config protocol to http requests ([#609](https://github.com/ipfs/js-ipfs-http-client/issues/609)) ([38d7289](https://github.com/ipfs/js-ipfs-http-client/commit/38d7289))\n\n\n### Features\n\n* avoid doing multiple RPC requests for files.add, fixes [#522](https://github.com/ipfs/js-ipfs-http-client/issues/522) ([#595](https://github.com/ipfs/js-ipfs-http-client/issues/595)) ([0ea5f57](https://github.com/ipfs/js-ipfs-http-client/commit/0ea5f57))\n* report progress on ipfs add  ([e2d894c](https://github.com/ipfs/js-ipfs-http-client/commit/e2d894c))\n\n\n\n<a name=\"14.3.5\"></a>\n## [14.3.5](https://github.com/ipfs/js-ipfs-http-client/compare/v14.3.4...v14.3.5) (2017-09-08)\n\n\n### Features\n\n* Support specify hash algorithm in files.add ([#597](https://github.com/ipfs/js-ipfs-http-client/issues/597)) ([ed68657](https://github.com/ipfs/js-ipfs-http-client/commit/ed68657))\n\n\n\n<a name=\"14.3.4\"></a>\n## [14.3.4](https://github.com/ipfs/js-ipfs-http-client/compare/v14.3.3...v14.3.4) (2017-09-07)\n\n\n\n<a name=\"14.3.3\"></a>\n## [14.3.3](https://github.com/ipfs/js-ipfs-http-client/compare/v14.3.2...v14.3.3) (2017-09-07)\n\n\n### Features\n\n* support options for .add / files.add  ([8c717b2](https://github.com/ipfs/js-ipfs-http-client/commit/8c717b2))\n\n\n\n<a name=\"14.3.2\"></a>\n## [14.3.2](https://github.com/ipfs/js-ipfs-http-client/compare/v14.3.1...v14.3.2) (2017-09-04)\n\n\n### Bug Fixes\n\n* new fixed aegir ([93ac472](https://github.com/ipfs/js-ipfs-http-client/commit/93ac472))\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "# Contributing\n\n## Setup\n\nYou should have [node.js] and [npm] installed.\n\n## Linting\n\nLinting is done using [eslint] and the rules are based on [standard].\n\n```bash\n$ npm run lint\n```\n\n## Tests\n\nTests in node\n\n```bash\n$ npm run test:node\n```\n\nTests in the browser\n\n```bash\n$ npm run test:browser\n```\n\n### Writing a new core interface test\n\nThe core interface tests are kept in a separate repo, because they are used by multiple other projects. To add a core interface test, follow this guide:\n\n1. Clone this project repo and the interface core tests repo:\n    * `git clone https://github.com/ipfs/js-ipfs-http-client.git`\n    * `git clone https://github.com/ipfs/interface-js-ipfs-core.git`\n1. Install dependencies and globally [link](https://docs.npmjs.com/cli/link) the interface core tests:\n    * `cd interface-js-ipfs-core`\n    * `npm install`\n    * `npm link`\n1. Write your test\n1. Install dependencies for this project and link to the interface core tests\n    * `cd ../js-ipfs-http-client`\n    * `npm install`\n    * `npm link interface-ipfs-core`\n1. Run the tests:\n    * `npm test`\n\nNext:\n\n1. Send a PR to `ipfs/interface-js-ipfs-core` (please also add to the documentation!)\n1. This will be reviewed by a core contributor and they will perform the same steps as above\n1. When merged, a new version of `interface-ipfs-core` will be released\n1. Finally, a PR needs to be created or updated to `ipfs/js-ipfs-http-client` to use the new version\n\n## Building browser version\n\n```bash\n$ npm run build\n```\n\n## Releases\n\nThe `release` task will\n\n1. Run a build\n2. Commit the build\n3. Bump the version in `package.json`\n4. Commit the version change\n5. Create a git tag\n6. Run `git push` to `upstream/master` (You can change this with `--remote my-remote`)\n\n```bash\n# Major release\n$ npm run release-major\n# Minor relase\n$ npm run release-minor\n# Patch release\n$ npm run release\n```\n\n[node.js]: https://nodejs.org/\n[npm]: http://npmjs.org/\n[eslint]: http://eslint.org/\n[standard]: https://github.com/feross/standard\n"
  },
  {
    "path": "COPYRIGHT",
    "content": "This project is transitioning from an MIT-only license to a dual MIT/Apache-2.0 license.\nUnless otherwise noted, all code contributed prior to 2019-11-26 and not contributed by\na user listed in [this signoff issue](https://github.com/ipfs/js-ipfs-http-client/issues/1189) is\nlicensed under MIT-only. All new contributions (and past contributions since 2019-11-29)\nare licensed under a dual MIT/Apache-2.0 license.\n"
  },
  {
    "path": "LICENSE-APACHE",
    "content": "Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use this file except in compliance with the License. You may obtain a copy of the License at\n\nhttp://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software distributed under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.\n"
  },
  {
    "path": "LICENSE-MIT",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2016 Protocol Labs, Inc.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\n"
  },
  {
    "path": "README.md",
    "content": "# 🔒 Archived <!-- omit in toc -->\n\nThe contents of this repo have been merged into [ipfs/js-ipfs](https://github.com/ipfs/js-ipfs).\n\nPlease open [issues](https://github.com/ipfs/js-ipfs/issues) or submit [PRs](https://github.com/ipfs/js-ipfs/pulls) there.\n\n<h1 align=\"center\">\n  <a href=\"https://ipfs.io\"><img width=\"650px\" src=\"https://ipfs.io/ipfs/QmQJ68PFMDdAsgCZvA1UVzzn18asVcf7HVvCDgpjiSCAse\" alt=\"IPFS http client lib logo\" /></a>\n</h1>\n\n<h3 align=\"center\">The JavaScript HTTP client library for IPFS implementations.</h3>\n\n<p align=\"center\">\n  <a href=\"http://ipn.io\"><img src=\"https://img.shields.io/badge/made%20by-Protocol%20Labs-blue.svg?style=flat-square\" /></a>\n  <a href=\"http://ipfs.io/\"><img src=\"https://img.shields.io/badge/project-IPFS-blue.svg?style=flat-square\" /></a>\n  <a href=\"http://webchat.freenode.net/?channels=%23ipfs\"><img src=\"https://img.shields.io/badge/freenode-%23ipfs-blue.svg?style=flat-square\" /></a>\n  <a href=\"https://waffle.io/ipfs/js-ipfs\"><img src=\"https://img.shields.io/badge/pm-waffle-blue.svg?style=flat-square\" /></a>\n  <a href=\"https://github.com/ipfs/interface-ipfs-core\"><img src=\"https://img.shields.io/badge/interface--ipfs--core-API%20Docs-blue.svg?style=flat-square\"></a>\n</p>\n\n<p align=\"center\">\n  <a href=\"https://app.fossa.io/projects/git%2Bhttps%3A%2F%2Fgithub.com%2Fipfs%2Fjs-ipfs-http-client?ref=badge_small\" alt=\"FOSSA Status\"><img src=\"https://app.fossa.io/api/projects/git%2Bhttps%3A%2F%2Fgithub.com%2Fipfs%2Fjs-ipfs-http-client.svg?type=small\"/></a>\n  <a href=\"https://travis-ci.com/ipfs/js-ipfs-http-client\"><img src=\"https://flat.badgen.net/travis/ipfs/js-ipfs-http-client\" /></a>\n  <a href=\"https://codecov.io/gh/ipfs/js-ipfs-http-client\"><img src=\"https://img.shields.io/codecov/c/github/ipfs/js-ipfs-http-client/master.svg?style=flat-square\"></a>\n   <a href=\"https://bundlephobia.com/result?p=ipfs-http-client\"><img src=\"https://flat.badgen.net/bundlephobia/minzip/ipfs-http-client\"></a>\n  <br>\n  <a href=\"https://david-dm.org/ipfs/js-ipfs-http-client\"><img src=\"https://david-dm.org/ipfs/js-ipfs-http-client.svg?style=flat-square\" /></a>\n  <a href=\"https://github.com/feross/standard\"><img src=\"https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat-square\"></a>\n  <a href=\"https://github.com/RichardLitt/standard-readme\"><img src=\"https://img.shields.io/badge/standard--readme-OK-green.svg?style=flat-square\" /></a>\n  <a href=\"\"><img src=\"https://img.shields.io/badge/npm-%3E%3D3.0.0-orange.svg?style=flat-square\" /></a>\n  <a href=\"\"><img src=\"https://img.shields.io/badge/Node.js-%3E%3D10.0.0-orange.svg?style=flat-square\" /></a>\n  <br>\n</p>\n\n> A client library for the IPFS HTTP API, implemented in JavaScript. This client library implements the [interface-ipfs-core](https://github.com/ipfs/interface-ipfs-core) enabling applications to change between an embedded js-ipfs node and any remote IPFS node without having to change the code. In addition, this client library implements a set of utility functions.\n\n## Lead Maintainer\n\n[Alan Shaw](http://github.com/alanshaw).\n\n## Table of Contents\n\n- [Lead Maintainer](#lead-maintainer)\n- [Table of Contents](#table-of-contents)\n- [Install](#install)\n  - [Running the daemon with the right port](#running-the-daemon-with-the-right-port)\n  - [Importing the module and usage](#importing-the-module-and-usage)\n  - [Importing a sub-module and usage](#importing-a-sub-module-and-usage)\n  - [In a web browser](#in-a-web-browser)\n  - [CORS](#cors)\n  - [Custom Headers](#custom-headers)\n  - [Global Timeouts](#global-timeouts)\n- [Usage](#usage)\n  - [API](#api)\n    - [Files](#files)\n    - [Graph](#graph)\n    - [Network](#network)\n    - [Node Management](#node-management)\n    - [Additional Options](#additional-options)\n    - [Instance Utils](#instance-utils)\n    - [Static Types and Utils](#static-types-and-utils)\n      - [Glob source](#glob-source)\n        - [`globSource(path, [options])`](#globsourcepath-options)\n        - [Example](#example)\n      - [URL source](#url-source)\n        - [`urlSource(url)`](#urlsourceurl)\n        - [Example](#example-1)\n- [Development](#development)\n  - [Testing](#testing)\n- [Contribute](#contribute)\n- [Historical context](#historical-context)\n- [License](#license)\n\n## Install\n\nThis module uses node.js, and can be installed through npm:\n\n```bash\nnpm install --save ipfs-http-client\n```\n\nWe support both the Current and Active LTS versions of Node.js. Please see [nodejs.org](https://nodejs.org/) for what these currently are.\n\n### Running the daemon with the right port\n\nTo interact with the API, you need to have a local daemon running. It needs to be open on the right port. `5001` is the default, and is used in the examples below, but it can be set to whatever you need.\n\n```sh\n# Show the ipfs config API port to check it is correct\n> ipfs config Addresses.API\n/ip4/127.0.0.1/tcp/5001\n# Set it if it does not match the above output\n> ipfs config Addresses.API /ip4/127.0.0.1/tcp/5001\n# Restart the daemon after changing the config\n\n# Run the daemon\n> ipfs daemon\n```\n\n### Importing the module and usage\n\n```javascript\nconst ipfsClient = require('ipfs-http-client')\n\n// connect to ipfs daemon API server\nconst ipfs = ipfsClient('http://localhost:5001') // (the default in Node.js)\n\n// or connect with multiaddr\nconst ipfs = ipfsClient('/ip4/127.0.0.1/tcp/5001')\n\n// or using options\nconst ipfs = ipfsClient({ host: 'localhost', port: '5001', protocol: 'http' })\n\n// or specifying a specific API path\nconst ipfs = ipfsClient({ host: '1.1.1.1', port: '80', apiPath: '/ipfs/api/v0' })\n```\n\n### Importing a sub-module and usage\n\n```javascript\nconst bitswap = require('ipfs-http-client/src/bitswap')('/ip4/127.0.0.1/tcp/5001')\n\nconst list = await bitswap.wantlist(key)\n// ...\n```\n\n### In a web browser\n\n**through Browserify**\n\nSame as in Node.js, you just have to [browserify](http://browserify.org) the code before serving it. See the browserify repo for how to do that.\n\nSee the example in the [examples folder](/examples/bundle-browserify) to get a boilerplate.\n\n**through webpack**\n\nSee the example in the [examples folder](/examples/bundle-webpack) to get an idea on how to use `js-ipfs-http-client` with webpack.\n\n**from CDN**\n\nInstead of a local installation (and browserification) you may request a remote copy of IPFS API from [unpkg CDN](https://unpkg.com/).\n\nTo always request the latest version, use the following:\n\n```html\n<script src=\"https://unpkg.com/ipfs-http-client/dist/index.min.js\"></script>\n```\n\nNote: remove the `.min` from the URL to get the human-readable (not minified) version.\n\nFor maximum security you may also decide to:\n\n* reference a specific version of IPFS API (to prevent unexpected breaking changes when a newer latest version is published)\n* [generate a SRI hash](https://www.srihash.org/) of that version and use it to ensure integrity\n* set the [CORS settings attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/CORS_settings_attributes) to make anonymous requests to CDN\n\nExample:\n\n```html\n<script src=\"https://unpkg.com/ipfs-http-client@9.0.0/dist/index.js\"\nintegrity=\"sha384-5bXRcW9kyxxnSMbOoHzraqa7Z0PQWIao+cgeg327zit1hz5LZCEbIMx/LWKPReuB\"\ncrossorigin=\"anonymous\"></script>\n```\n\nCDN-based IPFS API provides the `IpfsHttpClient` constructor as a method of the global `window` object. Example:\n\n```js\nconst ipfs = window.IpfsHttpClient({ host: 'localhost', port: 5001 })\n```\n\nIf you omit the host and port, the client will parse `window.host`, and use this information. This also works, and can be useful if you want to write apps that can be run from multiple different gateways:\n\n```js\nconst ipfs = window.IpfsHttpClient()\n```\n\n### CORS\n\nIn a web browser IPFS HTTP client (either browserified or CDN-based) might encounter an error saying that the origin is not allowed. This would be a CORS (\"Cross Origin Resource Sharing\") failure: IPFS servers are designed to reject requests from unknown domains by default. You can whitelist the domain that you are calling from by changing your ipfs config like this:\n\n```console\n$ ipfs config --json API.HTTPHeaders.Access-Control-Allow-Origin  '[\"http://example.com\"]'\n$ ipfs config --json API.HTTPHeaders.Access-Control-Allow-Methods '[\"PUT\", \"POST\", \"GET\"]'\n```\n\n### Custom Headers\n\nIf you wish to send custom headers with each request made by this library, for example, the Authorization header. You can use the config to do so:\n\n```js\nconst ipfs = ipfsClient({\n  host: 'localhost',\n  port: 5001,\n  protocol: 'http',\n  headers: {\n    authorization: 'Bearer ' + TOKEN\n  }\n})\n```\n\n### Global Timeouts\n\nTo set a global timeout for _all_ requests pass a value for the `timeout` option:\n\n```js\n// Timeout after 10 seconds\nconst ipfs = ipfsClient({ timeout: 10000 })\n// Timeout after 2 minutes\nconst ipfs = ipfsClient({ timeout: '2m' })\n// see https://www.npmjs.com/package/parse-duration for valid string values\n```\n\n## Usage\n\n### API\n\n[![IPFS Core API Compatible](https://cdn.rawgit.com/ipfs/interface-ipfs-core/master/img/badge.svg)](https://github.com/ipfs/interface-ipfs-core)\n\n> `js-ipfs-http-client` follows the spec defined by [`interface-ipfs-core`](https://github.com/ipfs/interface-ipfs-core), which concerns the interface to expect from IPFS implementations. This interface is a currently active endeavor. You can use it today to consult the methods available.\n\n#### Files\n\n- [Regular Files API](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md)\n  - [`ipfs.add(data, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#add)\n  - [`ipfs.cat(ipfsPath, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#cat)\n  - [`ipfs.get(ipfsPath, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#get)\n  - [`ipfs.ls(ipfsPath)`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#ls)\n- [MFS (mutable file system) specific](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#mutable-file-system)\n  - [`ipfs.files.cp([from, to])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#filescp)\n  - [`ipfs.files.flush([path])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#filesflush)\n  - [`ipfs.files.ls([path], [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#filesls)\n  - [`ipfs.files.mkdir(path, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#filesmkdir)\n  - [`ipfs.files.mv([from, to])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#filesmv)\n  - [`ipfs.files.read(path, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#filesread)\n  - [`ipfs.files.rm(path, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#filesrm)\n  - [`ipfs.files.stat(path, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#filesstat)\n  - [`ipfs.files.write(path, content, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#fileswrite)\n  _Explore the Mutable File System through interactive coding challenges in our [ProtoSchool tutorial](https://proto.school/#/mutable-file-system/)._\n\n- [block](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/BLOCK.md)\n  - [`ipfs.block.get(cid, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/BLOCK.md#blockget)\n  - [`ipfs.block.put(block, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/BLOCK.md#blockput)\n  - [`ipfs.block.stat(cid)`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/BLOCK.md#blockstat)\n\n- [refs](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/REFS.md)\n  - [`ipfs.refs(ipfsPath, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/REFS.md#refs)\n  - [`ipfs.refs.local()`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/REFS.md#refslocal)\n\n#### Graph\n\n- [dag](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/DAG.md)\n  - [`ipfs.dag.get(cid, [path], [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/DAG.md#dagget)\n  - [`ipfs.dag.put(dagNode, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/DAG.md#dagput)\n  - [`ipfs.dag.tree(cid, [path], [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/DAG.md#dagtree)\n  _Explore the DAG API through interactive coding challenges in our [ProtoSchool tutorial](https://proto.school/#/basics)._\n\n- [object](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/OBJECT.md)\n  - [`ipfs.object.data(multihash, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/OBJECT.md#objectdata)\n  - [`ipfs.object.get(multihash, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/OBJECT.md#objectget)\n  - [`ipfs.object.links(multihash, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/OBJECT.md#objectlinks)\n  - [`ipfs.object.new([template])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/OBJECT.md#objectnew)\n  - [`ipfs.object.patch.addLink(multihash, DAGLink, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/OBJECT.md#objectpatchaddlink)\n  - [`ipfs.object.patch.appendData(multihash, data, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/OBJECT.md#objectpatchappenddata)\n  - [`ipfs.object.patch.rmLink(multihash, DAGLink, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/OBJECT.md#objectpatchrmlink)\n  - [`ipfs.object.patch.setData(multihash, data, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/OBJECT.md#objectpatchsetdata)\n  - [`ipfs.object.put(obj, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/OBJECT.md#objectput)\n  - [`ipfs.object.stat(multihash, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/OBJECT.md#objectstat)\n\n- [pin](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/PIN.md)\n  - [`ipfs.pin.add(hash, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/PIN.md#pinadd)\n  - [`ipfs.pin.ls([hash], [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/PIN.md#pinls)\n  - [`ipfs.pin.rm(hash, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/PIN.md#pinrm)\n\n#### Network\n\n- [bootstrap](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/BOOTSTRAP.md)\n  - [`ipfs.bootstrap.add(addr, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/BOOTSTRAP.md#bootstrapadd)\n  - [`ipfs.bootstrap.list()`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/BOOTSTRAP.md#bootstraplist)\n  - [`ipfs.bootstrap.rm(addr, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/BOOTSTRAP.md#bootstraprm)\n\n- [bitswap](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/BITSWAP.md)\n  - [`ipfs.bitswap.stat()`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/BITSWAP.md#bitswapstat)\n  - [`ipfs.bitswap.wantlist([peerId])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/BITSWAP.md#bitswapwantlist)\n  - [`ipfs.bitswap.unwant(cid)`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/BITSWAP.md#bitswapunwant)\n\n- [dht](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/DHT.md)\n  - [`ipfs.dht.findPeer(peerId)`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/DHT.md#dhtfindpeer)\n  - [`ipfs.dht.findProvs(hash)`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/DHT.md#dhtfindprovs)\n  - [`ipfs.dht.get(key)`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/DHT.md#dhtget)\n  - [`ipfs.dht.provide(cid)`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/DHT.md#dhtprovide)\n  - [`ipfs.dht.put(key, value)`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/DHT.md#dhtput)\n\n- [pubsub](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/PUBSUB.md)\n  - [`ipfs.pubsub.ls(topic)`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/PUBSUB.md#pubsubls)\n  - [`ipfs.pubsub.peers(topic)`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/PUBSUB.md#pubsubpeers)\n  - [`ipfs.pubsub.publish(topic, data)`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/PUBSUB.md#pubsubpublish)\n  - [`ipfs.pubsub.subscribe(topic, handler, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/PUBSUB.md#pubsubsubscribe)\n  - [`ipfs.pubsub.unsubscribe(topic, handler)`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/PUBSUB.md#pubsubunsubscribe)\n\n- [swarm](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/SWARM.md)\n  - [`ipfs.swarm.addrs()`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/SWARM.md#swarmaddrs)\n  - [`ipfs.swarm.connect(addr)`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/SWARM.md#swarmconnect)\n  - [`ipfs.swarm.disconnect(addr)`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/SWARM.md#swarmdisconnect)\n  - [`ipfs.swarm.peers([options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/SWARM.md#swarmpeers)\n\n- [name](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/NAME.md)\n  - [`ipfs.name.publish(addr, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/NAME.md#namepublish)\n  - [`ipfs.name.pubsub.cancel(arg)`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/NAME.md#namepubsubcancel)\n  - [`ipfs.name.pubsub.state()`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/NAME.md#namepubsubstate)\n  - [`ipfs.name.pubsub.subs()`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/NAME.md#namepubsubsubs)\n  - [`ipfs.name.resolve(addr, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/NAME.md#nameresolve)\n\n#### Node Management\n\n- [miscellaneous operations](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/MISCELLANEOUS.md)\n  - [`ipfs.dns(domain)`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/MISCELLANEOUS.md#dns)\n  - [`ipfs.id()`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/MISCELLANEOUS.md#id)\n  - [`ipfs.ping(id, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/MISCELLANEOUS.md#ping)\n  - [`ipfs.stop()`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/MISCELLANEOUS.md#stop). Alias to `ipfs.shutdown`.\n  - [`ipfs.version()`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/MISCELLANEOUS.md#version)\n\n- [config](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/CONFIG.md)\n  - [`ipfs.config.get([key])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/CONFIG.md#configget)\n  - [`ipfs.config.replace(config)`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/CONFIG.md#configreplace)\n  - [`ipfs.config.set(key, value)`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/CONFIG.md#configset)\n  - [`ipfs.config.profiles.list()`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/CONFIG.md#configprofileslist)\n  - [`ipfs.config.profiles.apply(name, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/CONFIG.md#configprofilesapply)\n\n- [stats](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/STATS.md)\n  - [`ipfs.stats.bitswap()`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/STATS.md#statsbitswap)\n  - [`ipfs.stats.bw([options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/STATS.md#statsbw)\n  - [`ipfs.stats.repo([options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/STATS.md#statsrepo)\n\n- log\n  - `ipfs.log.level(subsystem, level, [options])`\n  - `ipfs.log.ls()`\n  - `ipfs.log.tail()`\n\n- [repo](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/REPO.md)\n  - [`ipfs.repo.gc([options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/REPO.md#repogc)\n  - [`ipfs.repo.stat([options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/REPO.md#repostat)\n  - [`ipfs.repo.version()`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/REPO.md#repoversion)\n\n- [key](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/KEY.md)\n  - [`ipfs.key.export(name, password)`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/KEY.md#keyexport)\n  - [`ipfs.key.gen(name, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/KEY.md#keygen)\n  - [`ipfs.key.import(name, pem, password)`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/KEY.md#keyimport)\n  - [`ipfs.key.list([options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/KEY.md#keylist)\n  - [`ipfs.key.rename(oldName, newName)`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/KEY.md#keyrename)\n  - [`ipfs.key.rm(name)`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/KEY.md#keyrm)\n\n#### Additional Options\n\nAll core API methods take _additional_ `options` specific to the HTTP API:\n\n* `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.\n* `signal` - An [`AbortSignal`](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal) that can be used to abort the request on demand.\n* `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.\n* `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.\n\n#### Instance Utils\n\n- `ipfs.getEndpointConfig()`\n\nCall this on your client instance to return an object containing the `host`, `port`, `protocol` and `api-path`.\n\n#### Static Types and Utils\n\nAside from the default export, `ipfs-http-client` exports various types and utilities that are included in the bundle:\n\n- [`Buffer`](https://www.npmjs.com/package/buffer)\n- [`multiaddr`](https://www.npmjs.com/package/multiaddr)\n- [`multibase`](https://www.npmjs.com/package/multibase)\n- [`multicodec`](https://www.npmjs.com/package/multicodec)\n- [`multihash`](https://www.npmjs.com/package/multihashes)\n- [`CID`](https://www.npmjs.com/package/cids)\n- [`globSource`](https://github.com/ipfs/js-ipfs-utils/blob/master/src/files/glob-source.js) (not available in the browser)\n- [`urlSource`](https://github.com/ipfs/js-ipfs-utils/blob/master/src/files/url-source.js)\n\nThese can be accessed like this, for example:\n\n```js\nconst { CID } = require('ipfs-http-client')\n// ...or from an es-module:\nimport { CID } from 'ipfs-http-client'\n```\n\n##### Glob source\n\nA utility to allow files on the file system to be easily added to IPFS.\n\n###### `globSource(path, [options])`\n\n- `path`: A path to a single file or directory to glob from\n- `options`: Optional options\n- `options.recursive`: If `path` is a directory, use option `{ recursive: true }` to add the directory and all its sub-directories.\n- `options.ignore`: To exclude file globs from the directory, use option `{ ignore: ['ignore/this/folder/**', 'and/this/file'] }`.\n- `options.hidden`: Hidden/dot files (files or folders starting with a `.`, for example, `.git/`) are not included by default. To add them, use the option `{ hidden: true }`.\n\nReturns an async iterable that yields `{ path, content }` objects suitable for passing to `ipfs.add`.\n\n###### Example\n\n```js\nconst IpfsHttpClient = require('ipfs-http-client')\nconst { globSource } = IpfsHttpClient\nconst ipfs = IpfsHttpClient()\n\nfor await (const file of ipfs.add(globSource('./docs', { recursive: true }))) {\n  console.log(file)\n}\n/*\n{\n  path: 'docs/assets/anchor.js',\n  cid: CID('QmVHxRocoWgUChLEvfEyDuuD6qJ4PhdDL2dTLcpUy3dSC2'),\n  size: 15347\n}\n{\n  path: 'docs/assets/bass-addons.css',\n  cid: CID('QmPiLWKd6yseMWDTgHegb8T7wVS7zWGYgyvfj7dGNt2viQ'),\n  size: 232\n}\n...\n*/\n```\n\n##### URL source\n\nA utility to allow content from the internet to be easily added to IPFS.\n\n###### `urlSource(url)`\n\n- `url`: A string URL or [`URL`](https://developer.mozilla.org/en-US/docs/Web/API/URL) instance to send HTTP GET request to\n\nReturns an async iterable that yields `{ path, content }` objects suitable for passing to `ipfs.add`.\n\n###### Example\n\n```js\nconst IpfsHttpClient = require('ipfs-http-client')\nconst { urlSource } = IpfsHttpClient\nconst ipfs = IpfsHttpClient()\n\nfor await (const file of ipfs.add(urlSource('https://ipfs.io/images/ipfs-logo.svg'))) {\n  console.log(file)\n}\n/*\n{\n  path: 'ipfs-logo.svg',\n  cid: CID('QmTqZhR6f7jzdhLgPArDPnsbZpvvgxzCZycXK7ywkLxSyU'),\n  size: 3243\n}\n*/\n```\n\n## Development\n\n### Testing\n\nWe run tests by executing `npm test` in a terminal window. This will run both Node.js and Browser tests, both in Chrome and PhantomJS. To ensure that the module conforms with the [`interface-ipfs-core`](https://github.com/ipfs/interface-ipfs-core) spec, we run the batch of tests provided by the interface module, which can be found [here](https://github.com/ipfs/interface-ipfs-core/tree/master/js/src).\n\n## Contribute\n\nThe js-ipfs-http-client is a work in progress. As such, there's a few things you can do right now to help out:\n\n- **[Check out the existing issues](https://github.com/ipfs/js-ipfs-http-client/issues)**!\n- **Perform code reviews**. More eyes will help a) speed the project along b) ensure quality and c) reduce possible future bugs.\n- **Add tests**. There can never be enough tests. Note that interface tests exist inside [`interface-ipfs-core`](https://github.com/ipfs/interface-ipfs-core/tree/master/js/src).\n- **Contribute to the [FAQ repository](https://github.com/ipfs/faq/issues)** with any questions you have about IPFS or any of the relevant technology. A good example would be asking, 'What is a merkledag tree?'. If you don't know a term, odds are, someone else doesn't either. Eventually, we should have a good understanding of where we need to improve communications and teaching together to make IPFS and IPNS better.\n\n**Want to hack on IPFS?**\n\n[![](https://cdn.rawgit.com/jbenet/contribute-ipfs-gif/master/img/contribute.gif)](https://github.com/ipfs/community/blob/master/CONTRIBUTING.md)\n\n## Historical context\n\nThis module started as a direct mapping from the go-ipfs cli to a JavaScript implementation, although this was useful and familiar to a lot of developers that were coming to IPFS for the first time, it also created some confusion on how to operate the core of IPFS and have access to the full capacity of the protocol. After much consideration, we decided to create `interface-ipfs-core` with the goal of standardizing the interface of a core implementation of IPFS, and keep the utility functions the IPFS community learned to use and love, such as reading files from disk and storing them directly to IPFS.\n\n## License\n\n[MIT](LICENSE)\n\n[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bhttps%3A%2F%2Fgithub.com%2Fipfs%2Fjs-ipfs-http-client.svg?type=large)](https://app.fossa.io/projects/git%2Bhttps%3A%2F%2Fgithub.com%2Fipfs%2Fjs-ipfs-http-client?ref=badge_large)\n"
  },
  {
    "path": "examples/browser-pubsub/.gitignore",
    "content": "bundle.js\n"
  },
  {
    "path": "examples/browser-pubsub/README.md",
    "content": "# Pubsub in the browser\n\n> Use pubsub in the browser!\n\nThis example is a demo web application that allows you to connect to an IPFS node, subscribe to a pubsub topic and send/receive messages. We'll start two IPFS nodes and two browsers and use the `ipfs-http-client` to instruct each node to listen to a pubsub topic and send/receive pubsub messages to/from each other. We're aiming for something like this:\n\n```\n   +-----------+                   +-----------+\n   |           +------------------->           |\n   |  js-ipfs  |      pubsub       |  go-ipfs  |\n   |           <-------------------+           |\n   +-----^-----+                   +-----^-----+\n         |                               |\n         | HTTP API                      | HTTP API\n         |                               |\n+-------------------+         +-------------------+\n+-------------------+         +-------------------+\n|                   |         |                   |\n|                   |         |                   |\n|     Browser 1     |         |     Browser 2     |\n|                   |         |                   |\n|                   |         |                   |\n|                   |         |                   |\n+-------------------+         +-------------------+\n```\n\n## 1. Get started\n\nWith Node.js and git installed, clone the repo and install the project dependencies:\n\n```sh\ngit clone https://github.com/ipfs/js-ipfs-http-client.git\ncd js-ipfs-http-client\nnpm install # Installs ipfs-http-client dependencies\ncd examples/browser-pubsub\nnpm install # Installs browser-pubsub app dependencies\n```\n\nStart the example application:\n\n```sh\nnpm start\n```\n\nYou should see something similar to the following in your terminal and the web app should now be available if you navigate to http://127.0.0.1:8888 using your browser:\n\n```sh\nStarting up http-server, serving ./\nAvailable on:\n  http://127.0.0.1:8888\n```\n\n## 2. Start two IPFS nodes\n\nTo demonstrate pubsub we need two nodes running so pubsub messages can be passed between them.\n\nRight now the easiest way to do this is to install and start a `js-ipfs` and `go-ipfs` node. There are other ways to do this, see [this document on running multiple nodes](https://github.com/ipfs/js-ipfs/tree/master/examples/running-multiple-nodes) for details.\n\n### Install and start the JS IPFS node\n\n```sh\nnpm install -g ipfs\njsipfs init\n# Configure CORS to allow ipfs-http-client to access this IPFS node\njsipfs config --json API.HTTPHeaders.Access-Control-Allow-Origin '[\"http://127.0.0.1:8888\"]'\n# Start the IPFS node, enabling pubsub\njsipfs daemon\n```\n\n### Install and start the Go IPFS node\n\nHead over to https://dist.ipfs.io/#go-ipfs and hit the \"Download go-ipfs\" button. Extract the archive and read the instructions to install.\n\nAfter installation:\n\n```sh\nipfs init\n# Configure CORS to allow ipfs-http-client to access this IPFS node\nipfs config --json API.HTTPHeaders.Access-Control-Allow-Origin '[\"http://127.0.0.1:8888\"]'\n# Start the IPFS node, enabling pubsub\nipfs daemon --enable-pubsub-experiment\n```\n\n## 3. Open two browsers and connect to each node\n\nNow, open up **two** browser windows. This could be two tabs in the same browser or two completely different browsers, it doesn't matter. Navigate to http://127.0.0.1:8888 in both.\n\nIn the \"API ADDR\" field enter `/ip4/127.0.0.1/tcp/5001` in one browser and `/ip4/127.0.0.1/tcp/5002` in the other and hit the \"Connect\" button.\n\nThis connects each browser to an IPFS node and now from the comfort of our browser we can instruct each node to listen to a pubsub topic and send/receive pubsub messages to each other.\n\n> N.B. Since our two IPFS nodes are running on the same network they should have already found each other by MDNS. So you probably won't need to use the \"CONNECT TO PEER\" field. If you find your pubsub messages aren't getting through, check the output from your `jsipfs daemon` command and find the first address listed in \"Swarm listening on\" - it'll look like `/ip4/127.0.0.1/tcp/4002/ipfs/Qm...`. Paste this address into the \"CONNECT TO PEER\" field for the browser that is connected to your go-ipfs node and hit connect.\n\nFinally, use the \"SUBSCRIBE TO PUBSUB TOPIC\" and \"SEND MESSAGE\" fields to do some pubsub-ing, you should see messages sent from one browser appear in the log of the other (provided they're both subscribed to the same topic).\n"
  },
  {
    "path": "examples/browser-pubsub/index.html",
    "content": "<!doctype html>\n<html>\n<head>\n  <title>Pubsub in the browser</title>\n  <link rel=\"stylesheet\" href=\"https://unpkg.com/tachyons@4.10.0/css/tachyons.min.css\"/>\n  <link rel=\"stylesheet\" href=\"https://unpkg.com/ipfs-css@0.12.0/ipfs.css\">\n</head>\n<body class=\"sans-serif\">\n  <header class=\"pv3 ph2 ph3-l bg-navy cf mb4\">\n    <a href=\"https://ipfs.io/\" title=\"ipfs.io\">\n      <img src=\"https://ipfs.io/images/ipfs-logo.svg\" class=\"v-mid\" style=\"height:50px\">\n    </a>\n    <h1 class=\"aqua fw2 montserrat dib ma0 pv2 ph1 v-mid fr f3 lh-copy\">Pubsub</h1>\n  </header>\n  <div class=\"ph3 mb3\">\n    <div class=\"fw2 tracked ttu f6 teal-muted mb2\">API Addr</div>\n    <input id=\"api-url\" value=\"/ip4/127.0.0.1/tcp/5001\" class=\"dib w-50 ph1 pv2 monospace input-reset ba b--black-20 border-box\" placeholder=\"e.g. /ip4/127.0.0.1/tcp/5001\" />\n    <button id=\"node-connect\" class=\"dib ph3 pv2 input-reset ba b--black-20 border-box\">Connect</button>\n  </div>\n  <div class=\"ph3 mb3\">\n    <div class=\"fw2 tracked ttu f6 teal-muted mb2\">Connect to peer</div>\n    <input id=\"peer-addr\" class=\"dib w-50 ph1 pv2 monospace input-reset ba b--black-20 border-box\" placeholder=\"e.g. /ip4/127.0.0.1/tcp/4002/ipfs/QmPeerId\" />\n    <button id=\"peer-connect\" class=\"dib ph3 pv2 input-reset ba b--black-20 border-box\">Connect</button>\n  </div>\n  <div class=\"ph3 mb3\">\n    <div class=\"fw2 tracked ttu f6 teal-muted mb2\">Subscribe to pubsub topic</div>\n    <input id=\"topic\" class=\"dib w-50 ph1 pv2 monospace input-reset ba b--black-20 border-box\" placeholder=\"e.g. books\" />\n    <button id=\"subscribe\" class=\"dib ph3 pv2 input-reset ba b--black-20 border-box\">Subscribe</button>\n  </div>\n  <div class=\"ph3 mb3\">\n    <div class=\"fw2 tracked ttu f6 teal-muted mb2\">Send pubsub message</div>\n    <input id=\"message\" class=\"dib w-50 ph1 pv2 monospace input-reset ba b--black-20 border-box\" />\n    <button id=\"send\" class=\"dib ph3 pv2 input-reset ba b--black-20 border-box\">Send</button>\n  </div>\n  <div class=\"ph3 mb3\">\n    <div class=\"fw2 tracked ttu f6 teal-muted mb2\">Console</div>\n    <div id=\"console\" class=\"f7 db w-100 ph1 pv2 monospace input-reset ba b--black-20 border-box overflow-scroll\" style=\"height: 300px\">\n    </div>\n  </div>\n  <script src=\"index.js\"></script>\n</body>\n</html>\n"
  },
  {
    "path": "examples/browser-pubsub/index.js",
    "content": "'use strict'\n\nconst IpfsHttpClient = require('ipfs-http-client')\nconst { sleep, Logger, onEnterPress, catchAndLog } = require('./util')\n\nasync function main () {\n  const apiUrlInput = document.getElementById('api-url')\n  const nodeConnectBtn = document.getElementById('node-connect')\n\n  const peerAddrInput = document.getElementById('peer-addr')\n  const peerConnectBtn = document.getElementById('peer-connect')\n\n  const topicInput = document.getElementById('topic')\n  const subscribeBtn = document.getElementById('subscribe')\n\n  const messageInput = document.getElementById('message')\n  const sendBtn = document.getElementById('send')\n\n  let log = Logger(document.getElementById('console'))\n  let ipfs\n  let topic\n  let peerId\n\n  async function reset () {\n    if (ipfs && topic) {\n      log(`Unsubscribing from topic ${topic}`)\n      await ipfs.pubsub.unsubscribe(topic)\n    }\n    log = Logger(document.getElementById('console'))\n    topicInput.value = ''\n    topic = null\n    peerId = null\n    ipfs = null\n  }\n\n  async function nodeConnect (url) {\n    await reset()\n    log(`Connecting to ${url}`)\n    ipfs = IpfsHttpClient(url)\n    const { id, agentVersion } = await ipfs.id()\n    peerId = id\n    log(`<span class=\"green\">Success!</span>`)\n    log(`Version ${agentVersion}`)\n    log(`Peer ID ${id}`)\n  }\n\n  async function peerConnect (addr) {\n    if (!addr) throw new Error('Missing peer multiaddr')\n    if (!ipfs) throw new Error('Connect to a node first')\n    log(`Connecting to peer ${addr}`)\n    await ipfs.swarm.connect(addr)\n    log(`<span class=\"green\">Success!</span>`)\n    log('Listing swarm peers...')\n    await sleep()\n    const peers = await ipfs.swarm.peers()\n    peers.forEach(peer => {\n      const fullAddr = `${peer.addr}/ipfs/${peer.peer.toB58String()}`\n      log(`<span class=\"${addr.endsWith(peer.peer.toB58String()) ? 'teal' : ''}\">${fullAddr}</span>`)\n    })\n    log(`(${peers.length} peers total)`)\n  }\n\n  async function subscribe (nextTopic) {\n    if (!nextTopic) throw new Error('Missing topic name')\n    if (!ipfs) throw new Error('Connect to a node first')\n\n    const lastTopic = topic\n\n    if (topic) {\n      topic = null\n      log(`Unsubscribing from topic ${lastTopic}`)\n      await ipfs.pubsub.unsubscribe(lastTopic)\n    }\n\n    log(`Subscribing to ${nextTopic}...`)\n\n    await ipfs.pubsub.subscribe(nextTopic, msg => {\n      const from = msg.from\n      const seqno = msg.seqno.toString('hex')\n      if (from === peerId) return log(`Ignoring message ${seqno} from self`)\n      log(`Message ${seqno} from ${from}:`)\n      try {\n        log(JSON.stringify(msg.data.toString(), null, 2))\n      } catch (_) {\n        log(msg.data.toString('hex'))\n      }\n    }, {\n      onError: (err, fatal) => {\n        if (fatal) {\n          console.error(err)\n          log(`<span class=\"red\">${err.message}</span>`)\n          topic = null\n          log('Resubscribing in 5s...')\n          setTimeout(catchAndLog(() => subscribe(nextTopic), log), 5000)\n        } else {\n          console.warn(err)\n        }\n      }\n    })\n\n    topic = nextTopic\n    log(`<span class=\"green\">Success!</span>`)\n  }\n\n  async function send (msg) {\n    if (!msg) throw new Error('Missing message')\n    if (!topic) throw new Error('Subscribe to a topic first')\n    if (!ipfs) throw new Error('Connect to a node first')\n\n    log(`Sending message to ${topic}...`)\n    await ipfs.pubsub.publish(topic, msg)\n    log(`<span class=\"green\">Success!</span>`)\n  }\n\n  const onNodeConnectClick = catchAndLog(() => nodeConnect(apiUrlInput.value), log)\n  apiUrlInput.addEventListener('keydown', onEnterPress(onNodeConnectClick))\n  nodeConnectBtn.addEventListener('click', onNodeConnectClick)\n\n  const onPeerConnectClick = catchAndLog(() => peerConnect(peerAddrInput.value), log)\n  peerAddrInput.addEventListener('keydown', onEnterPress(onPeerConnectClick))\n  peerConnectBtn.addEventListener('click', onPeerConnectClick)\n\n  const onSubscribeClick = catchAndLog(() => subscribe(topicInput.value), log)\n  topicInput.addEventListener('keydown', onEnterPress(onSubscribeClick))\n  subscribeBtn.addEventListener('click', onSubscribeClick)\n\n  const onSendClick = catchAndLog(async () => {\n    await send(messageInput.value)\n    messageInput.value = ''\n  }, log)\n  messageInput.addEventListener('keydown', onEnterPress(onSendClick))\n  sendBtn.addEventListener('click', onSendClick)\n}\n\nmain()\n"
  },
  {
    "path": "examples/browser-pubsub/package.json",
    "content": "{\n  \"name\": \"browser-pubsub-example\",\n  \"version\": \"0.0.0\",\n  \"description\": \"An example demonstrating pubsub in the browser\",\n  \"private\": true,\n  \"main\": \"index.js\",\n  \"scripts\": {\n    \"start\": \"parcel index.html\"\n  },\n  \"author\": \"Alan Shaw\",\n  \"license\": \"MIT\",\n  \"dependencies\": {\n    \"ipfs-http-client\": \"../../\"\n  },\n  \"browserslist\": [\n    \"last 2 versions and not dead and > 2%\"\n  ],\n  \"devDependencies\": {\n    \"parcel-bundler\": \"^1.12.4\"\n  }\n}\n"
  },
  {
    "path": "examples/browser-pubsub/util.js",
    "content": "exports.sleep = (ms = 1000) => new Promise(resolve => setTimeout(resolve, ms))\n\nexports.Logger = outEl => {\n  outEl.innerHTML = ''\n  return message => {\n    const container = document.createElement('div')\n    container.innerHTML = message\n    outEl.appendChild(container)\n    outEl.scrollTop = outEl.scrollHeight\n  }\n}\n\nexports.onEnterPress = fn => {\n  return e => {\n    if (event.which == 13 || event.keyCode == 13) {\n      e.preventDefault()\n      fn()\n    }\n  }\n}\n\nexports.catchAndLog = (fn, log) => {\n  return async (...args) => {\n    try {\n      await fn(...args)\n    } catch (err) {\n      console.error(err)\n      log(`<span class=\"red\">${err.message}</span>`)\n    }\n  }\n}\n"
  },
  {
    "path": "examples/bundle-webpack/.eslintrc",
    "content": "{\n  \"extends\": \"standard\",\n  \"rules\": {\n    \"react/jsx-uses-react\": 2,\n    \"react/jsx-uses-vars\": 2,\n    \"react/react-in-jsx-scope\": 2\n  },\n  \"plugins\": [\n    \"react\"\n  ]\n}\n"
  },
  {
    "path": "examples/bundle-webpack/.gitignore",
    "content": "node_modules\nnpm-debug.log\n.DS_Store\ndist\n"
  },
  {
    "path": "examples/bundle-webpack/README.md",
    "content": "# Bundle js-ipfs-http-client with Webpack!\n\n> In this example, you will find a boilerplate you can use to guide yourself into bundling js-ipfs-http-client with webpack, so that you can use it in your own web app!\n\n## Setup\n\nAs for any js-ipfs-http-client example, **you need a running IPFS daemon**, you learn how to do that here:\n\n- [Spawn a go-ipfs daemon](https://ipfs.io/docs/getting-started/)\n- [Spawn a js-ipfs daemon](https://github.com/ipfs/js-ipfs#usage)\n\n**Note:** If you load your app from a different domain than the one the daemon is running (most probably), you will need to set up CORS, see https://github.com/ipfs/js-ipfs-http-client#cors to learn how to do that.\n\nA quick (and dirty) way to get it done is:\n\n```bash\n> ipfs config --json API.HTTPHeaders.Access-Control-Allow-Origin \"[\\\"*\\\"]\"\n> ipfs config --json API.HTTPHeaders.Access-Control-Allow-Credentials \"[\\\"true\\\"]\"\n```\n\n## Run this example\n\nOnce the daemon is on, run the following commands within this folder:\n\n```bash\n> npm install\n> npm start\n```\n\nNow open your browser at `http://localhost:3000`\n\nYou should see the following:\n\n![](https://ipfs.io/ipfs/QmZndNLRct3co7h1yVB72S4qfwAwbq7DQghCpWpVQ45jSi/1.png)\n\n"
  },
  {
    "path": "examples/bundle-webpack/index.html",
    "content": "<html>\n  <head>\n    <title>Sample App</title>\n  </head>\n  <body>\n    <div id='root'>\n    </div>\n    <script src=\"/static/bundle.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "examples/bundle-webpack/package.json",
    "content": "{\n  \"name\": \"bundle-webpack\",\n  \"version\": \"1.0.0\",\n  \"description\": \"Bundle js-ipfs-http-client with Webpack\",\n  \"scripts\": {\n    \"start\": \"node server.js\"\n  },\n  \"author\": \"Victor Bjelkholm <victor@ipfs.io>\",\n  \"license\": \"MIT\",\n  \"keywords\": [],\n  \"devDependencies\": {\n    \"@babel/core\": \"^7.2.2\",\n    \"@babel/preset-env\": \"^7.3.1\",\n    \"@babel/preset-react\": \"^7.0.0\",\n    \"babel-loader\": \"^8.0.5\",\n    \"ipfs-http-client\": \"../../\",\n    \"react\": \"~16.8.6\",\n    \"react-dom\": \"~16.8.6\",\n    \"react-hot-loader\": \"~4.8.4\",\n    \"webpack\": \"~4.31.0\",\n    \"webpack-dev-server\": \"~3.3.1\"\n  },\n  \"browserslist\": [\n    \"last 2 versions and not dead and > 2%\"\n  ]\n}\n"
  },
  {
    "path": "examples/bundle-webpack/server.js",
    "content": "'use strict'\nvar webpack = require('webpack')\nvar WebpackDevServer = require('webpack-dev-server')\nvar config = require('./webpack.config')\n\nnew WebpackDevServer(webpack(config), {\n  publicPath: config.output.publicPath,\n  hot: true,\n  historyApiFallback: true\n}).listen(3000, 'localhost', function (err, result) {\n  if (err) {\n    console.log(err)\n  }\n\n  console.log('Listening at localhost:3000')\n})\n"
  },
  {
    "path": "examples/bundle-webpack/src/App.js",
    "content": "'use strict'\nconst React = require('react')\nconst ipfsClient = require('ipfs-http-client')\n\nconst ipfs = ipfsClient('/ip4/127.0.0.1/tcp/5001')\nconst stringToUse = 'hello world from webpacked IPFS'\n\nclass App extends React.Component {\n  constructor (props) {\n    super(props)\n    this.state = {\n      id: null,\n      version: null,\n      protocol_version: null,\n      added_file_hash: null,\n      added_file_contents: null\n    }\n  }\n  async componentDidMount () {\n    const id = await ipfs.id()\n    this.setState({\n      id: id.id,\n      version: id.agentVersion,\n      protocol_version: id.protocolVersion\n    })\n\n    const source = ipfs.add(stringToUse)\n    for await (const file of source) {\n      console.log(\"TCL: App -> forawait -> file\", file)\n      const hash = file.path\n      this.setState({ added_file_hash: hash })\n\n      const source = ipfs.cat(hash)\n      const data = []\n      for await (const chunk of source) {\n        data.push(chunk)\n      }\n      this.setState({ added_file_contents: Buffer.concat(data).toString() })\n    }\n  }\n  render () {\n    return <div style={{ textAlign: 'center' }}>\n      <h1>Everything is working!</h1>\n      <p>Your ID is <strong>{this.state.id}</strong></p>\n      <p>Your IPFS version is <strong>{this.state.version}</strong></p>\n      <p>Your IPFS protocol version is <strong>{this.state.protocol_version}</strong></p>\n      <div>\n        <div>\n          Added a file! <br />\n          {this.state.added_file_hash}\n        </div>\n        <div>\n          Contents of this file: <br />\n          {this.state.added_file_contents}\n        </div>\n      </div>\n    </div>\n  }\n}\nmodule.exports = App\n"
  },
  {
    "path": "examples/bundle-webpack/src/index.js",
    "content": "'use strict'\nconst React = require('react')\nconst ReactDOM = require('react-dom')\nconst App = require('./App')\n\nReactDOM.render(<App />, document.getElementById('root'))\n"
  },
  {
    "path": "examples/bundle-webpack/webpack.config.js",
    "content": "'use strict'\n\nconst path = require('path')\nconst webpack = require('webpack')\n\nmodule.exports = {\n  mode: 'production',\n  devtool: 'eval',\n  entry: [\n    'webpack-dev-server/client?http://localhost:3000',\n    'webpack/hot/only-dev-server',\n    './src/index'\n  ],\n  output: {\n    path: path.join(__dirname, 'dist'),\n    filename: 'bundle.js',\n    publicPath: '/static/'\n  },\n  plugins: [\n    new webpack.HotModuleReplacementPlugin()\n  ],\n  module: {\n    rules: [\n      {\n        test: /\\.js$/,\n        exclude: /node_modules/,\n        use: {\n          loader: 'babel-loader',\n          options: {\n            presets: ['@babel/preset-env', '@babel/preset-react']\n          }\n        }\n      }\n    ]\n  },\n  node: {\n    fs: 'empty',\n    net: 'empty',\n    tls: 'empty'\n  }\n}\n"
  },
  {
    "path": "examples/files-api/files-api.js",
    "content": "/* eslint-disable no-console */\n'use strict'\n\n// Run `ipfs daemon` in your terminal to start the IPFS daemon\n// Look for `API server listening on /ip4/127.0.0.1/tcp/5001`\nconst ipfs = require('../../src')('/ip4/127.0.0.1/tcp/5001')\n\nconst run = async () => {\n  await ipfs.files.write(\n    '/temp/hello-world',\n    Buffer.from('Hello, world!'),\n    { create: true, parents: true }\n  )\n  const source = ipfs.files.ls('/temp')\n\n  for await (const file of source) {\n    console.log(file)\n  }\n}\n\nrun()\n"
  },
  {
    "path": "examples/name-api/.gitignore",
    "content": "bundle.js\n"
  },
  {
    "path": "examples/name-api/README.md",
    "content": "# JS IPFS API - Example Browser - Name\n\n## Setup\n\nInstall [go-ipfs](https://ipfs.io/docs/install/) and start the daemon.\n\nConfigure CORS as suggested by the README https://github.com/ipfs/js-ipfs-http-client#cors\n\n```bash\n> ipfs daemon\n```\n\nthen in this folder run\n\n```bash\n> npm install\n> npm start\n```\n\nand open your browser at `http://localhost:8888`.\n"
  },
  {
    "path": "examples/name-api/index.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <meta charset=\"utf-8\" />\n    <title>JS IPFS API name example</title>\n    <style>\n      .hidden {\n        opacity: 0;\n      }\n\n      form {\n        padding-bottom: 1em;\n      }\n    </style>\n  </head>\n\n  <body>\n    <h1>js-ipfs-http-client</h1>\n    <h2><code>name.publish()</code> and <code>name.resolve()</code></h2>\n    <p id=\"status\" style=\"color: white; padding: .5em; background: blue\">\n      initializing...\n    </p>\n    \n    <form id=\"publish-text\">\n      <h3>Add a new file to IPFS and publish it.</h3>\n      <textarea name=\"text\" placeholder=\"hello, world\" required></textarea>\n      <button type=\"submit\" disabled>Publish</button>\n    </form>\n\n    <form id=\"publish-path\">\n      <h3>Publish an existing file or directory from IPFS.</h3>\n      <input name=\"path\" type=\"text\" placeholder=\"IPFS path\" required/>\n      <button type=\"submit\" disabled>Publish</button>\n    </form>\n\n    <div class=\"results--publish hidden\">\n      <p>\n        Published at <code id=\"publish-result\"></code>\n      </p>\n      <p>\n        <a id=\"publish-gateway-link\">Open with HTTP gateway</a>\n      </p>\n    </div>\n\n    <hr />\n\n    <form id=\"resolve-name\">\n      <h3>Resolve an IPNS name</h3>\n      <input name=\"name\" type=\"text\" placeholder=\"IPNS name\" required />\n      <button type=\"submit\" disabled>Resolve</button>\n    </form>\n    <div class=\"results--resolve hidden\">\n      <p>\n        Resolves to <code id=\"resolve-result\"></code>\n      </p>\n      <p>\n        <a id=\"resolve-gateway-link\">Open with HTTP gateway</a>\n      </p>\n    </div>\n\n    <script src=\"index.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "examples/name-api/index.js",
    "content": "/* eslint-disable no-console */\n'use strict'\nconst ipfsHttp = require('ipfs-http-client')\nconst ipfs = ipfsHttp('/ip4/127.0.0.1/tcp/5001')\n\nconst DOM = {\n  status: document.getElementById('status'),\n  buttons: document.getElementsByTagName('button'),\n  publishNew: document.forms[0],\n  publishPath: document.forms[1],\n  resolveName: document.forms[2],\n  publishResultsDiv: document.querySelector('.results--publish'),\n  resolveResultsDiv: document.querySelector('.results--resolve'),\n  publishResult: document.getElementById('publish-result'),\n  resolveResult: document.getElementById('resolve-result'),\n  publishGatewayLink: document.getElementById('publish-gateway-link'),\n  resolveGatewayLink: document.getElementById('resolve-gateway-link')\n}\n\nconst COLORS = {\n  active: 'blue',\n  success: 'green',\n  error: 'red'\n}\n\nconst IPFS_DOMAIN = 'https://ipfs.io'\n\nconst showStatus = (text, bg) => {\n  DOM.status.innerText = text\n  DOM.status.style.background = bg\n}\n\nconst enableForms = () => {\n  for (const btn of DOM.buttons) {\n    btn.disabled = false\n  }\n}\n\nconst init = () => {\n  ipfs.id()\n    .then(res => {\n      showStatus(`daemon active\\nid: ${res.id}`, COLORS.success)\n      enableForms()\n    })\n    .catch(err => {\n      showStatus('daemon inactive', COLORS.error)\n      console.error(err)\n    })\n}\n\n// Adds a new file to IPFS and publish it\nconst addAndPublish = async (e) => {\n  e.preventDefault()\n\n  const input = e.target.elements.text\n  const buffer = Buffer.from(input.value)\n\n  showStatus('adding to IPFS...', COLORS.active)\n  try {\n    for await (const file of ipfs.add(buffer)) {\n      showStatus('success!', COLORS.success)\n\n      publish(file.path)\n\n      input.value = ''\n    }\n  } catch (err) {\n    showStatus('failed to add the data', COLORS.error)\n    console.error(err)\n  }\n}\n\n// Publishes an IPFS file or directory under your node's identity\nconst publish = (path) => {\n  showStatus('publishing...', COLORS.active)\n  DOM.publishResultsDiv.classList.add('hidden')\n\n  ipfs.name.publish(path)\n    .then(res => {\n      const name = res.name\n      showStatus('success!', COLORS.success)\n      DOM.publishResultsDiv.classList.remove('hidden')\n      DOM.publishResult.innerText = `/ipns/${name}`\n      DOM.publishGatewayLink.href = `${IPFS_DOMAIN}/ipns/${name}`\n    })\n    .catch(err => {\n      showStatus(`error publishing ${path}`, COLORS.error)\n      console.error(err)\n    })\n}\n\n// Resolves an IPNS name\nconst resolve = async (name) => {\n  showStatus('resolving...', COLORS.active)\n  DOM.resolveResultsDiv.classList.add('hidden')\n  try {\n    for await (const path of ipfs.name.resolve(name)) {\n      showStatus('success!', COLORS.success)\n      DOM.resolveResultsDiv.classList.remove('hidden')\n      DOM.resolveResult.innerText = path\n      DOM.resolveGatewayLink.href = `${IPFS_DOMAIN}${path}`\n    }\n  } catch (err) {\n    showStatus(`error resolving ${name}`, COLORS.error)\n    console.error(err)\n  }\n}\n\n// Event listeners\nDOM.publishNew.onsubmit = addAndPublish\n\nDOM.publishPath.onsubmit = (e) => {\n  e.preventDefault()\n  const input = e.target.elements.path\n  publish(input.value)\n  input.value = ''\n}\n\nDOM.resolveName.onsubmit = (e) => {\n  e.preventDefault()\n  const input = e.target.elements.name\n  resolve(input.value)\n  input.value = ''\n}\n\ninit()\n"
  },
  {
    "path": "examples/name-api/package.json",
    "content": "{\n  \"name\": \"js-ipfs-http-client-example-name-publish-resolve\",\n  \"version\": \"1.0.0\",\n  \"description\": \"\",\n  \"main\": \"index.js\",\n  \"scripts\": {\n    \"start\": \"parcel index.html\"\n  },\n  \"author\": \"Tara Vancil <tbvanc@gmail.com>\",\n  \"license\": \"MIT\",\n  \"devDependencies\": {\n    \"parcel-bundler\": \"^1.12.4\"\n  },\n  \"dependencies\": {\n    \"ipfs-http-client\": \"../..\"\n  },\n  \"browserslist\": [\n    \"last 2 versions and not dead and > 2%\"\n  ]\n}\n"
  },
  {
    "path": "examples/sub-module/bundles-size-KBs.csv",
    "content": "name, bundled (KBs), minified (KBs)\nIPFS, 1412.20, 573.44\nadd, 591.17, 198.23\nbitswap, 590.14, 197.96\nblock, 630.50, 216.31\nbootstrap, 590.97, 198.22\ncat, 630.78, 216.41\ncommands, 589.22, 197.59\nconfig, 592.21, 198.93\ndht, 593.86, 199.24\ndiag, 590.31, 198.00\nfiles, 669.07, 235.88\nget, 661.57, 233.16\nid, 589.65, 197.78\nkey, 589.93, 197.86\nlog, 590.74, 198.20\nls, 589.35, 197.63\nmount, 589.53, 197.69\nname, 589.97, 197.88\nobject, 833.17, 307.73\npin, 590.86, 198.22\nping, 589.94, 197.73\npubsub, 595.31, 199.76\nrefs, 589.74, 197.77\nrepo, 589.91, 197.85\nswarm, 1239.42, 498.59\nupdate, 589.79, 197.79\nversion, 589.55, 197.71\n"
  },
  {
    "path": "examples/sub-module/complete-module.js",
    "content": "'use strict'\n\nrequire('../../src')('/ip4/127.0.0.1/tcp/5001')\n"
  },
  {
    "path": "examples/sub-module/modules/add/add.js",
    "content": "'use strict'\n\nrequire('../../../../src/add')('/ip4/127.0.0.1/tcp/5001')\n"
  },
  {
    "path": "examples/sub-module/modules/bitswap/bitswap.js",
    "content": "'use strict'\n\nrequire('../../../../src/bitswap')('/ip4/127.0.0.1/tcp/5001')\n"
  },
  {
    "path": "examples/sub-module/modules/block/block.js",
    "content": "'use strict'\n\nrequire('../../../../src/block')('/ip4/127.0.0.1/tcp/5001')\n"
  },
  {
    "path": "examples/sub-module/modules/bootstrap/bootstrap.js",
    "content": "'use strict'\n\nrequire('../../../../src/bootstrap')('/ip4/127.0.0.1/tcp/5001')\n"
  },
  {
    "path": "examples/sub-module/modules/cat/cat.js",
    "content": "'use strict'\n\nrequire('../../../../src/cat')('/ip4/127.0.0.1/tcp/5001')\n"
  },
  {
    "path": "examples/sub-module/modules/commands/commands.js",
    "content": "'use strict'\n\nrequire('../../../../src/commands')('/ip4/127.0.0.1/tcp/5001')\n"
  },
  {
    "path": "examples/sub-module/modules/config/config.js",
    "content": "'use strict'\n\nrequire('../../../../src/config')('/ip4/127.0.0.1/tcp/5001')\n"
  },
  {
    "path": "examples/sub-module/modules/dht/dht.js",
    "content": "'use strict'\n\nrequire('../../../../src/dht')('/ip4/127.0.0.1/tcp/5001')\n"
  },
  {
    "path": "examples/sub-module/modules/diag/diag.js",
    "content": "'use strict'\n\nrequire('../../../../src/diag')('/ip4/127.0.0.1/tcp/5001')\n"
  },
  {
    "path": "examples/sub-module/modules/files/files.js",
    "content": "'use strict'\n\nrequire('../../../../src/files')('/ip4/127.0.0.1/tcp/5001')\n"
  },
  {
    "path": "examples/sub-module/modules/get/get.js",
    "content": "'use strict'\n\nrequire('../../../../src/get')('/ip4/127.0.0.1/tcp/5001')\n"
  },
  {
    "path": "examples/sub-module/modules/id/id.js",
    "content": "'use strict'\n\nrequire('../../../../src/id')('/ip4/127.0.0.1/tcp/5001')\n"
  },
  {
    "path": "examples/sub-module/modules/key/key.js",
    "content": "'use strict'\n\nrequire('../../../../src/key')('/ip4/127.0.0.1/tcp/5001')\n"
  },
  {
    "path": "examples/sub-module/modules/log/log.js",
    "content": "'use strict'\n\nrequire('../../../../src/log')('/ip4/127.0.0.1/tcp/5001')\n"
  },
  {
    "path": "examples/sub-module/modules/ls/ls.js",
    "content": "'use strict'\n\nrequire('../../../../src/ls')('/ip4/127.0.0.1/tcp/5001')\n"
  },
  {
    "path": "examples/sub-module/modules/mount/mount.js",
    "content": "'use strict'\n\nrequire('../../../../src/mount')('/ip4/127.0.0.1/tcp/5001')\n"
  },
  {
    "path": "examples/sub-module/modules/name/name.js",
    "content": "'use strict'\n\nrequire('../../../../src/name')('/ip4/127.0.0.1/tcp/5001')\n"
  },
  {
    "path": "examples/sub-module/modules/object/object.js",
    "content": "'use strict'\n\nrequire('../../../../src/object')('/ip4/127.0.0.1/tcp/5001')\n"
  },
  {
    "path": "examples/sub-module/modules/pin/pin.js",
    "content": "'use strict'\n\nrequire('../../../../src/pin')('/ip4/127.0.0.1/tcp/5001')\n"
  },
  {
    "path": "examples/sub-module/modules/ping/ping.js",
    "content": "'use strict'\n\nrequire('../../../../src/ping')('/ip4/127.0.0.1/tcp/5001')\n"
  },
  {
    "path": "examples/sub-module/modules/pubsub/pubsub.js",
    "content": "'use strict'\n\nrequire('../../../../src/pubsub')('/ip4/127.0.0.1/tcp/5001')\n"
  },
  {
    "path": "examples/sub-module/modules/refs/refs.js",
    "content": "'use strict'\n\nrequire('../../../../src/refs')('/ip4/127.0.0.1/tcp/5001')\n"
  },
  {
    "path": "examples/sub-module/modules/repo/repo.js",
    "content": "'use strict'\n\nrequire('../../../../src/repo')('/ip4/127.0.0.1/tcp/5001')\n"
  },
  {
    "path": "examples/sub-module/modules/swarm/swarm.js",
    "content": "'use strict'\n\nrequire('../../../../src/swarm')('/ip4/127.0.0.1/tcp/5001')\n"
  },
  {
    "path": "examples/sub-module/modules/update/update.js",
    "content": "'use strict'\n\nrequire('../../../../src/update')('/ip4/127.0.0.1/tcp/5001')\n"
  },
  {
    "path": "examples/sub-module/modules/version/version.js",
    "content": "'use strict'\n\nrequire('../../../../src/version')('/ip4/127.0.0.1/tcp/5001')\n"
  },
  {
    "path": "examples/sub-module/package.json",
    "content": "{\n  \"name\": \"sub-module\",\n  \"version\": \"1.0.0\",\n  \"description\": \"\",\n  \"scripts\": {\n    \"test\": \"echo \\\"Error: no test specified\\\" && exit 1\"\n  },\n  \"author\": \"Nuno Nogueira\",\n  \"license\": \"MIT\",\n  \"devDependencies\": {\n    \"babel-core\": \"^6.25.0\",\n    \"babel-loader\": \"^8.0.5\",\n    \"babel-preset-env\": \"^1.5.2\",\n    \"babili\": \"~0.1.4\",\n    \"webpack\": \"~4.31.0\"\n  }\n}\n"
  },
  {
    "path": "examples/sub-module/test-modules-size.sh",
    "content": "#!/bin/sh\nset -e\n\nmodules=($(ls modules/))\n\necho \"name, bundled (KBs), minified (KBs)\"\n\n# Full IPFS module\nwebpack --display none --config webpack.config.js complete-module.js complete-bundle.js\nbabili complete-bundle.js -o complete-bundle-minified.js\n\nipfsBundleSize=($(wc -c < complete-bundle.js | awk '{b=$1/1024; printf \"%.2f\\n\", b}' | sed 's/,/./g'))\nipfsMinSize=($(wc -c < complete-bundle-minified.js | awk '{b=$1/1024; printf \"%.2f\\n\", b}' | sed 's/,/./g'))\n\necho IPFS, $ipfsBundleSize, $ipfsMinSize\n\nfor module in \"${modules[@]}\"\ndo\n  moduledir=\"modules/$module\"\n  webpack --display none --config webpack.config.js $moduledir/$module.js $moduledir/bundle.js\n  babili $moduledir/bundle.js -o $moduledir/bundle-minified.js\n\n  bundlesize=($(wc -c < $moduledir/bundle.js | awk '{b=$1/1024; printf \"%.2f\\n\", b}' | sed 's/,/./g'))\n  minsize=($(wc -c < $moduledir/bundle-minified.js | awk '{b=$1/1024; printf \"%.2f\\n\", b}' | sed 's/,/./g'))\n  echo $module, $bundlesize, $minsize\ndone\n"
  },
  {
    "path": "examples/sub-module/webpack.config.js",
    "content": "'use strict'\n\nmodule.exports = {\n  module: {\n    loaders: [{\n      test: /\\.js$/,\n      loaders: ['babel-loader']\n    }]\n  },\n  node: {\n    fs: 'empty',\n    net: 'empty',\n    tls: 'empty'\n  }\n}\n"
  },
  {
    "path": "examples/upload-file-via-browser/.gitignore",
    "content": "node_modules\nnpm-debug.log\n.DS_Store\ndist\nyarn.lock"
  },
  {
    "path": "examples/upload-file-via-browser/README.md",
    "content": "# Upload file to IPFS via browser using js-ipfs-http-client\n\n> In this example, you will find a simple React app to upload a file to IPFS via the browser using js-ipfs-http-client and Webpack.\n\n## Setup\n\nAs for any js-ipfs-http-client example, **you need a running IPFS daemon**, you learn how to do that here:\n\n- [Spawn a go-ipfs daemon](https://ipfs.io/docs/getting-started/)\n- [Spawn a js-ipfs daemon](https://github.com/ipfs/js-ipfs#usage)\n\n**Note:** If you load your app from a different domain than the one the daemon is running (most probably), you will need to set up CORS, see https://github.com/ipfs/js-ipfs-http-client#cors to learn how to do that.\n\nA quick (and dirty way to get it done) is:\n\n```bash\n> ipfs config --json API.HTTPHeaders.Access-Control-Allow-Origin \"[\\\"*\\\"]\"\n> ipfs config --json API.HTTPHeaders.Access-Control-Allow-Credentials \"[\\\"true\\\"]\"\n```\n\n## Run this example\n\nOnce the daemon is on, run the following commands within this folder:\n\n```bash\n> npm install\n> npm start\n```\nAfter uploading a file (left screen), and opening the uploaded file (right screen), you should see something like:\n\n> ![App Screenshot](https://github.com/ipfs/js-ipfs-http-client/raw/master/examples/upload-file-via-browser/screenshot.png)\n"
  },
  {
    "path": "examples/upload-file-via-browser/index.html",
    "content": "<html>\n  <head>\n    <title>Sample App</title>\n  </head>\n  <body>\n    <div id='root'>\n    </div>\n    <script src=\"src/index.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "examples/upload-file-via-browser/package.json",
    "content": "{\n  \"name\": \"upload-file-via-browser\",\n  \"version\": \"1.0.0\",\n  \"description\": \"Upload file to IPFS via browser using js-ipfs-http-client with Webpack\",\n  \"scripts\": {\n    \"start\": \"parcel index.html\"\n  },\n  \"author\": \"Harlan T Wood <code@harlantwood.net>\",\n  \"contributors\": [\n    \"Victor Bjelkholm <victor@ipfs.io>\"\n  ],\n  \"license\": \"MIT\",\n  \"dependencies\": {\n    \"ipfs-http-client\": \"../..\"\n  },\n  \"devDependencies\": {\n    \"react\": \"~16.6.3\",\n    \"react-dom\": \"~16.6.3\",\n    \"parcel-bundler\": \"^1.12.4\"\n  },\n  \"browserslist\": [\n    \"last 2 versions and not dead and > 2%\"\n  ]\n}\n"
  },
  {
    "path": "examples/upload-file-via-browser/src/App.js",
    "content": "/* eslint-disable no-console */\n'use strict'\nconst React = require('react')\nconst ipfsClient = require('ipfs-http-client')\n\nclass App extends React.Component {\n  constructor () {\n    super()\n    this.state = {\n      added_file_hash: null\n    }\n    this.ipfs = ipfsClient('/ip4/127.0.0.1/tcp/5001')\n\n    // bind methods\n    this.captureFile = this.captureFile.bind(this)\n    this.saveToIpfs = this.saveToIpfs.bind(this)\n    this.handleSubmit = this.handleSubmit.bind(this)\n  }\n\n  captureFile (event) {\n    event.stopPropagation()\n    event.preventDefault()\n    if (document.getElementById('keepFilename').checked) {\n      this.saveToIpfsWithFilename(event.target.files)\n    } else {\n      this.saveToIpfs(event.target.files)\n    }\n  }\n\n  // Example #1\n  // Add file to IPFS and return a CID\n  async saveToIpfs (files) {\n    const source = this.ipfs.add(\n      [...files],\n      {\n        progress: (prog) => console.log(`received: ${prog}`)\n      }\n    )\n    try {\n      for await (const file of source) {\n        console.log(file)\n        this.setState({ added_file_hash: file.path })\n      }\n    } catch (err) {\n      console.error(err)\n    }\n  }\n\n  // Example #2\n  // Add file to IPFS and wrap it in a directory to keep the original filename\n  async saveToIpfsWithFilename (files) {\n    const file = [...files][0]\n    const fileDetails = {\n      path: file.name,\n      content: file\n    }\n    const options = {\n      wrapWithDirectory: true,\n      progress: (prog) => console.log(`received: ${prog}`)\n    }\n\n    const source = this.ipfs.add(fileDetails, options)\n    try {\n      for await (const file of source) {\n        console.log(file)\n        this.setState({ added_file_hash: file.cid.toString() })\n      }\n    } catch (err) {\n      console.error(err)\n    }\n  }\n\n  handleSubmit (event) {\n    event.preventDefault()\n  }\n\n  render () {\n    return (\n      <div>\n        <form id='captureMedia' onSubmit={this.handleSubmit}>\n          <input type='file' onChange={this.captureFile} /><br/>\n          <label htmlFor='keepFilename'><input type='checkbox' id='keepFilename' name='keepFilename' /> keep filename</label>\n        </form>\n        <div>\n          <a target='_blank'\n            href={'https://ipfs.io/ipfs/' + this.state.added_file_hash}>\n            {this.state.added_file_hash}\n          </a>\n        </div>\n      </div>\n    )\n  }\n}\nmodule.exports = App\n"
  },
  {
    "path": "examples/upload-file-via-browser/src/index.js",
    "content": "/* eslint-disable no-unused-vars */\n'use strict'\nconst React = require('react')\nconst ReactDOM = require('react-dom')\nconst App = require('./App')\n\nReactDOM.render(<App />, document.getElementById('root'))\n"
  },
  {
    "path": "greenkeeper.json",
    "content": "{\n  \"groups\": {\n    \"default\": {\n      \"packages\": [\n        \"package.json\"\n      ]\n    }\n  }\n}\n"
  },
  {
    "path": "maintainer.json",
    "content": "{\n  \"repoLeadMaintainer\": {\n    \"name\": \"Alan Shaw\",\n    \"email\": \"alan.shaw@protocol.ai\",\n    \"username\": \"alanshaw\"\n  },\n  \"workingGroup\": {\n    \"name\": \"JS IPFS\",\n    \"entryPoint\": \"https://github.com/ipfs/js-core\"\n  }\n}\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"ipfs-http-client\",\n  \"version\": \"42.0.0\",\n  \"description\": \"A client library for the IPFS HTTP API\",\n  \"keywords\": [\n    \"ipfs\"\n  ],\n  \"homepage\": \"https://github.com/ipfs/js-ipfs-http-client\",\n  \"bugs\": \"https://github.com/ipfs/js-ipfs-http-client/issues\",\n  \"license\": \"(Apache-2.0 OR MIT)\",\n  \"leadMaintainer\": \"Alan Shaw <alan@tableflip.io>\",\n  \"files\": [\n    \"src\",\n    \"dist\"\n  ],\n  \"main\": \"src/index.js\",\n  \"browser\": {\n    \"./src/add/form-data.js\": \"./src/add/form-data.browser.js\",\n    \"./src/lib/buffer-to-form-data.js\": \"./src/lib/buffer-to-form-data.browser.js\",\n    \"ipfs-utils/src/files/glob-source\": false\n  },\n  \"repository\": \"github:ipfs/js-ipfs-http-client\",\n  \"scripts\": {\n    \"test\": \"aegir test\",\n    \"test:node\": \"aegir test -t node\",\n    \"test:browser\": \"aegir test -t browser\",\n    \"test:webworker\": \"aegir test -t webworker\",\n    \"test:electron-main\": \"aegir test -t electron-main\",\n    \"test:electron-renderer\": \"aegir test -t electron-renderer\",\n    \"test:chrome\": \"aegir test -t browser -t webworker -- --browsers ChromeHeadless\",\n    \"test:firefox\": \"aegir test -t browser -t webworker -- --browsers FirefoxHeadless\",\n    \"lint\": \"aegir lint\",\n    \"build\": \"aegir build\",\n    \"release\": \"aegir release \",\n    \"release-minor\": \"aegir release --type minor \",\n    \"release-major\": \"aegir release --type major \",\n    \"coverage\": \"npx nyc -r html npm run test:node -- --bail\"\n  },\n  \"dependencies\": {\n    \"abort-controller\": \"^3.0.0\",\n    \"bignumber.js\": \"^9.0.0\",\n    \"bs58\": \"^4.0.1\",\n    \"buffer\": \"^5.4.2\",\n    \"cids\": \"~0.7.1\",\n    \"debug\": \"^4.1.0\",\n    \"form-data\": \"^3.0.0\",\n    \"ipfs-block\": \"~0.8.1\",\n    \"ipfs-utils\": \"^0.7.1\",\n    \"ipld-dag-cbor\": \"^0.15.1\",\n    \"ipld-dag-pb\": \"^0.18.2\",\n    \"ipld-raw\": \"^4.0.1\",\n    \"it-tar\": \"^1.1.1\",\n    \"it-to-stream\": \"^0.1.1\",\n    \"iterable-ndjson\": \"^1.1.0\",\n    \"ky\": \"^0.15.0\",\n    \"ky-universal\": \"^0.3.0\",\n    \"merge-options\": \"^2.0.0\",\n    \"multiaddr\": \"^7.2.1\",\n    \"multiaddr-to-uri\": \"^5.1.0\",\n    \"multibase\": \"~0.6.0\",\n    \"multicodec\": \"^1.0.0\",\n    \"multihashes\": \"~0.4.14\",\n    \"parse-duration\": \"^0.1.1\",\n    \"stream-to-it\": \"^0.2.0\"\n  },\n  \"devDependencies\": {\n    \"aegir\": \"^20.4.1\",\n    \"async\": \"^3.1.0\",\n    \"browser-process-platform\": \"~0.1.1\",\n    \"go-ipfs-dep\": \"^0.4.23-3\",\n    \"interface-ipfs-core\": \"^0.131.7\",\n    \"ipfsd-ctl\": \"^3.0.0\",\n    \"it-all\": \"^1.0.1\",\n    \"it-concat\": \"^1.0.0\",\n    \"it-pipe\": \"^1.1.0\",\n    \"nock\": \"^11.7.2\"\n  },\n  \"engines\": {\n    \"node\": \">=10.3.0\",\n    \"npm\": \">=3.0.0\"\n  },\n  \"contributors\": [\n    \"Alan Shaw <alan.shaw@protocol.ai>\",\n    \"Alan Shaw <alan@tableflip.io>\",\n    \"Alex Mingoia <talk@alexmingoia.com>\",\n    \"Alex Potsides <alex@achingbrain.net>\",\n    \"Antonio Tenorio-Fornés <antoniotenorio@ucm.es>\",\n    \"Bruno Barbieri <bbarbieri@delivery.com>\",\n    \"Clemo <flipflopsimsommer@users.noreply.github.com>\",\n    \"Connor Keenan <ckeenan89@gmail.com>\",\n    \"Daniel Constantin <hello@danielconstantin.net>\",\n    \"Danny <dannyid@protonmail.com>\",\n    \"David Braun <David.Braun@Toptal.com>\",\n    \"David Dias <daviddias.p@gmail.com>\",\n    \"Dietrich Ayala <autonome@gmail.com>\",\n    \"Diogo Silva <fsdiogo@gmail.com>\",\n    \"Dmitriy Ryajov <dryajov@gmail.com>\",\n    \"Dmitry Nikulin <dmitr-nikulin@mail.ru>\",\n    \"Donatas Stundys <donatas.stundys@necolt.com>\",\n    \"Fil <fil@rezo.net>\",\n    \"Filip Š <filip.stamcar@hotmail.com>\",\n    \"Francisco Baio Dias <xicombd@gmail.com>\",\n    \"Friedel Ziegelmayer <dignifiedquire@gmail.com>\",\n    \"Gar <gar+gh@danger.computer>\",\n    \"Gavin McDermott <gavinmcdermott@gmail.com>\",\n    \"Gopalakrishna Palem <KrishnaPG@users.noreply.github.com>\",\n    \"Greenkeeper <support@greenkeeper.io>\",\n    \"Haad <haadcode@users.noreply.github.com>\",\n    \"Harlan T Wood <harlantwood@users.noreply.github.com>\",\n    \"Harlan T Wood <code@harlantwood.net>\",\n    \"Henrique Dias <hacdias@gmail.com>\",\n    \"Holodisc <holodiscent@gmail.com>\",\n    \"Hugo Dias <hugomrdias@gmail.com>\",\n    \"Hugo Dias <mail@hugodias.me>\",\n    \"JGAntunes <j.goncalo.antunes@gmail.com>\",\n    \"Jacob Heun <jacobheun@gmail.com>\",\n    \"James Halliday <substack@gmail.com>\",\n    \"Jason Carver <jacarver@linkedin.com>\",\n    \"Jason Papakostas <vith@users.noreply.github.com>\",\n    \"Jeff Downie <JeffDownie@users.noreply.github.com>\",\n    \"Jeromy <why@ipfs.io>\",\n    \"Jeromy <jeromyj@gmail.com>\",\n    \"Jim Pick <jim@protocol.ai>\",\n    \"Joe Turgeon <arithmetric@gmail.com>\",\n    \"Jonathan <jkrone@vt.edu>\",\n    \"Juan Batiz-Benet <juan@benet.ai>\",\n    \"Kevin Wang <kevin@fossa.io>\",\n    \"Kristoffer Ström <kristoffer@rymdkoloni.se>\",\n    \"Marcin Rataj <lidel@lidel.org>\",\n    \"Matt Bell <mappum@gmail.com>\",\n    \"Matt Ober <matt.ober3@gmail.com>\",\n    \"Maxime Lathuilière <k@maxlath.eu>\",\n    \"Michael Bradley <michaelsbradleyjr@gmail.com>\",\n    \"Michael Muré <michael.mure@consensys.net>\",\n    \"Michael Muré <batolettre@gmail.com>\",\n    \"Mikeal Rogers <mikeal.rogers@gmail.com>\",\n    \"Mitar <mitar.git@tnode.com>\",\n    \"Mithgol <getgit@mithgol.ru>\",\n    \"Mohamed Abdulaziz <mohamed@mohamedabdulaziz.com>\",\n    \"Nitin Patel <31539366+niinpatel@users.noreply.github.com>\",\n    \"Nuno Nogueira <nunofmn@gmail.com>\",\n    \"Níckolas Goline <nickolas.goline@gmail.com>\",\n    \"Oli Evans <oli@tableflip.io>\",\n    \"Orie Steele <orie@ohs.io>\",\n    \"Paul Cowgill <pauldavidcowgill@gmail.com>\",\n    \"Pedro Santos <pedro.santos@moxy.studio>\",\n    \"Pedro Santos <pedromiguelsousasantos@hotmail.com>\",\n    \"Pedro Teixeira <i@pgte.me>\",\n    \"Pete Thomas <pete@xminusone.net>\",\n    \"Richard Littauer <richard.littauer@gmail.com>\",\n    \"Richard Schneider <makaretu@gmail.com>\",\n    \"Roman Khafizianov <requilence@gmail.com>\",\n    \"SeungWon <ksw3894@gmail.com>\",\n    \"Stephen Whitmore <stephen.whitmore@gmail.com>\",\n    \"Tara Vancil <tbvanc@gmail.com>\",\n    \"Teri Chadbourne <terichadbourne@users.noreply.github.com>\",\n    \"Travis Person <travis@protocol.ai>\",\n    \"Travis Person <travis.person@gmail.com>\",\n    \"Vasco Santos <vasco.santos@ua.pt>\",\n    \"Vasco Santos <vasco.santos@moxy.studio>\",\n    \"Victor Bjelkholm <victor@typeform.com>\",\n    \"Volker Mische <volker.mische@gmail.com>\",\n    \"Zhiyuan Lin <edsgerlin@gmail.com>\",\n    \"dirkmc <dirkmdev@gmail.com>\",\n    \"dmitriy ryajov <dryajov@dmitriys-MacBook-Pro.local>\",\n    \"elsehow <yes@cosmopol.is>\",\n    \"ethers <ethereum@outlook.com>\",\n    \"greenkeeper[bot] <23040076+greenkeeper[bot]@users.noreply.github.com>\",\n    \"greenkeeper[bot] <greenkeeper[bot]@users.noreply.github.com>\",\n    \"haad <haad@headbanggames.com>\",\n    \"kumavis <kumavis@users.noreply.github.com>\",\n    \"leekt216 <leekt216@gmail.com>\",\n    \"nginnever <ginneversource@gmail.com>\",\n    \"noah the goodra <peterpan0413@live.com>\",\n    \"phillmac <phillmac@users.noreply.github.com>\",\n    \"priecint <tp-dev@seznam.cz>\",\n    \"samuli <samuli@nugg.ad>\",\n    \"sarthak khandelwal <sarthak0906@gmail.com>\",\n    \"shunkin <hiyoko.san.ipod@gmail.com>\",\n    \"victorbjelkholm <victorbjelkholm@gmail.com>\",\n    \"Łukasz Magiera <magik6k@users.noreply.github.com>\",\n    \"Łukasz Magiera <magik6k@gmail.com>\"\n  ]\n}\n"
  },
  {
    "path": "src/add/form-data.browser.js",
    "content": "'use strict'\n/* eslint-env browser */\n\nconst normaliseInput = require('ipfs-utils/src/files/normalise-input')\nconst mtimeToObject = require('../lib/mtime-to-object')\n\nexports.toFormData = async input => {\n  const files = normaliseInput(input)\n  const formData = new FormData()\n  let i = 0\n\n  for await (const file of files) {\n    const headers = {}\n\n    if (file.mtime !== undefined && file.mtime !== null) {\n      const mtime = mtimeToObject(file.mtime)\n\n      if (mtime) {\n        headers.mtime = mtime.secs\n        headers['mtime-nsecs'] = mtime.nsecs\n      }\n    }\n\n    if (file.mode !== undefined && file.mode !== null) {\n      headers.mode = file.mode.toString(8).padStart(4, '0')\n    }\n\n    if (file.content) {\n      // In the browser there's _currently_ no streaming upload, buffer up our\n      // async iterator chunks and append a big Blob :(\n      // One day, this will be browser streams\n      const bufs = []\n      for await (const chunk of file.content) {\n        bufs.push(chunk)\n      }\n\n      formData.append(`file-${i}`, new Blob(bufs, { type: 'application/octet-stream' }), encodeURIComponent(file.path), {\n        header: headers\n      })\n    } else {\n      formData.append(`dir-${i}`, new Blob([], { type: 'application/x-directory' }), encodeURIComponent(file.path), {\n        header: headers\n      })\n    }\n\n    i++\n  }\n\n  return formData\n}\n"
  },
  {
    "path": "src/add/form-data.js",
    "content": "'use strict'\n\nconst FormData = require('form-data')\nconst { Buffer } = require('buffer')\nconst toStream = require('it-to-stream')\nconst normaliseInput = require('ipfs-utils/src/files/normalise-input')\nconst { isElectronRenderer } = require('ipfs-utils/src/env')\nconst mtimeToObject = require('../lib/mtime-to-object')\n\nexports.toFormData = async input => {\n  const files = normaliseInput(input)\n  const formData = new FormData()\n  let i = 0\n\n  for await (const file of files) {\n    const headers = {}\n\n    if (file.mtime !== undefined && file.mtime !== null) {\n      const mtime = mtimeToObject(file.mtime)\n\n      if (mtime) {\n        headers.mtime = mtime.secs\n        headers['mtime-nsecs'] = mtime.nsecs\n      }\n    }\n\n    if (file.mode !== undefined && file.mode !== null) {\n      headers.mode = file.mode.toString(8).padStart(4, '0')\n    }\n\n    if (file.content) {\n      // In Node.js, FormData can be passed a stream so no need to buffer\n      formData.append(\n        `file-${i}`,\n        // FIXME: add a `path` property to the stream so `form-data` doesn't set\n        // a Content-Length header that is only the sum of the size of the\n        // header/footer when knownLength option (below) is null.\n        Object.assign(\n          toStream.readable(file.content),\n          { path: file.path || `file-${i}` }\n        ),\n        {\n          filepath: encodeURIComponent(file.path),\n          contentType: 'application/octet-stream',\n          knownLength: file.content.length, // Send Content-Length header if known\n          header: headers\n        }\n      )\n    } else {\n      formData.append(`dir-${i}`, Buffer.alloc(0), {\n        filepath: encodeURIComponent(file.path),\n        contentType: 'application/x-directory',\n        header: headers\n      })\n    }\n\n    i++\n  }\n\n  return formData\n}\n\n// TODO remove this when upstream fix for ky-universal is merged\n// https://github.com/sindresorhus/ky-universal/issues/9\n// also this should only be necessary when nodeIntegration is false in electron renderer\nif (isElectronRenderer) {\n  exports.toFormData = require('./form-data.browser').toFormData\n}\n"
  },
  {
    "path": "src/add/index.js",
    "content": "'use strict'\n\nconst ndjson = require('iterable-ndjson')\nconst CID = require('cids')\nconst configure = require('../lib/configure')\nconst toIterable = require('stream-to-it/source')\nconst { toFormData } = require('./form-data')\nconst toCamel = require('../lib/object-to-camel')\n\nmodule.exports = configure(({ ky }) => {\n  return async function * add (input, options) {\n    options = options || {}\n\n    const searchParams = new URLSearchParams(options.searchParams)\n\n    searchParams.set('stream-channels', true)\n    if (options.chunker) searchParams.set('chunker', options.chunker)\n    if (options.cidVersion) searchParams.set('cid-version', options.cidVersion)\n    if (options.cidBase) searchParams.set('cid-base', options.cidBase)\n    if (options.enableShardingExperiment != null) searchParams.set('enable-sharding-experiment', options.enableShardingExperiment)\n    if (options.hashAlg) searchParams.set('hash', options.hashAlg)\n    if (options.onlyHash != null) searchParams.set('only-hash', options.onlyHash)\n    if (options.pin != null) searchParams.set('pin', options.pin)\n    if (options.progress) searchParams.set('progress', true)\n    if (options.quiet != null) searchParams.set('quiet', options.quiet)\n    if (options.quieter != null) searchParams.set('quieter', options.quieter)\n    if (options.rawLeaves != null) searchParams.set('raw-leaves', options.rawLeaves)\n    if (options.shardSplitThreshold) searchParams.set('shard-split-threshold', options.shardSplitThreshold)\n    if (options.silent) searchParams.set('silent', options.silent)\n    if (options.trickle != null) searchParams.set('trickle', options.trickle)\n    if (options.wrapWithDirectory != null) searchParams.set('wrap-with-directory', options.wrapWithDirectory)\n    if (options.preload != null) searchParams.set('preload', options.preload)\n    if (options.fileImportConcurrency != null) searchParams.set('file-import-concurrency', options.fileImportConcurrency)\n    if (options.blockWriteConcurrency != null) searchParams.set('block-write-concurrency', options.blockWriteConcurrency)\n\n    const res = await ky.post('add', {\n      timeout: options.timeout,\n      signal: options.signal,\n      headers: options.headers,\n      searchParams,\n      body: await toFormData(input)\n    })\n\n    for await (let file of ndjson(toIterable(res.body))) {\n      file = toCamel(file)\n\n      if (options.progress && file.bytes) {\n        options.progress(file.bytes)\n      } else {\n        yield toCoreInterface(file)\n      }\n    }\n  }\n})\n\nfunction toCoreInterface ({ name, hash, size, mode, mtime, mtimeNsecs }) {\n  const output = {\n    path: name,\n    cid: new CID(hash),\n    size: parseInt(size)\n  }\n\n  if (mode != null) {\n    output.mode = parseInt(mode, 8)\n  }\n\n  if (mtime != null) {\n    output.mtime = {\n      secs: mtime,\n      nsecs: mtimeNsecs || 0\n    }\n  }\n\n  return output\n}\n"
  },
  {
    "path": "src/bitswap/index.js",
    "content": "'use strict'\n\nmodule.exports = config => ({\n  wantlist: require('./wantlist')(config),\n  stat: require('./stat')(config),\n  unwant: require('./unwant')(config)\n})\n"
  },
  {
    "path": "src/bitswap/stat.js",
    "content": "'use strict'\n\nconst configure = require('../lib/configure')\nconst Big = require('bignumber.js')\nconst CID = require('cids')\n\nmodule.exports = configure(({ ky }) => {\n  return async (options) => {\n    options = options || {}\n\n    const res = await ky.post('bitswap/stat', {\n      timeout: options.timeout,\n      signal: options.signal,\n      headers: options.headers,\n      searchParams: options.searchParams\n    }).json()\n\n    return toCoreInterface(res)\n  }\n})\n\nfunction toCoreInterface (res) {\n  return {\n    provideBufLen: res.ProvideBufLen,\n    wantlist: (res.Wantlist || []).map(k => new CID(k['/'])),\n    peers: (res.Peers || []),\n    blocksReceived: new Big(res.BlocksReceived),\n    dataReceived: new Big(res.DataReceived),\n    blocksSent: new Big(res.BlocksSent),\n    dataSent: new Big(res.DataSent),\n    dupBlksReceived: new Big(res.DupBlksReceived),\n    dupDataReceived: new Big(res.DupDataReceived)\n  }\n}\n"
  },
  {
    "path": "src/bitswap/unwant.js",
    "content": "'use strict'\n\nconst CID = require('cids')\nconst configure = require('../lib/configure')\n\nmodule.exports = configure(({ ky }) => {\n  return async (cid, options) => {\n    options = options || {}\n\n    const searchParams = new URLSearchParams(options.searchParams)\n\n    if (typeof cid === 'string') {\n      searchParams.set('arg', cid)\n    } else {\n      searchParams.set('arg', new CID(cid).toString())\n    }\n\n    const res = await ky.post('bitswap/unwant', {\n      timeout: options.timeout,\n      signal: options.signal,\n      headers: options.headers,\n      searchParams\n    }).json()\n\n    return res\n  }\n})\n"
  },
  {
    "path": "src/bitswap/wantlist.js",
    "content": "'use strict'\n\nconst CID = require('cids')\nconst configure = require('../lib/configure')\n\nmodule.exports = configure(({ ky }) => {\n  return async (peerId, options) => {\n    options = options || {}\n\n    const searchParams = new URLSearchParams(options.searchParams)\n\n    if (peerId) {\n      if (typeof peerId === 'string') {\n        searchParams.set('peer', peerId)\n      } else {\n        searchParams.set('peer', new CID(peerId).toString())\n      }\n    }\n\n    const res = await ky.post('bitswap/wantlist', {\n      timeout: options.timeout,\n      signal: options.signal,\n      headers: options.headers,\n      searchParams\n    }).json()\n\n    return (res.Keys || []).map(k => new CID(k['/']))\n  }\n})\n"
  },
  {
    "path": "src/block/get.js",
    "content": "'use strict'\n\nconst Block = require('ipfs-block')\nconst CID = require('cids')\nconst { Buffer } = require('buffer')\nconst configure = require('../lib/configure')\n\nmodule.exports = configure(({ ky }) => {\n  return async (cid, options) => {\n    cid = new CID(cid)\n    options = options || {}\n\n    const searchParams = new URLSearchParams(options.searchParams)\n    searchParams.set('arg', `${cid}`)\n\n    const data = await ky.post('block/get', {\n      timeout: options.timeout,\n      signal: options.signal,\n      headers: options.headers,\n      searchParams\n    }).arrayBuffer()\n\n    return new Block(Buffer.from(data), cid)\n  }\n})\n"
  },
  {
    "path": "src/block/index.js",
    "content": "'use strict'\n\nmodule.exports = config => ({\n  get: require('./get')(config),\n  stat: require('./stat')(config),\n  put: require('./put')(config),\n  rm: require('./rm')(config)\n})\n"
  },
  {
    "path": "src/block/put.js",
    "content": "'use strict'\n\nconst Block = require('ipfs-block')\nconst CID = require('cids')\nconst multihash = require('multihashes')\nconst configure = require('../lib/configure')\nconst toFormData = require('../lib/buffer-to-form-data')\n\nmodule.exports = configure(({ ky }) => {\n  async function put (data, options) {\n    options = options || {}\n\n    if (Block.isBlock(data)) {\n      const { name, length } = multihash.decode(data.cid.multihash)\n      options = {\n        ...options,\n        format: data.cid.codec,\n        mhtype: name,\n        mhlen: length,\n        version: data.cid.version\n      }\n      data = data.data\n    } else if (options.cid) {\n      const cid = new CID(options.cid)\n      const { name, length } = multihash.decode(cid.multihash)\n      options = {\n        ...options,\n        format: cid.codec,\n        mhtype: name,\n        mhlen: length,\n        version: cid.version\n      }\n      delete options.cid\n    }\n\n    const searchParams = new URLSearchParams(options.searchParams)\n    if (options.format) searchParams.set('format', options.format)\n    if (options.mhtype) searchParams.set('mhtype', options.mhtype)\n    if (options.mhlen) searchParams.set('mhlen', options.mhlen)\n    if (options.pin != null) searchParams.set('pin', options.pin)\n    if (options.version != null) searchParams.set('version', options.version)\n\n    let res\n    try {\n      res = await ky.post('block/put', {\n        timeout: options.timeout,\n        signal: options.signal,\n        headers: options.headers,\n        searchParams,\n        body: toFormData(data)\n      }).json()\n    } catch (err) {\n      // Retry with \"protobuf\"/\"cbor\" format for go-ipfs\n      // TODO: remove when https://github.com/ipfs/go-cid/issues/75 resolved\n      if (options.format === 'dag-pb') {\n        return put(data, { ...options, format: 'protobuf' })\n      } else if (options.format === 'dag-cbor') {\n        return put(data, { ...options, format: 'cbor' })\n      }\n\n      throw err\n    }\n\n    return new Block(data, new CID(res.Key))\n  }\n\n  return put\n})\n"
  },
  {
    "path": "src/block/rm.js",
    "content": "'use strict'\n\nconst CID = require('cids')\nconst ndjson = require('iterable-ndjson')\nconst configure = require('../lib/configure')\nconst toIterable = require('stream-to-it/source')\n\nmodule.exports = configure(({ ky }) => {\n  return async function * rm (cid, options) {\n    options = options || {}\n\n    if (!Array.isArray(cid)) {\n      cid = [cid]\n    }\n\n    const searchParams = new URLSearchParams()\n    searchParams.set('stream-channels', true)\n    searchParams.set('force', options.force || false)\n    searchParams.set('quiet', options.quiet || false)\n\n    cid.forEach(cid => {\n      searchParams.append('arg', new CID(cid).toString())\n    })\n\n    const res = await ky.post('block/rm', {\n      timeout: options.timeout,\n      signal: options.signal,\n      headers: options.headers,\n      searchParams\n    })\n\n    for await (const removed of ndjson(toIterable(res.body))) {\n      yield toCoreInterface(removed)\n    }\n  }\n})\n\nfunction toCoreInterface (removed) {\n  const out = {\n    cid: new CID(removed.Hash)\n  }\n\n  if (removed.Error) {\n    out.error = new Error(removed.Error)\n  }\n\n  return out\n}\n"
  },
  {
    "path": "src/block/stat.js",
    "content": "'use strict'\n\nconst CID = require('cids')\nconst { Buffer } = require('buffer')\nconst configure = require('../lib/configure')\n\nmodule.exports = configure(({ ky }) => {\n  return async (cid, options) => {\n    options = options || {}\n\n    if (Buffer.isBuffer(cid)) {\n      cid = new CID(cid)\n    }\n\n    const searchParams = new URLSearchParams(options.searchParams)\n    searchParams.set('arg', `${cid}`)\n\n    const res = await ky.post('block/stat', {\n      timeout: options.timeout,\n      signal: options.signal,\n      headers: options.headers,\n      searchParams\n    }).json()\n\n    return { cid: new CID(res.Key), size: res.Size }\n  }\n})\n"
  },
  {
    "path": "src/bootstrap/add.js",
    "content": "'use strict'\n\nconst Multiaddr = require('multiaddr')\nconst configure = require('../lib/configure')\n\nmodule.exports = configure(({ ky }) => {\n  return async (addr, options) => {\n    if (addr && typeof addr === 'object' && !Multiaddr.isMultiaddr(addr)) {\n      options = addr\n      addr = null\n    }\n\n    options = options || {}\n\n    const searchParams = new URLSearchParams(options.searchParams)\n    if (addr) searchParams.set('arg', `${addr}`)\n    if (options.default != null) searchParams.set('default', options.default)\n\n    const res = await ky.post('bootstrap/add', {\n      timeout: options.timeout,\n      signal: options.signal,\n      headers: options.headers,\n      searchParams\n    }).json()\n\n    return res\n  }\n})\n"
  },
  {
    "path": "src/bootstrap/index.js",
    "content": "'use strict'\n\nmodule.exports = config => ({\n  add: require('./add')(config),\n  rm: require('./rm')(config),\n  list: require('./list')(config)\n})\n"
  },
  {
    "path": "src/bootstrap/list.js",
    "content": "'use strict'\n\nconst configure = require('../lib/configure')\n\nmodule.exports = configure(({ ky }) => {\n  return async (options) => {\n    options = options || {}\n\n    const res = await ky.post('bootstrap/list', {\n      timeout: options.timeout,\n      signal: options.signal,\n      headers: options.headers,\n      searchParams: options.searchParams\n    }).json()\n\n    return res\n  }\n})\n"
  },
  {
    "path": "src/bootstrap/rm.js",
    "content": "'use strict'\n\nconst Multiaddr = require('multiaddr')\nconst configure = require('../lib/configure')\n\nmodule.exports = configure(({ ky }) => {\n  return async (addr, options) => {\n    if (addr && typeof addr === 'object' && !Multiaddr.isMultiaddr(addr)) {\n      options = addr\n      addr = null\n    }\n\n    options = options || {}\n\n    const searchParams = new URLSearchParams(options.searchParams)\n    if (addr) searchParams.set('arg', `${addr}`)\n    if (options.all != null) searchParams.set('all', options.all)\n\n    const res = await ky.post('bootstrap/rm', {\n      timeout: options.timeout,\n      signal: options.signal,\n      headers: options.headers,\n      searchParams\n    }).json()\n\n    return res\n  }\n})\n"
  },
  {
    "path": "src/cat.js",
    "content": "'use strict'\n\nconst CID = require('cids')\nconst { Buffer } = require('buffer')\nconst configure = require('./lib/configure')\nconst toIterable = require('stream-to-it/source')\n\nmodule.exports = configure(({ ky }) => {\n  return async function * cat (path, options) {\n    options = options || {}\n\n    const searchParams = new URLSearchParams(options.searchParams)\n\n    if (typeof path === 'string') {\n      searchParams.set('arg', path)\n    } else {\n      searchParams.set('arg', new CID(path).toString())\n    }\n\n    if (options.offset) searchParams.set('offset', options.offset)\n    if (options.length) searchParams.set('length', options.length)\n\n    const res = await ky.post('cat', {\n      timeout: options.timeout,\n      signal: options.signal,\n      headers: options.headers,\n      searchParams\n    })\n\n    for await (const chunk of toIterable(res.body)) {\n      yield Buffer.from(chunk)\n    }\n  }\n})\n"
  },
  {
    "path": "src/commands.js",
    "content": "'use strict'\n\nconst configure = require('./lib/configure')\n\nmodule.exports = configure(({ ky }) => {\n  return options => {\n    options = options || {}\n\n    const searchParams = new URLSearchParams(options.searchParams)\n    if (options.flags != null) searchParams.set('flags', options.flags)\n\n    return ky.post('commands', {\n      timeout: options.timeout,\n      signal: options.signal,\n      headers: options.headers,\n      searchParams\n    }).json()\n  }\n})\n"
  },
  {
    "path": "src/config/get.js",
    "content": "'use strict'\n\nconst configure = require('../lib/configure')\n\nmodule.exports = configure(({ ky }) => {\n  return async (key, options) => {\n    if (key && typeof key === 'object') {\n      options = key\n      key = null\n    }\n\n    options = options || {}\n\n    const searchParams = new URLSearchParams(options.searchParams)\n    if (key) searchParams.set('arg', key)\n\n    const url = key ? 'config' : 'config/show'\n    const data = await ky.post(url, {\n      timeout: options.timeout,\n      signal: options.signal,\n      headers: options.headers,\n      searchParams\n    }).json()\n\n    return key ? data.Value : data\n  }\n})\n"
  },
  {
    "path": "src/config/index.js",
    "content": "'use strict'\n\nmodule.exports = config => ({\n  get: require('./get')(config),\n  set: require('./set')(config),\n  replace: require('./replace')(config),\n  profiles: require('./profiles')(config)\n})\n"
  },
  {
    "path": "src/config/profiles/apply.js",
    "content": "'use strict'\n\nconst configure = require('../../lib/configure')\n\nmodule.exports = configure(({ ky }) => {\n  return async (profile, options) => {\n    options = options || {}\n\n    const searchParams = new URLSearchParams(options.searchParams)\n    searchParams.set('arg', profile)\n    if (options.dryRun != null) searchParams.set('dry-run', options.dryRun)\n\n    const res = await ky.post('config/profile/apply', {\n      timeout: options.timeout,\n      signal: options.signal,\n      headers: options.headers,\n      searchParams\n    }).json()\n\n    return {\n      original: res.OldCfg, updated: res.NewCfg\n    }\n  }\n})\n"
  },
  {
    "path": "src/config/profiles/index.js",
    "content": "'use strict'\n\nmodule.exports = config => ({\n  apply: require('./apply')(config),\n  list: require('./list')(config)\n})\n"
  },
  {
    "path": "src/config/profiles/list.js",
    "content": "'use strict'\n\nconst configure = require('../../lib/configure')\nconst toCamel = require('../../lib/object-to-camel')\n\nmodule.exports = configure(({ ky }) => {\n  return async (options) => {\n    options = options || {}\n\n    const res = await ky.post('config/profile/list', {\n      timeout: options.timeout,\n      signal: options.signal,\n      headers: options.headers,\n      searchParams: options.searchParams\n    }).json()\n\n    return res.map(profile => toCamel(profile))\n  }\n})\n"
  },
  {
    "path": "src/config/replace.js",
    "content": "'use strict'\n\nconst { Buffer } = require('buffer')\nconst configure = require('../lib/configure')\nconst toFormData = require('../lib/buffer-to-form-data')\n\nmodule.exports = configure(({ ky }) => {\n  return async (config, options) => {\n    options = options || {}\n\n    const res = await ky.post('config/replace', {\n      timeout: options.timeout,\n      signal: options.signal,\n      headers: options.headers,\n      searchParams: options.searchParams,\n      body: toFormData(Buffer.from(JSON.stringify(config)))\n    }).text()\n\n    return res\n  }\n})\n"
  },
  {
    "path": "src/config/set.js",
    "content": "'use strict'\n\nconst configure = require('../lib/configure')\nconst toCamel = require('../lib/object-to-camel')\n\nmodule.exports = configure(({ ky }) => {\n  return async (key, value, options) => {\n    options = options || {}\n\n    if (typeof key !== 'string') {\n      throw new Error('Invalid key type')\n    }\n\n    const searchParams = new URLSearchParams(options.searchParams)\n\n    if (typeof value === 'boolean') {\n      searchParams.set('bool', true)\n      value = value.toString()\n    } else if (typeof value !== 'string') {\n      searchParams.set('json', true)\n      value = JSON.stringify(value)\n    }\n\n    searchParams.set('arg', key)\n    searchParams.append('arg', value)\n\n    const res = await ky.post('config', {\n      timeout: options.timeout,\n      signal: options.signal,\n      headers: options.headers,\n      searchParams\n    }).json()\n\n    return toCamel(res)\n  }\n})\n"
  },
  {
    "path": "src/dag/get.js",
    "content": "'use strict'\n\nconst dagPB = require('ipld-dag-pb')\nconst dagCBOR = require('ipld-dag-cbor')\nconst raw = require('ipld-raw')\nconst configure = require('../lib/configure')\n\nconst resolvers = {\n  'dag-cbor': dagCBOR.resolver,\n  'dag-pb': dagPB.resolver,\n  raw: raw.resolver\n}\n\nmodule.exports = config => {\n  const getBlock = require('../block/get')(config)\n  const dagResolve = require('./resolve')(config)\n\n  return configure(({ ky }) => {\n    return async (cid, path, options) => {\n      if (typeof path === 'object') {\n        options = path\n        path = null\n      }\n\n      options = options || {}\n\n      const resolved = await dagResolve(cid, path, options)\n      const block = await getBlock(resolved.cid, options)\n      const dagResolver = resolvers[block.cid.codec]\n\n      if (!dagResolver) {\n        throw Object.assign(\n          new Error(`Missing IPLD format \"${block.cid.codec}\"`),\n          { missingMulticodec: cid.codec }\n        )\n      }\n\n      return dagResolver.resolve(block.data, resolved.remPath)\n    }\n  })(config)\n}\n"
  },
  {
    "path": "src/dag/index.js",
    "content": "'use strict'\n\nmodule.exports = config => ({\n  get: require('./get')(config),\n  put: require('./put')(config),\n  resolve: require('./resolve')(config)\n})\n"
  },
  {
    "path": "src/dag/put.js",
    "content": "'use strict'\n\nconst dagCBOR = require('ipld-dag-cbor')\nconst CID = require('cids')\nconst multihash = require('multihashes')\nconst configure = require('../lib/configure')\nconst toFormData = require('../lib/buffer-to-form-data')\n\nmodule.exports = configure(({ ky }) => {\n  return async (dagNode, options) => {\n    options = options || {}\n\n    if (options.hash) {\n      options.hashAlg = options.hash\n      delete options.hash\n    }\n\n    if (options.cid && (options.format || options.hashAlg)) {\n      throw new Error('Failed to put DAG node. Provide either `cid` OR `format` and `hashAlg` options')\n    } else if ((options.format && !options.hashAlg) || (!options.format && options.hashAlg)) {\n      throw new Error('Failed to put DAG node. Provide `format` AND `hashAlg` options')\n    }\n\n    if (options.cid) {\n      const cid = new CID(options.cid)\n      options = {\n        ...options,\n        format: cid.codec,\n        hashAlg: multihash.decode(cid.multihash).name\n      }\n      delete options.cid\n    }\n\n    options = {\n      format: 'dag-cbor',\n      hashAlg: 'sha2-256',\n      inputEnc: 'raw',\n      ...options\n    }\n\n    let serialized\n\n    if (options.format === 'dag-cbor') {\n      serialized = dagCBOR.util.serialize(dagNode)\n    } else if (options.format === 'dag-pb') {\n      serialized = dagNode.serialize()\n    } else {\n      // FIXME Hopefully already serialized...can we use IPLD to serialise instead?\n      serialized = dagNode\n    }\n\n    const searchParams = new URLSearchParams(options.searchParams)\n    searchParams.set('format', options.format)\n    searchParams.set('hash', options.hashAlg)\n    searchParams.set('input-enc', options.inputEnc)\n    if (options.pin != null) searchParams.set('pin', options.pin)\n\n    const res = await ky.post('dag/put', {\n      timeout: options.timeout,\n      signal: options.signal,\n      headers: options.headers,\n      searchParams,\n      body: toFormData(serialized)\n    }).json()\n\n    return new CID(res.Cid['/'])\n  }\n})\n"
  },
  {
    "path": "src/dag/resolve.js",
    "content": "'use strict'\n\nconst CID = require('cids')\nconst configure = require('../lib/configure')\n\nmodule.exports = configure(({ ky }) => {\n  return async (cid, path, options) => {\n    if (typeof path === 'object') {\n      options = path\n      path = null\n    }\n\n    options = options || {}\n\n    const cidPath = path\n      ? [cid, path].join(path.startsWith('/') ? '' : '/')\n      : `${cid}`\n\n    const searchParams = new URLSearchParams(options.searchParams)\n    searchParams.set('arg', cidPath)\n\n    const res = await ky.post('dag/resolve', {\n      timeout: options.timeout,\n      signal: options.signal,\n      headers: options.headers,\n      searchParams\n    }).json()\n\n    return { cid: new CID(res.Cid['/']), remPath: res.RemPath }\n  }\n})\n"
  },
  {
    "path": "src/dht/find-peer.js",
    "content": "'use strict'\n\nconst { Buffer } = require('buffer')\nconst CID = require('cids')\nconst multiaddr = require('multiaddr')\nconst ndjson = require('iterable-ndjson')\nconst configure = require('../lib/configure')\nconst toIterable = require('stream-to-it/source')\n\nmodule.exports = configure(({ ky }) => {\n  return async function findPeer (peerId, options) {\n    options = options || {}\n\n    const searchParams = new URLSearchParams(options.searchParams)\n    searchParams.set('arg', `${Buffer.isBuffer(peerId) ? new CID(peerId) : peerId}`)\n    if (options.verbose != null) searchParams.set('verbose', options.verbose)\n\n    const res = await ky.post('dht/findpeer', {\n      timeout: options.timeout,\n      signal: options.signal,\n      headers: options.headers,\n      searchParams\n    })\n\n    for await (const message of ndjson(toIterable(res.body))) {\n      // 3 = QueryError\n      // https://github.com/libp2p/go-libp2p-core/blob/6e566d10f4a5447317a66d64c7459954b969bdab/routing/query.go#L18\n      // https://github.com/ipfs/go-ipfs/blob/eb11f569b064b960d1aba4b5b8ca155a3bd2cb21/core/commands/dht.go#L388-L389\n      if (message.Type === 3) {\n        throw new Error(message.Extra)\n      }\n\n      // 2 = FinalPeer\n      // https://github.com/libp2p/go-libp2p-core/blob/6e566d10f4a5447317a66d64c7459954b969bdab/routing/query.go#L18\n      if (message.Type === 2 && message.Responses) {\n        // There will only be 1:\n        // https://github.com/ipfs/go-ipfs/blob/eb11f569b064b960d1aba4b5b8ca155a3bd2cb21/core/commands/dht.go#L395-L396\n        for (const { ID, Addrs } of message.Responses) {\n          return {\n            id: ID,\n            addrs: (Addrs || []).map(a => multiaddr(a))\n          }\n        }\n      }\n    }\n\n    throw new Error('not found')\n  }\n})\n"
  },
  {
    "path": "src/dht/find-provs.js",
    "content": "'use strict'\n\nconst CID = require('cids')\nconst multiaddr = require('multiaddr')\nconst ndjson = require('iterable-ndjson')\nconst configure = require('../lib/configure')\nconst toIterable = require('stream-to-it/source')\n\nmodule.exports = configure(({ ky }) => {\n  return async function * findProvs (cid, options) {\n    options = options || {}\n\n    const searchParams = new URLSearchParams(options.searchParams)\n    searchParams.set('arg', `${new CID(cid)}`)\n    if (options.numProviders) searchParams.set('num-providers', options.numProviders)\n    if (options.verbose != null) searchParams.set('verbose', options.verbose)\n\n    const res = await ky.post('dht/findprovs', {\n      timeout: options.timeout,\n      signal: options.signal,\n      headers: options.headers,\n      searchParams\n    })\n\n    for await (const message of ndjson(toIterable(res.body))) {\n      // 3 = QueryError\n      // https://github.com/libp2p/go-libp2p-core/blob/6e566d10f4a5447317a66d64c7459954b969bdab/routing/query.go#L18\n      // https://github.com/libp2p/go-libp2p-kad-dht/blob/master/routing.go#L525-L526\n      if (message.Type === 3) {\n        throw new Error(message.Extra)\n      }\n\n      // 4 = Provider\n      // https://github.com/libp2p/go-libp2p-core/blob/6e566d10f4a5447317a66d64c7459954b969bdab/routing/query.go#L20\n      if (message.Type === 4 && message.Responses) {\n        for (const { ID, Addrs } of message.Responses) {\n          yield {\n            id: ID,\n            addrs: (Addrs || []).map(a => multiaddr(a))\n          }\n        }\n      }\n    }\n  }\n})\n"
  },
  {
    "path": "src/dht/get.js",
    "content": "'use strict'\n\nconst { Buffer } = require('buffer')\nconst ndjson = require('iterable-ndjson')\nconst toIterable = require('stream-to-it/source')\nconst encodeBufferURIComponent = require('../lib/encode-buffer-uri-component')\nconst configure = require('../lib/configure')\n\nmodule.exports = configure(({ ky }) => {\n  return async function get (key, options) {\n    options = options || {}\n\n    const searchParams = new URLSearchParams(options.searchParams)\n    if (options.verbose != null) searchParams.set('verbose', options.verbose)\n\n    if (!Buffer.isBuffer(key)) {\n      throw new Error('invalid key')\n    }\n\n    const res = await ky.post(`dht/get?key=${encodeBufferURIComponent(key)}&${searchParams}`, {\n      timeout: options.timeout,\n      signal: options.signal,\n      headers: options.headers\n    })\n\n    for await (const message of ndjson(toIterable(res.body))) {\n      // 3 = QueryError\n      // https://github.com/libp2p/go-libp2p-core/blob/6e566d10f4a5447317a66d64c7459954b969bdab/routing/query.go#L18\n      // https://github.com/ipfs/go-ipfs/blob/eb11f569b064b960d1aba4b5b8ca155a3bd2cb21/core/commands/dht.go#L472-L473\n      if (message.Type === 3) {\n        throw new Error(message.Extra)\n      }\n\n      // 5 = Value\n      // https://github.com/libp2p/go-libp2p-core/blob/6e566d10f4a5447317a66d64c7459954b969bdab/routing/query.go#L21\n      if (message.Type === 5) {\n        return message.Extra\n      }\n    }\n\n    throw new Error('not found')\n  }\n})\n"
  },
  {
    "path": "src/dht/index.js",
    "content": "'use strict'\n\nmodule.exports = config => ({\n  get: require('./get')(config),\n  put: require('./put')(config),\n  findProvs: require('./find-provs')(config),\n  findPeer: require('./find-peer')(config),\n  provide: require('./provide')(config),\n  // find closest peerId to given peerId\n  query: require('./query')(config)\n})\n"
  },
  {
    "path": "src/dht/provide.js",
    "content": "'use strict'\n\nconst CID = require('cids')\nconst multiaddr = require('multiaddr')\nconst ndjson = require('iterable-ndjson')\nconst configure = require('../lib/configure')\nconst toIterable = require('stream-to-it/source')\nconst toCamel = require('../lib/object-to-camel')\n\nmodule.exports = configure(({ ky }) => {\n  return async function * provide (cids, options) {\n    cids = Array.isArray(cids) ? cids : [cids]\n    options = options || {}\n\n    const searchParams = new URLSearchParams(options.searchParams)\n    cids.forEach(cid => searchParams.append('arg', `${new CID(cid)}`))\n    if (options.recursive != null) searchParams.set('recursive', options.recursive)\n    if (options.verbose != null) searchParams.set('verbose', options.verbose)\n\n    const res = await ky.post('dht/provide', {\n      timeout: options.timeout,\n      signal: options.signal,\n      headers: options.headers,\n      searchParams\n    })\n\n    for await (let message of ndjson(toIterable(res.body))) {\n      // 3 = QueryError\n      // https://github.com/libp2p/go-libp2p-core/blob/6e566d10f4a5447317a66d64c7459954b969bdab/routing/query.go#L18\n      // https://github.com/ipfs/go-ipfs/blob/eb11f569b064b960d1aba4b5b8ca155a3bd2cb21/core/commands/dht.go#L283-L284\n      if (message.Type === 3) {\n        throw new Error(message.Extra)\n      }\n\n      message = toCamel(message)\n      message.id = new CID(message.id)\n      if (message.responses) {\n        message.responses = message.responses.map(({ ID, Addrs }) => ({\n          id: ID,\n          addrs: (Addrs || []).map(a => multiaddr(a))\n        }))\n      } else {\n        message.responses = []\n      }\n      yield message\n    }\n  }\n})\n"
  },
  {
    "path": "src/dht/put.js",
    "content": "'use strict'\n\nconst { Buffer } = require('buffer')\nconst CID = require('cids')\nconst multiaddr = require('multiaddr')\nconst ndjson = require('iterable-ndjson')\nconst configure = require('../lib/configure')\nconst toIterable = require('stream-to-it/source')\nconst encodeBufferURIComponent = require('../lib/encode-buffer-uri-component')\nconst toCamel = require('../lib/object-to-camel')\n\nmodule.exports = configure(({ ky }) => {\n  return async function * put (key, value, options) {\n    options = options || {}\n\n    const searchParams = new URLSearchParams(options.searchParams)\n    if (options.verbose != null) searchParams.set('verbose', options.verbose)\n\n    key = Buffer.isBuffer(key) ? encodeBufferURIComponent(key) : encodeURIComponent(key)\n    value = Buffer.isBuffer(value) ? encodeBufferURIComponent(value) : encodeURIComponent(value)\n\n    const url = `dht/put?arg=${key}&arg=${value}&${searchParams}`\n    const res = await ky.post(url, {\n      timeout: options.timeout,\n      signal: options.signal,\n      headers: options.headers\n    })\n\n    for await (let message of ndjson(toIterable(res.body))) {\n      // 3 = QueryError\n      // https://github.com/libp2p/go-libp2p-core/blob/6e566d10f4a5447317a66d64c7459954b969bdab/routing/query.go#L18\n      // https://github.com/ipfs/go-ipfs/blob/eb11f569b064b960d1aba4b5b8ca155a3bd2cb21/core/commands/dht.go#L472-L473\n      if (message.Type === 3) {\n        throw new Error(message.Extra)\n      }\n\n      message = toCamel(message)\n      message.id = new CID(message.id)\n      if (message.responses) {\n        message.responses = message.responses.map(({ ID, Addrs }) => ({\n          id: ID,\n          addrs: (Addrs || []).map(a => multiaddr(a))\n        }))\n      }\n      yield message\n    }\n  }\n})\n"
  },
  {
    "path": "src/dht/query.js",
    "content": "'use strict'\n\nconst CID = require('cids')\nconst ndjson = require('iterable-ndjson')\nconst multiaddr = require('multiaddr')\nconst toIterable = require('stream-to-it/source')\nconst configure = require('../lib/configure')\nconst toCamel = require('../lib/object-to-camel')\n\nmodule.exports = configure(({ ky }) => {\n  return async function * query (peerId, options) {\n    options = options || {}\n\n    const searchParams = new URLSearchParams(options.searchParams)\n    searchParams.set('arg', `${Buffer.isBuffer(peerId) ? new CID(peerId) : peerId}`)\n    if (options.verbose != null) searchParams.set('verbose', options.verbose)\n\n    const res = await ky.post('dht/query', {\n      timeout: options.timeout,\n      signal: options.signal,\n      headers: options.headers,\n      searchParams\n    })\n\n    for await (let message of ndjson(toIterable(res.body))) {\n      message = toCamel(message)\n      message.id = new CID(message.id)\n      message.responses = (message.responses || []).map(({ ID, Addrs }) => ({\n        id: ID,\n        addrs: (Addrs || []).map(a => multiaddr(a))\n      }))\n      yield message\n    }\n  }\n})\n"
  },
  {
    "path": "src/diag/cmds.js",
    "content": "'use strict'\n\nconst configure = require('../lib/configure')\n\nmodule.exports = configure(({ ky }) => {\n  return options => {\n    options = options || {}\n\n    const searchParams = new URLSearchParams(options.searchParams)\n    if (options.verbose != null) searchParams.set('verbose', options.verbose)\n\n    return ky.post('diag/cmds', {\n      timeout: options.timeout,\n      signal: options.signal,\n      headers: options.headers,\n      searchParams\n    }).json()\n  }\n})\n"
  },
  {
    "path": "src/diag/index.js",
    "content": "'use strict'\n\nmodule.exports = config => ({\n  net: require('./net')(config),\n  sys: require('./sys')(config),\n  cmds: require('./cmds')(config)\n})\n"
  },
  {
    "path": "src/diag/net.js",
    "content": "'use strict'\n\nconst configure = require('../lib/configure')\n\nmodule.exports = configure(({ ky }) => {\n  return options => {\n    options = options || {}\n\n    return ky.post('diag/net', {\n      timeout: options.timeout,\n      signal: options.signal,\n      headers: options.headers,\n      searchParams: options.searchParams\n    }).json()\n  }\n})\n"
  },
  {
    "path": "src/diag/sys.js",
    "content": "'use strict'\n\nconst configure = require('../lib/configure')\n\nmodule.exports = configure(({ ky }) => {\n  return options => {\n    options = options || {}\n\n    return ky.post('diag/sys', {\n      timeout: options.timeout,\n      signal: options.signal,\n      headers: options.headers,\n      searchParams: options.searchParams\n    }).json()\n  }\n})\n"
  },
  {
    "path": "src/dns.js",
    "content": "'use strict'\n\nconst configure = require('./lib/configure')\n\nmodule.exports = configure(({ ky }) => {\n  return async (domain, options) => {\n    options = options || {}\n\n    const searchParams = new URLSearchParams(options.searchParams)\n    searchParams.set('arg', domain)\n    if (options.recursive != null) searchParams.set('recursive', options.recursive)\n\n    const res = await ky.post('dns', {\n      timeout: options.timeout,\n      signal: options.signal,\n      headers: options.headers,\n      searchParams\n    }).json()\n\n    return res.Path\n  }\n})\n"
  },
  {
    "path": "src/files/chmod.js",
    "content": "'use strict'\n\nconst configure = require('../lib/configure')\nconst modeToString = require('../lib/mode-to-string')\n\nmodule.exports = configure(({ ky }) => {\n  return function chmod (path, mode, options) {\n    options = options || {}\n\n    const searchParams = new URLSearchParams(options.searchParams)\n    searchParams.append('arg', path)\n    searchParams.append('mode', modeToString(mode))\n    if (options.flush != null) searchParams.set('flush', options.flush)\n    if (options.hashAlg) searchParams.set('hash', options.hashAlg)\n    if (options.parents != null) searchParams.set('parents', options.parents)\n\n    return ky.post('files/chmod', {\n      timeout: options.timeout,\n      signal: options.signal,\n      headers: options.headers,\n      searchParams\n    }).text()\n  }\n})\n"
  },
  {
    "path": "src/files/cp.js",
    "content": "'use strict'\n\nconst CID = require('cids')\nconst configure = require('../lib/configure')\nconst { findSources } = require('./utils')\n\nmodule.exports = configure(({ ky }) => {\n  return (...args) => {\n    const { sources, options } = findSources(args)\n\n    const searchParams = new URLSearchParams(options.searchParams)\n    sources.forEach(src => searchParams.append('arg', CID.isCID(src) ? `/ipfs/${src}` : src))\n    if (options.flush != null) searchParams.set('flush', options.flush)\n    if (options.hashAlg) searchParams.set('hash', options.hashAlg)\n    if (options.parents != null) searchParams.set('parents', options.parents)\n    if (options.shardSplitThreshold != null) searchParams.set('shardSplitThreshold', options.shardSplitThreshold)\n\n    return ky.post('files/cp', {\n      timeout: options.timeout,\n      signal: options.signal,\n      headers: options.headers,\n      searchParams\n    }).text()\n  }\n})\n"
  },
  {
    "path": "src/files/flush.js",
    "content": "'use strict'\n\nconst configure = require('../lib/configure')\nconst CID = require('cids')\n\nmodule.exports = configure(({ ky }) => {\n  return async (path, options) => {\n    if (typeof path !== 'string') {\n      options = path\n      path = '/'\n    }\n\n    options = options || {}\n\n    const searchParams = new URLSearchParams(options.searchParams)\n    searchParams.set('arg', path)\n\n    const res = await ky.post('files/flush', {\n      timeout: options.timeout,\n      signal: options.signal,\n      headers: options.headers,\n      searchParams\n    }).json()\n\n    return new CID(res.Cid)\n  }\n})\n"
  },
  {
    "path": "src/files/index.js",
    "content": "'use strict'\n\nmodule.exports = config => ({\n  chmod: require('./chmod')(config),\n  cp: require('./cp')(config),\n  mkdir: require('./mkdir')(config),\n  flush: require('./flush')(config),\n  stat: require('./stat')(config),\n  rm: require('./rm')(config),\n  ls: require('./ls')(config),\n  read: require('./read')(config),\n  touch: require('./touch')(config),\n  write: require('./write')(config),\n  mv: require('./mv')(config)\n})\n"
  },
  {
    "path": "src/files/ls.js",
    "content": "'use strict'\n\nconst CID = require('cids')\nconst ndjson = require('iterable-ndjson')\nconst toIterable = require('stream-to-it/source')\nconst configure = require('../lib/configure')\nconst toCamelWithMetadata = require('../lib/object-to-camel-with-metadata')\n\nmodule.exports = configure(({ ky }) => {\n  return async function * ls (path, options) {\n    if (typeof path !== 'string') {\n      options = path\n      path = '/'\n    }\n\n    options = options || {}\n\n    const searchParams = new URLSearchParams(options.searchParams)\n    searchParams.set('arg', CID.isCID(path) ? `/ipfs/${path}` : path)\n    searchParams.set('stream', options.stream == null ? true : options.stream)\n    if (options.cidBase) searchParams.set('cid-base', options.cidBase)\n    searchParams.set('long', options.long == null ? true : options.long)\n    // TODO: remove after go-ipfs 0.5 is released\n    searchParams.set('l', options.long == null ? true : options.long)\n\n    const res = await ky.post('files/ls', {\n      timeout: options.timeout,\n      signal: options.signal,\n      headers: options.headers,\n      searchParams\n    })\n\n    for await (const result of ndjson(toIterable(res.body))) {\n      // go-ipfs does not yet support the \"stream\" option\n      if ('Entries' in result) {\n        for (const entry of result.Entries || []) {\n          yield toCoreInterface(toCamelWithMetadata(entry))\n        }\n      } else {\n        yield toCoreInterface(toCamelWithMetadata(result))\n      }\n    }\n  }\n})\n\nfunction toCoreInterface (entry) {\n  if (entry.hash) entry.cid = new CID(entry.hash)\n  delete entry.hash\n  return entry\n}\n"
  },
  {
    "path": "src/files/mkdir.js",
    "content": "'use strict'\n\nconst configure = require('../lib/configure')\nconst modeToString = require('../lib/mode-to-string')\nconst mtimeToObject = require('../lib/mtime-to-object')\n\nmodule.exports = configure(({ ky }) => {\n  return (path, options) => {\n    options = options || {}\n    const mtime = mtimeToObject(options.mtime)\n\n    const searchParams = new URLSearchParams(options.searchParams)\n    searchParams.append('arg', path)\n    if (options.cidVersion != null) searchParams.set('cid-version', options.cidVersion)\n    if (options.flush != null) searchParams.set('flush', options.flush)\n    if (options.hashAlg) searchParams.set('hash', options.hashAlg)\n    if (options.parents != null) searchParams.set('parents', options.parents)\n    if (options.shardSplitThreshold != null) searchParams.set('shardSplitThreshold', options.shardSplitThreshold)\n    if (mtime) {\n      searchParams.set('mtime', mtime.secs)\n\n      if (mtime.nsecs != null) {\n        searchParams.set('mtimeNsecs', mtime.nsecs)\n      }\n    }\n    if (options.mode != null) searchParams.set('mode', modeToString(options.mode))\n\n    return ky.post('files/mkdir', {\n      timeout: options.timeout,\n      signal: options.signal,\n      headers: options.headers,\n      searchParams\n    }).text()\n  }\n})\n"
  },
  {
    "path": "src/files/mv.js",
    "content": "'use strict'\n\nconst CID = require('cids')\nconst configure = require('../lib/configure')\nconst { findSources } = require('./utils')\n\nmodule.exports = configure(({ ky }) => {\n  return (...args) => {\n    const { sources, options } = findSources(args)\n\n    const searchParams = new URLSearchParams(options.searchParams)\n    sources.forEach(src => searchParams.append('arg', CID.isCID(src) ? `/ipfs/${src}` : src))\n    if (options.flush != null) searchParams.set('flush', options.flush)\n    if (options.hashAlg) searchParams.set('hash', options.hashAlg)\n    if (options.parents != null) searchParams.set('parents', options.parents)\n    if (options.shardSplitThreshold != null) searchParams.set('shardSplitThreshold', options.shardSplitThreshold)\n\n    return ky.post('files/mv', {\n      timeout: options.timeout,\n      signal: options.signal,\n      headers: options.headers,\n      searchParams\n    }).text()\n  }\n})\n"
  },
  {
    "path": "src/files/read.js",
    "content": "'use strict'\n\nconst { Buffer } = require('buffer')\nconst configure = require('../lib/configure')\nconst toIterable = require('stream-to-it/source')\n\nmodule.exports = configure(({ ky }) => {\n  return async function * read (path, options) {\n    options = options || {}\n\n    const searchParams = new URLSearchParams(options.searchParams)\n    searchParams.append('arg', `${path}`)\n    if (options.length != null) searchParams.set('length', options.length)\n    if (options.offset != null) searchParams.set('offset', options.offset)\n\n    const res = await ky.post('files/read', {\n      timeout: options.timeout,\n      signal: options.signal,\n      headers: options.headers,\n      searchParams\n    })\n\n    for await (const chunk of toIterable(res.body)) {\n      yield Buffer.from(chunk)\n    }\n  }\n})\n"
  },
  {
    "path": "src/files/rm.js",
    "content": "'use strict'\n\nconst configure = require('../lib/configure')\n\nmodule.exports = configure(({ ky }) => {\n  return (path, options) => {\n    options = options || {}\n\n    const searchParams = new URLSearchParams(options.searchParams)\n    searchParams.append('arg', path)\n    if (options.recursive != null) searchParams.set('recursive', options.recursive)\n    if (options.force != null) searchParams.set('force', options.force)\n    if (options.shardSplitThreshold != null) searchParams.set('shardSplitThreshold', options.shardSplitThreshold)\n\n    return ky.post('files/rm', {\n      timeout: options.timeout,\n      signal: options.signal,\n      headers: options.headers,\n      searchParams\n    }).text()\n  }\n})\n"
  },
  {
    "path": "src/files/stat.js",
    "content": "'use strict'\n\nconst CID = require('cids')\nconst configure = require('../lib/configure')\nconst toCamelWithMetadata = require('../lib/object-to-camel-with-metadata')\n\nmodule.exports = configure(({ ky }) => {\n  return async (path, options) => {\n    if (typeof path !== 'string') {\n      options = path\n      path = '/'\n    }\n\n    options = options || {}\n\n    const searchParams = new URLSearchParams(options.searchParams)\n    searchParams.set('arg', path)\n    if (options.cidBase) searchParams.set('cid-base', options.cidBase)\n    if (options.hash != null) searchParams.set('hash', options.hash)\n    if (options.size != null) searchParams.set('size', options.size)\n    if (options.withLocal != null) searchParams.set('with-local', options.withLocal)\n\n    const res = await ky.post('files/stat', {\n      timeout: options.timeout,\n      signal: options.signal,\n      headers: options.headers,\n      searchParams\n    }).json()\n\n    res.WithLocality = res.WithLocality || false\n    return toCoreInterface(toCamelWithMetadata(res))\n  }\n})\n\nfunction toCoreInterface (entry) {\n  entry.cid = new CID(entry.hash)\n  delete entry.hash\n  return entry\n}\n"
  },
  {
    "path": "src/files/touch.js",
    "content": "'use strict'\n\nconst configure = require('../lib/configure')\nconst mtimeToObject = require('../lib/mtime-to-object')\n\nmodule.exports = configure(({ ky }) => {\n  return function touch (path, options) {\n    options = options || {}\n    const mtime = mtimeToObject(options.mtime)\n\n    const searchParams = new URLSearchParams(options.searchParams)\n    searchParams.append('arg', path)\n    if (mtime) {\n      searchParams.set('mtime', mtime.secs)\n      searchParams.set('mtimeNsecs', mtime.nsecs)\n    }\n    if (options.flush != null) searchParams.set('flush', options.flush)\n    if (options.hashAlg) searchParams.set('hash', options.hashAlg)\n    if (options.parents != null) searchParams.set('parents', options.parents)\n\n    return ky.post('files/touch', {\n      timeout: options.timeout,\n      signal: options.signal,\n      headers: options.headers,\n      searchParams\n    }).text()\n  }\n})\n"
  },
  {
    "path": "src/files/utils.js",
    "content": "'use strict'\n\nexports.findSources = (args) => {\n  let options = {}\n  let sources = []\n\n  if (!Array.isArray(args[args.length - 1]) && typeof args[args.length - 1] === 'object') {\n    options = args.pop()\n  }\n\n  if (args.length === 1 && Array.isArray(args[0])) {\n    // support ipfs.files.cp([src, dest], opts)\n    sources = args[0]\n  } else {\n    // support ipfs.files.cp(src, dest, opts) and ipfs.files.cp(src1, src2, dest, opts)\n    sources = args\n  }\n\n  return {\n    sources,\n    options\n  }\n}\n"
  },
  {
    "path": "src/files/write.js",
    "content": "'use strict'\n\nconst configure = require('../lib/configure')\nconst toFormData = require('../lib/buffer-to-form-data')\nconst modeToString = require('../lib/mode-to-string')\nconst mtimeToObject = require('../lib/mtime-to-object')\n\nmodule.exports = configure(({ ky }) => {\n  return async (path, input, options) => {\n    options = options || {}\n    const mtime = mtimeToObject(options.mtime)\n\n    const searchParams = new URLSearchParams(options.searchParams)\n    searchParams.set('arg', path)\n    searchParams.set('stream-channels', true)\n    if (options.cidVersion) searchParams.set('cid-version', options.cidVersion)\n    if (options.create != null) searchParams.set('create', options.create)\n    if (options.hashAlg) searchParams.set('hash', options.hashAlg)\n    if (options.length != null) searchParams.set('length', options.length)\n    if (options.offset != null) searchParams.set('offset', options.offset)\n    if (options.parents != null) searchParams.set('parents', options.parents)\n    if (options.rawLeaves != null) searchParams.set('raw-leaves', options.rawLeaves)\n    if (options.truncate != null) searchParams.set('truncate', options.truncate)\n    if (options.shardSplitThreshold != null) searchParams.set('shardSplitThreshold', options.shardSplitThreshold)\n    if (mtime) {\n      searchParams.set('mtime', mtime.secs)\n\n      if (mtime.nsecs != null) {\n        searchParams.set('mtimeNsecs', mtime.nsecs)\n      }\n    }\n\n    const res = await ky.post('files/write', {\n      timeout: options.timeout,\n      signal: options.signal,\n      headers: options.headers,\n      searchParams,\n      body: toFormData(input, {\n        mode: options.mode != null ? modeToString(options.mode) : undefined,\n        mtime: mtime ? mtime.secs : undefined,\n        mtimeNsecs: mtime ? mtime.nsecs : undefined\n      }) // TODO: support inputs other than buffer as per spec\n    })\n\n    return res.text()\n  }\n})\n"
  },
  {
    "path": "src/get-endpoint-config.js",
    "content": "'use strict'\n\nconst configure = require('./lib/configure')\n\nmodule.exports = configure(({ apiAddr, apiPath }) => {\n  const url = new URL(apiAddr)\n  return () => ({\n    host: url.hostname,\n    port: url.port,\n    protocol: url.protocol.split(':')[0], // remove \":\"\n    'api-path': apiPath\n  })\n})\n"
  },
  {
    "path": "src/get.js",
    "content": "'use strict'\n\nconst configure = require('./lib/configure')\nconst Tar = require('it-tar')\nconst { Buffer } = require('buffer')\nconst CID = require('cids')\nconst toIterable = require('stream-to-it/source')\n\nmodule.exports = configure(({ ky }) => {\n  return async function * get (path, options) {\n    options = options || {}\n\n    const searchParams = new URLSearchParams()\n    searchParams.set('arg', `${Buffer.isBuffer(path) ? new CID(path) : path}`)\n\n    if (options.compress !== undefined) {\n      searchParams.set('compress', options.compress)\n    }\n\n    if (options.compressionLevel !== undefined) {\n      searchParams.set('compression-level', options.compressionLevel)\n    }\n\n    if (options.offset) {\n      searchParams.set('offset', options.offset)\n    }\n\n    if (options.length) {\n      searchParams.set('length', options.length)\n    }\n\n    const res = await ky.post('get', {\n      timeout: options.timeout,\n      signal: options.signal,\n      headers: options.headers,\n      searchParams\n    })\n\n    const extractor = Tar.extract()\n\n    for await (const { header, body } of extractor(toIterable(res.body))) {\n      if (header.type === 'directory') {\n        yield {\n          path: header.name\n        }\n      } else {\n        yield {\n          path: header.name,\n          content: body\n        }\n      }\n    }\n  }\n})\n"
  },
  {
    "path": "src/id.js",
    "content": "'use strict'\n\nconst configure = require('./lib/configure')\nconst toCamel = require('./lib/object-to-camel')\nconst multiaddr = require('multiaddr')\n\nmodule.exports = configure(({ ky }) => {\n  return async options => {\n    options = options || {}\n\n    const res = await ky.post('id', {\n      timeout: options.timeout,\n      signal: options.signal,\n      headers: options.headers,\n      searchParams: options.searchParams\n    }).json()\n\n    const output = toCamel(res)\n\n    if (output.addresses) {\n      output.addresses = output.addresses.map(ma => multiaddr(ma))\n    }\n\n    return output\n  }\n})\n"
  },
  {
    "path": "src/index.js",
    "content": "'use strict'\n\nconst { Buffer } = require('buffer')\nconst CID = require('cids')\nconst multiaddr = require('multiaddr')\nconst multibase = require('multibase')\nconst multicodec = require('multicodec')\nconst multihash = require('multihashes')\nconst globSource = require('ipfs-utils/src/files/glob-source')\nconst urlSource = require('ipfs-utils/src/files/url-source')\n\nfunction ipfsClient (config) {\n  return {\n    add: require('./add')(config),\n    bitswap: require('./bitswap')(config),\n    block: require('./block')(config),\n    bootstrap: require('./bootstrap')(config),\n    cat: require('./cat')(config),\n    commands: require('./commands')(config),\n    config: require('./config')(config),\n    dag: require('./dag')(config),\n    dht: require('./dht')(config),\n    diag: require('./diag')(config),\n    dns: require('./dns')(config),\n    files: require('./files')(config),\n    get: require('./get')(config),\n    getEndpointConfig: require('./get-endpoint-config')(config),\n    id: require('./id')(config),\n    key: require('./key')(config),\n    log: require('./log')(config),\n    ls: require('./ls')(config),\n    mount: require('./mount')(config),\n    name: require('./name')(config),\n    object: require('./object')(config),\n    pin: require('./pin')(config),\n    ping: require('./ping')(config),\n    pubsub: require('./pubsub')(config),\n    refs: require('./refs')(config),\n    repo: require('./repo')(config),\n    resolve: require('./resolve')(config),\n    stats: require('./stats')(config),\n    stop: require('./stop')(config),\n    shutdown: require('./stop')(config),\n    swarm: require('./swarm')(config),\n    version: require('./version')(config)\n  }\n}\n\nObject.assign(ipfsClient, { Buffer, CID, multiaddr, multibase, multicodec, multihash, globSource, urlSource })\n\nmodule.exports = ipfsClient\n"
  },
  {
    "path": "src/key/export.js",
    "content": "'use strict'\n\nconst configure = require('../lib/configure')\n\nmodule.exports = configure(({ ky }) => {\n  return (name, password, options) => {\n    if (typeof password !== 'string') {\n      options = password\n      password = null\n    }\n\n    options = options || {}\n\n    const searchParams = new URLSearchParams(options.searchParams)\n    searchParams.set('arg', name)\n    if (password) searchParams.set('password', password)\n\n    return ky.post('key/export', {\n      timeout: options.timeout,\n      signal: options.signal,\n      headers: options.headers,\n      searchParams\n    }).text()\n  }\n})\n"
  },
  {
    "path": "src/key/gen.js",
    "content": "'use strict'\n\nconst configure = require('../lib/configure')\nconst toCamel = require('../lib/object-to-camel')\n\nmodule.exports = configure(({ ky }) => {\n  return async (name, options) => {\n    options = options || {}\n\n    const searchParams = new URLSearchParams(options.searchParams)\n    searchParams.set('arg', name)\n    if (options.type) searchParams.set('type', options.type)\n    if (options.size != null) searchParams.set('size', options.size)\n\n    const res = await ky.post('key/gen', {\n      timeout: options.timeout,\n      signal: options.signal,\n      headers: options.headers,\n      searchParams\n    }).json()\n\n    return toCamel(res)\n  }\n})\n"
  },
  {
    "path": "src/key/import.js",
    "content": "'use strict'\n\nconst configure = require('../lib/configure')\nconst toCamel = require('../lib/object-to-camel')\n\nmodule.exports = configure(({ ky }) => {\n  return async (name, pem, password, options) => {\n    if (typeof password !== 'string') {\n      options = password\n      password = null\n    }\n\n    options = options || {}\n\n    const searchParams = new URLSearchParams(options.searchParams)\n    searchParams.set('arg', name)\n    searchParams.set('pem', pem)\n    if (password) searchParams.set('password', password)\n\n    const res = await ky.post('key/import', {\n      timeout: options.timeout,\n      signal: options.signal,\n      headers: options.headers,\n      searchParams\n    }).json()\n\n    return toCamel(res)\n  }\n})\n"
  },
  {
    "path": "src/key/index.js",
    "content": "'use strict'\n\nmodule.exports = config => ({\n  gen: require('./gen')(config),\n  list: require('./list')(config),\n  rename: require('./rename')(config),\n  rm: require('./rm')(config),\n  export: require('./export')(config),\n  import: require('./import')(config)\n})\n"
  },
  {
    "path": "src/key/list.js",
    "content": "'use strict'\n\nconst configure = require('../lib/configure')\nconst toCamel = require('../lib/object-to-camel')\n\nmodule.exports = configure(({ ky }) => {\n  return async options => {\n    options = options || {}\n\n    const res = await ky.post('key/list', {\n      timeout: options.timeout,\n      signal: options.signal,\n      headers: options.headers,\n      searchParams: options.searchParams\n    }).json()\n\n    return (res.Keys || []).map(k => toCamel(k))\n  }\n})\n"
  },
  {
    "path": "src/key/rename.js",
    "content": "'use strict'\n\nconst configure = require('../lib/configure')\nconst toCamel = require('../lib/object-to-camel')\n\nmodule.exports = configure(({ ky }) => {\n  return async (oldName, newName, options) => {\n    options = options || {}\n\n    const searchParams = new URLSearchParams(options.searchParams)\n    searchParams.set('arg', oldName)\n    searchParams.append('arg', newName)\n    if (options.force != null) searchParams.set('force', options.force)\n\n    const res = await ky.post('key/rename', {\n      timeout: options.timeout,\n      signal: options.signal,\n      headers: options.headers,\n      searchParams\n    }).json()\n\n    return toCamel(res)\n  }\n})\n"
  },
  {
    "path": "src/key/rm.js",
    "content": "'use strict'\n\nconst configure = require('../lib/configure')\nconst toCamel = require('../lib/object-to-camel')\n\nmodule.exports = configure(({ ky }) => {\n  return async (name, options) => {\n    options = options || {}\n\n    const searchParams = new URLSearchParams(options.searchParams)\n    searchParams.set('arg', name)\n\n    const res = await ky.post('key/rm', {\n      timeout: options.timeout,\n      signal: options.signal,\n      headers: options.headers,\n      searchParams\n    }).json()\n\n    return toCamel(res.Keys[0])\n  }\n})\n"
  },
  {
    "path": "src/lib/buffer-to-form-data.browser.js",
    "content": "'use strict'\n/* eslint-env browser */\n\nmodule.exports = buf => {\n  const formData = new FormData()\n  formData.append('file', new Blob([buf], { type: 'application/octet-stream' }))\n  return formData\n}\n"
  },
  {
    "path": "src/lib/buffer-to-form-data.js",
    "content": "'use strict'\n\nconst FormData = require('form-data')\nconst { isElectronRenderer } = require('ipfs-utils/src/env')\n\nmodule.exports = (buf, { mode, mtime, mtimeNsecs } = {}) => {\n  const headers = {}\n\n  if (mode != null) {\n    headers.mode = mode\n  }\n\n  if (mtime != null) {\n    headers.mtime = mtime\n\n    if (mtimeNsecs != null) {\n      headers['mtime-nsecs'] = mtimeNsecs\n    }\n  }\n\n  const formData = new FormData()\n  formData.append('file', buf, {\n    header: headers\n  })\n  return formData\n}\n\n// TODO remove this when upstream fix for ky-universal is merged\n// https://github.com/sindresorhus/ky-universal/issues/9\n// also this should only be necessary when nodeIntegration is false in electron renderer\nif (isElectronRenderer) {\n  module.exports = require('./buffer-to-form-data.browser')\n}\n"
  },
  {
    "path": "src/lib/configure.js",
    "content": "'use strict'\n/* eslint-env browser */\n\nconst ky = require('ky-universal').default\nconst { isBrowser, isWebWorker } = require('ipfs-utils/src/env')\nconst toUri = require('multiaddr-to-uri')\nconst errorHandler = require('./error-handler')\nconst mergeOptions = require('merge-options').bind({ ignoreUndefined: true })\nconst parseDuration = require('parse-duration')\n\n// Set default configuration and call create function with them\nmodule.exports = create => config => {\n  config = config || {}\n\n  if (typeof config === 'string') {\n    config = { apiAddr: config }\n  } else if (config.constructor && config.constructor.isMultiaddr) {\n    config = { apiAddr: config }\n  } else {\n    config = { ...config }\n  }\n\n  config.apiAddr = (config.apiAddr || getDefaultApiAddr(config)).toString()\n  config.apiAddr = config.apiAddr.startsWith('/') ? toUri(config.apiAddr) : config.apiAddr\n  config.apiAddr = trimEnd(config.apiAddr, '/')\n\n  const apiAddrPath = getNonRootPath(config.apiAddr)\n\n  // Use configured apiPath, or path on the end of apiAddr (if there is one) or default to /api/v0\n  config.apiPath = config.apiPath || config['api-path'] || apiAddrPath || '/api/v0'\n  config.apiPath = trimEnd(config.apiPath, '/')\n\n  // If user passed apiAddr with a path, trim it from the end (it is now apiPath)\n  config.apiAddr = apiAddrPath ? trimEnd(config.apiAddr, apiAddrPath) : config.apiAddr\n\n  const defaults = {\n    prefixUrl: config.apiAddr + config.apiPath,\n    timeout: parseTimeout(config.timeout) || 60000 * 20,\n    headers: config.headers,\n    hooks: {\n      afterResponse: [errorHandler]\n    }\n  }\n  const k = ky.extend(defaults)\n  const client = ['get', 'post', 'put', 'delete', 'patch', 'head']\n    .reduce((client, key) => {\n      client[key] = wrap(k[key], defaults)\n\n      return client\n    }, wrap(k, defaults))\n\n  return create({\n    ky: client,\n    ...config\n  })\n}\n\nfunction getDefaultApiAddr ({ protocol, host, port }) {\n  if (isBrowser || isWebWorker) {\n    if (!protocol) {\n      protocol = location.protocol.startsWith('http')\n        ? trimEnd(location.protocol, ':')\n        : 'http'\n    }\n\n    host = host || location.hostname\n    port = port || location.port\n\n    return `${protocol}://${host}${port ? ':' + port : ''}`\n  }\n\n  return `${protocol || 'http'}://${host || 'localhost'}:${port || 5001}`\n}\n\n// returns the passed function wrapped in a function that ignores\n// undefined values in the passed `options` object\nfunction wrap (fn, defaults) {\n  return (input, options) => {\n    if (options.timeout) options.timeout = parseTimeout(options.timeout)\n    return fn(input, mergeOptions(defaults, options))\n  }\n}\n\nfunction parseTimeout (value) {\n  return typeof value === 'string' ? parseDuration(value) : value\n}\n\nconst trimEnd = (str, end) => str.endsWith(end) ? str.slice(0, -end.length) : str\n\n// Get the path from a URL is it is not /\nfunction getNonRootPath (url) {\n  if (url) {\n    const { pathname } = new URL(url)\n    return pathname === '/' ? null : pathname\n  }\n}\n"
  },
  {
    "path": "src/lib/encode-buffer-uri-component.js",
    "content": "'use strict'\n\n// https://github.com/ipfs/js-ipfs-http-client/issues/569\nmodule.exports = function encodeBuffer (buf) {\n  let uriEncoded = ''\n  for (const byte of buf) {\n    // https://tools.ietf.org/html/rfc3986#page-14\n    // ALPHA (%41-%5A and %61-%7A), DIGIT (%30-%39), hyphen (%2D), period (%2E),\n    // underscore (%5F), or tilde (%7E)\n    if (\n      (byte >= 0x41 && byte <= 0x5A) ||\n      (byte >= 0x61 && byte <= 0x7A) ||\n      (byte >= 0x30 && byte <= 0x39) ||\n      (byte === 0x2D) ||\n      (byte === 0x2E) ||\n      (byte === 0x5F) ||\n      (byte === 0x7E)\n    ) {\n      uriEncoded += String.fromCharCode(byte)\n    } else {\n      uriEncoded += `%${byte.toString(16).padStart(2, '0')}`\n    }\n  }\n  return uriEncoded\n}\n"
  },
  {
    "path": "src/lib/error-handler.js",
    "content": "'use strict'\n\nconst { HTTPError } = require('ky-universal')\nconst log = require('debug')('ipfs-http-client:lib:error-handler')\nconst { isNode, isElectronMain } = require('ipfs-utils/src/env')\n\nfunction isJsonResponse (res) {\n  return (res.headers.get('Content-Type') || '').startsWith('application/json')\n}\n\nmodule.exports = async function errorHandler (input, options, response) {\n  if (response.ok) {\n    // FIXME: remove when fixed https://github.com/sindresorhus/ky-universal/issues/8\n    //\n    // ky clones the response for each handler. In Node.js the response body is\n    // piped to 2 PassThroughs, one becomes the real body and the other is used\n    // in the clone.\n    //\n    // If the body in the clone is not consumed or destroyed the highwater mark\n    // will be reached (for large payloads) and stop the real body from flowing.\n    if (isNode || isElectronMain) response.body.destroy()\n    return\n  }\n\n  let msg\n\n  try {\n    if (isJsonResponse(response)) {\n      const data = await response.json()\n      log(data)\n      msg = data.Message || data.message\n    } else {\n      msg = await response.text()\n    }\n  } catch (err) {\n    log('Failed to parse error response', err)\n    // Failed to extract/parse error message from response\n    msg = err.message\n  }\n\n  const error = new HTTPError(response)\n\n  // If we managed to extract a message from the response, use it\n  if (msg) {\n    error.message = msg\n  }\n\n  throw error\n}\n"
  },
  {
    "path": "src/lib/mode-to-string.js",
    "content": "'use strict'\n\nmodule.exports = (mode) => {\n  if (mode === undefined || mode === null) {\n    return undefined\n  }\n\n  if (typeof mode === 'string' || mode instanceof String) {\n    return mode\n  }\n\n  return mode.toString(8).padStart(4, '0')\n}\n"
  },
  {
    "path": "src/lib/mtime-to-object.js",
    "content": "'use strict'\n\nmodule.exports = function parseMtime (mtime) {\n  if (mtime == null) {\n    return undefined\n  }\n\n  // Javascript Date\n  if (mtime instanceof Date) {\n    const ms = mtime.getTime()\n    const secs = Math.floor(ms / 1000)\n\n    return {\n      secs: secs,\n      nsecs: (ms - (secs * 1000)) * 1000\n    }\n  }\n\n  // { secs, nsecs }\n  if (Object.prototype.hasOwnProperty.call(mtime, 'secs')) {\n    return {\n      secs: mtime.secs,\n      nsecs: mtime.nsecs\n    }\n  }\n\n  // UnixFS TimeSpec\n  if (Object.prototype.hasOwnProperty.call(mtime, 'Seconds')) {\n    return {\n      secs: mtime.Seconds,\n      nsecs: mtime.FractionalNanoseconds\n    }\n  }\n\n  // process.hrtime()\n  if (Array.isArray(mtime)) {\n    return {\n      secs: mtime[0],\n      nsecs: mtime[1]\n    }\n  }\n  /*\n  TODO: https://github.com/ipfs/aegir/issues/487\n\n  // process.hrtime.bigint()\n  if (typeof mtime === 'bigint') {\n    const secs = mtime / BigInt(1e9)\n    const nsecs = mtime - (secs * BigInt(1e9))\n\n    return {\n      secs: parseInt(secs),\n      nsecs: parseInt(nsecs)\n    }\n  }\n  */\n}\n"
  },
  {
    "path": "src/lib/object-to-camel-with-metadata.js",
    "content": "'use strict'\n\nconst toCamel = require('./object-to-camel')\n\nfunction toCamelWithMetadata (entry) {\n  const file = toCamel(entry)\n\n  if (Object.prototype.hasOwnProperty.call(file, 'mode')) {\n    file.mode = parseInt(file.mode, 8)\n  }\n\n  if (Object.prototype.hasOwnProperty.call(file, 'mtime')) {\n    file.mtime = {\n      secs: file.mtime,\n      nsecs: file.mtimeNsecs || 0\n    }\n\n    delete file.mtimeNsecs\n  }\n\n  return file\n}\n\nmodule.exports = toCamelWithMetadata\n"
  },
  {
    "path": "src/lib/object-to-camel.js",
    "content": "'use strict'\n\n// Convert object properties to camel case.\n// NOT recursive!\n// e.g.\n// AgentVersion => agentVersion\n// ID => id\nmodule.exports = obj => {\n  if (obj == null) return obj\n  const caps = /^[A-Z]+$/\n  return Object.keys(obj).reduce((camelObj, k) => {\n    if (caps.test(k)) { // all caps\n      camelObj[k.toLowerCase()] = obj[k]\n    } else if (caps.test(k[0])) { // pascal\n      camelObj[k[0].toLowerCase() + k.slice(1)] = obj[k]\n    } else {\n      camelObj[k] = obj[k]\n    }\n    return camelObj\n  }, {})\n}\n"
  },
  {
    "path": "src/log/index.js",
    "content": "'use strict'\n\nmodule.exports = config => ({\n  tail: require('./tail')(config),\n  ls: require('./ls')(config),\n  level: require('./level')(config)\n})\n"
  },
  {
    "path": "src/log/level.js",
    "content": "'use strict'\n\nconst configure = require('../lib/configure')\nconst toCamel = require('../lib/object-to-camel')\n\nmodule.exports = configure(({ ky }) => {\n  return async (subsystem, level, options) => {\n    options = options || {}\n\n    const searchParams = new URLSearchParams(options.searchParams)\n    searchParams.set('arg', subsystem)\n    searchParams.append('arg', level)\n\n    const res = await ky.post('log/level', {\n      timeout: options.timeout,\n      signal: options.signal,\n      headers: options.headers,\n      searchParams\n    }).json()\n\n    return toCamel(res)\n  }\n})\n"
  },
  {
    "path": "src/log/ls.js",
    "content": "'use strict'\n\nconst configure = require('../lib/configure')\n\nmodule.exports = configure(({ ky }) => {\n  return async options => {\n    options = options || {}\n\n    const res = await ky.post('log/ls', {\n      timeout: options.timeout,\n      signal: options.signal,\n      headers: options.headers,\n      searchParams: options.searchParams\n    }).json()\n\n    return res.Strings\n  }\n})\n"
  },
  {
    "path": "src/log/tail.js",
    "content": "'use strict'\n\nconst ndjson = require('iterable-ndjson')\nconst configure = require('../lib/configure')\nconst toIterable = require('stream-to-it/source')\n\nmodule.exports = configure(({ ky }) => {\n  return async function * tail (options) {\n    options = options || {}\n\n    const res = await ky.post('log/tail', {\n      timeout: options.timeout,\n      signal: options.signal,\n      headers: options.headers,\n      searchParams: options.searchParams\n    })\n\n    yield * ndjson(toIterable(res.body))\n  }\n})\n"
  },
  {
    "path": "src/ls.js",
    "content": "'use strict'\n\nconst { Buffer } = require('buffer')\nconst CID = require('cids')\nconst ndjson = require('iterable-ndjson')\nconst toIterable = require('stream-to-it/source')\nconst configure = require('./lib/configure')\n\nmodule.exports = configure(({ ky }) => {\n  return async function * ls (path, options) {\n    options = options || {}\n\n    const searchParams = new URLSearchParams()\n    searchParams.set('arg', `${Buffer.isBuffer(path) ? new CID(path) : path}`)\n    searchParams.set('stream', options.stream == null ? true : options.stream)\n\n    if (options.long != null) searchParams.set('long', options.long)\n    if (options.unsorted != null) searchParams.set('unsorted', options.unsorted)\n    if (options.recursive != null) searchParams.set('recursive', options.recursive)\n\n    const res = await ky.post('ls', {\n      timeout: options.timeout,\n      signal: options.signal,\n      headers: options.headers,\n      searchParams\n    })\n\n    for await (let result of ndjson(toIterable(res.body))) {\n      result = result.Objects\n\n      if (!result) {\n        throw new Error('expected .Objects in results')\n      }\n\n      result = result[0]\n      if (!result) {\n        throw new Error('expected one array in results.Objects')\n      }\n\n      result = result.Links\n      if (!Array.isArray(result)) {\n        throw new Error('expected one array in results.Objects[0].Links')\n      }\n\n      for (const link of result) {\n        const entry = {\n          name: link.Name,\n          path: path + '/' + link.Name,\n          size: link.Size,\n          cid: new CID(link.Hash),\n          type: typeOf(link),\n          depth: link.Depth || 1\n        }\n\n        if (link.Mode) {\n          entry.mode = parseInt(link.Mode, 8)\n        }\n\n        if (link.Mtime !== undefined && link.Mtime !== null) {\n          entry.mtime = {\n            secs: link.Mtime\n          }\n\n          if (link.MtimeNsecs !== undefined && link.MtimeNsecs !== null) {\n            entry.mtime.nsecs = link.MtimeNsecs\n          }\n        }\n\n        yield entry\n      }\n    }\n  }\n})\n\nfunction typeOf (link) {\n  switch (link.Type) {\n    case 1:\n    case 5:\n      return 'dir'\n    case 2:\n      return 'file'\n    default:\n      return 'unknown'\n  }\n}\n"
  },
  {
    "path": "src/mount.js",
    "content": "'use strict'\n\nconst configure = require('./lib/configure')\nconst toCamel = require('./lib/object-to-camel')\n\nmodule.exports = configure(({ ky }) => {\n  return async options => {\n    options = options || {}\n\n    const searchParams = new URLSearchParams(options.searchParams)\n    if (options.ipfsPath != null) searchParams.set('ipfs-path', options.ipfsPath)\n    if (options.ipnsPath != null) searchParams.set('ipns-path', options.ipnsPath)\n\n    const res = await ky.post('dns', {\n      timeout: options.timeout,\n      signal: options.signal,\n      headers: options.headers,\n      searchParams\n    }).json()\n\n    return toCamel(res)\n  }\n})\n"
  },
  {
    "path": "src/name/index.js",
    "content": "'use strict'\n\nmodule.exports = config => ({\n  publish: require('./publish')(config),\n  resolve: require('./resolve')(config),\n  pubsub: require('./pubsub')(config)\n})\n"
  },
  {
    "path": "src/name/publish.js",
    "content": "'use strict'\n\nconst configure = require('../lib/configure')\nconst toCamel = require('../lib/object-to-camel')\n\nmodule.exports = configure(({ ky }) => {\n  return async (path, options) => {\n    options = options || {}\n\n    const searchParams = new URLSearchParams(options.searchParams)\n    searchParams.set('arg', path)\n    if (options.allowOffline != null) searchParams.set('allow-offline', options.allowOffline)\n    if (options.key) searchParams.set('key', options.key)\n    if (options.lifetime) searchParams.set('lifetime', options.lifetime)\n    if (options.quieter != null) searchParams.set('quieter', options.quieter)\n    if (options.resolve != null) searchParams.set('resolve', options.resolve)\n    if (options.ttl) searchParams.set('ttl', options.ttl)\n\n    const res = await ky.post('name/publish', {\n      timeout: options.timeout,\n      signal: options.signal,\n      headers: options.headers,\n      searchParams\n    }).json()\n\n    return toCamel(res)\n  }\n})\n"
  },
  {
    "path": "src/name/pubsub/cancel.js",
    "content": "'use strict'\n\nconst configure = require('../../lib/configure')\nconst toCamel = require('../../lib/object-to-camel')\n\nmodule.exports = configure(({ ky }) => {\n  return async (name, options) => {\n    options = options || {}\n\n    const searchParams = new URLSearchParams(options.searchParams)\n    searchParams.set('arg', name)\n\n    const res = await ky.post('name/pubsub/cancel', {\n      timeout: options.timeout,\n      signal: options.signal,\n      headers: options.headers,\n      searchParams\n    }).json()\n\n    return toCamel(res)\n  }\n})\n"
  },
  {
    "path": "src/name/pubsub/index.js",
    "content": "'use strict'\n\nmodule.exports = config => ({\n  cancel: require('./cancel')(config),\n  state: require('./state')(config),\n  subs: require('./subs')(config)\n})\n"
  },
  {
    "path": "src/name/pubsub/state.js",
    "content": "'use strict'\n\nconst configure = require('../../lib/configure')\nconst toCamel = require('../../lib/object-to-camel')\n\nmodule.exports = configure(({ ky }) => {\n  return async options => {\n    options = options || {}\n\n    const res = await ky.post('name/pubsub/state', {\n      timeout: options.timeout,\n      signal: options.signal,\n      headers: options.headers,\n      searchParams: options.searchParams\n    }).json()\n\n    return toCamel(res)\n  }\n})\n"
  },
  {
    "path": "src/name/pubsub/subs.js",
    "content": "'use strict'\n\nconst configure = require('../../lib/configure')\n\nmodule.exports = configure(({ ky }) => {\n  return async (name, options) => {\n    options = options || {}\n\n    const res = await ky.post('name/pubsub/subs', {\n      timeout: options.timeout,\n      signal: options.signal,\n      headers: options.headers,\n      searchParams: options.searchParams\n    }).json()\n\n    return res.Strings || []\n  }\n})\n"
  },
  {
    "path": "src/name/resolve.js",
    "content": "'use strict'\n\nconst ndjson = require('iterable-ndjson')\nconst configure = require('../lib/configure')\nconst toIterable = require('stream-to-it/source')\n\nmodule.exports = configure(({ ky }) => {\n  return async function * (path, options) {\n    options = options || {}\n\n    const searchParams = new URLSearchParams(options.searchParams)\n    searchParams.set('arg', path)\n    searchParams.set('stream', options.stream == null ? true : options.stream)\n    if (options.dhtRecordCount != null) searchParams.set('dht-record-count', options.dhtRecordCount)\n    if (options.dhtTimeout != null) searchParams.set('dht-timeout', options.dhtTimeout)\n    if (options.noCache != null) searchParams.set('nocache', options.noCache)\n    if (options.recursive != null) searchParams.set('recursive', options.recursive)\n\n    const res = await ky.post('name/resolve', {\n      timeout: options.timeout,\n      signal: options.signal,\n      headers: options.headers,\n      searchParams\n    })\n\n    for await (const result of ndjson(toIterable(res.body))) {\n      yield result.Path\n    }\n  }\n})\n"
  },
  {
    "path": "src/object/data.js",
    "content": "'use strict'\n\nconst { Buffer } = require('buffer')\nconst CID = require('cids')\nconst configure = require('../lib/configure')\n\nmodule.exports = configure(({ ky }) => {\n  return async function data (cid, options) {\n    options = options || {}\n\n    const searchParams = new URLSearchParams(options.searchParams)\n    searchParams.set('arg', `${Buffer.isBuffer(cid) ? new CID(cid) : cid}`)\n\n    const data = await ky.post('object/data', {\n      timeout: options.timeout,\n      signal: options.signal,\n      headers: options.headers,\n      searchParams\n    }).arrayBuffer()\n\n    return Buffer.from(data)\n  }\n})\n"
  },
  {
    "path": "src/object/get.js",
    "content": "'use strict'\n\nconst { Buffer } = require('buffer')\nconst CID = require('cids')\nconst { DAGNode, DAGLink } = require('ipld-dag-pb')\nconst configure = require('../lib/configure')\n\nmodule.exports = configure(({ ky }) => {\n  return async (cid, options) => {\n    options = options || {}\n\n    const searchParams = new URLSearchParams(options.searchParams)\n    searchParams.set('arg', `${Buffer.isBuffer(cid) ? new CID(cid) : cid}`)\n    searchParams.set('data-encoding', 'base64')\n\n    const res = await ky.post('object/get', {\n      timeout: options.timeout,\n      signal: options.signal,\n      headers: options.headers,\n      searchParams\n    }).json()\n\n    return new DAGNode(\n      Buffer.from(res.Data, 'base64'),\n      (res.Links || []).map(l => new DAGLink(l.Name, l.Size, l.Hash))\n    )\n  }\n})\n"
  },
  {
    "path": "src/object/index.js",
    "content": "'use strict'\n\nmodule.exports = config => ({\n  data: require('./data')(config),\n  get: require('./get')(config),\n  links: require('./links')(config),\n  new: require('./new')(config),\n  patch: require('./patch')(config),\n  put: require('./put')(config),\n  stat: require('./stat')(config)\n})\n"
  },
  {
    "path": "src/object/links.js",
    "content": "'use strict'\n\nconst { Buffer } = require('buffer')\nconst CID = require('cids')\nconst { DAGLink } = require('ipld-dag-pb')\nconst configure = require('../lib/configure')\n\nmodule.exports = configure(({ ky }) => {\n  return async (cid, options) => {\n    options = options || {}\n\n    const searchParams = new URLSearchParams(options.searchParams)\n    searchParams.set('arg', `${Buffer.isBuffer(cid) ? new CID(cid) : cid}`)\n\n    const res = await ky.post('object/links', {\n      timeout: options.timeout,\n      signal: options.signal,\n      headers: options.headers,\n      searchParams\n    }).json()\n\n    return (res.Links || []).map(l => new DAGLink(l.Name, l.Size, l.Hash))\n  }\n})\n"
  },
  {
    "path": "src/object/new.js",
    "content": "'use strict'\n\nconst CID = require('cids')\nconst configure = require('../lib/configure')\n\nmodule.exports = configure(({ ky }) => {\n  return async (template, options) => {\n    if (typeof template !== 'string') {\n      options = template\n      template = null\n    }\n\n    options = options || {}\n\n    const searchParams = new URLSearchParams(options.searchParams)\n    if (template) searchParams.set('arg', template)\n\n    const { Hash } = await ky.post('object/new', {\n      timeout: options.timeout,\n      signal: options.signal,\n      headers: options.headers,\n      searchParams\n    }).json()\n\n    return new CID(Hash)\n  }\n})\n"
  },
  {
    "path": "src/object/patch/add-link.js",
    "content": "'use strict'\n\nconst { Buffer } = require('buffer')\nconst CID = require('cids')\nconst configure = require('../../lib/configure')\n\nmodule.exports = configure(({ ky }) => {\n  return async (cid, dLink, options) => {\n    options = options || {}\n\n    const searchParams = new URLSearchParams(options.searchParams)\n    searchParams.set('arg', `${Buffer.isBuffer(cid) ? new CID(cid) : cid}`)\n    searchParams.append('arg', dLink.Name || dLink.name || null)\n    searchParams.append('arg', (dLink.Hash || dLink.cid || '').toString() || null)\n\n    const { Hash } = await ky.post('object/patch/add-link', {\n      timeout: options.timeout,\n      signal: options.signal,\n      headers: options.headers,\n      searchParams\n    }).json()\n\n    return new CID(Hash)\n  }\n})\n"
  },
  {
    "path": "src/object/patch/append-data.js",
    "content": "'use strict'\n\nconst { Buffer } = require('buffer')\nconst CID = require('cids')\nconst configure = require('../../lib/configure')\nconst toFormData = require('../../lib/buffer-to-form-data')\n\nmodule.exports = configure(({ ky }) => {\n  return async (cid, data, options) => {\n    options = options || {}\n\n    const searchParams = new URLSearchParams(options.searchParams)\n    searchParams.set('arg', `${Buffer.isBuffer(cid) ? new CID(cid) : cid}`)\n\n    const { Hash } = await ky.post('object/patch/append-data', {\n      timeout: options.timeout,\n      signal: options.signal,\n      headers: options.headers,\n      searchParams,\n      body: toFormData(data)\n    }).json()\n\n    return new CID(Hash)\n  }\n})\n"
  },
  {
    "path": "src/object/patch/index.js",
    "content": "'use strict'\n\nmodule.exports = config => ({\n  addLink: require('./add-link')(config),\n  appendData: require('./append-data')(config),\n  rmLink: require('./rm-link')(config),\n  setData: require('./set-data')(config)\n})\n"
  },
  {
    "path": "src/object/patch/rm-link.js",
    "content": "'use strict'\n\nconst { Buffer } = require('buffer')\nconst CID = require('cids')\nconst configure = require('../../lib/configure')\n\nmodule.exports = configure(({ ky }) => {\n  return async (cid, dLink, options) => {\n    options = options || {}\n\n    const searchParams = new URLSearchParams(options.searchParams)\n    searchParams.set('arg', `${Buffer.isBuffer(cid) ? new CID(cid) : cid}`)\n    searchParams.append('arg', dLink.Name || dLink.name || null)\n\n    const { Hash } = await ky.post('object/patch/rm-link', {\n      timeout: options.timeout,\n      signal: options.signal,\n      headers: options.headers,\n      searchParams\n    }).json()\n\n    return new CID(Hash)\n  }\n})\n"
  },
  {
    "path": "src/object/patch/set-data.js",
    "content": "'use strict'\n\nconst { Buffer } = require('buffer')\nconst CID = require('cids')\nconst configure = require('../../lib/configure')\nconst toFormData = require('../../lib/buffer-to-form-data')\n\nmodule.exports = configure(({ ky }) => {\n  return async (cid, data, options) => {\n    options = options || {}\n\n    const searchParams = new URLSearchParams(options.searchParams)\n    searchParams.set('arg', `${Buffer.isBuffer(cid) ? new CID(cid) : cid}`)\n\n    const { Hash } = await ky.post('object/patch/set-data', {\n      timeout: options.timeout,\n      signal: options.signal,\n      headers: options.headers,\n      searchParams,\n      body: toFormData(data)\n    }).json()\n\n    return new CID(Hash)\n  }\n})\n"
  },
  {
    "path": "src/object/put.js",
    "content": "'use strict'\n\nconst CID = require('cids')\nconst { DAGNode } = require('ipld-dag-pb')\nconst { Buffer } = require('buffer')\nconst configure = require('../lib/configure')\nconst toFormData = require('../lib/buffer-to-form-data')\n\nmodule.exports = configure(({ ky }) => {\n  return async (obj, options) => {\n    options = options || {}\n\n    let tmpObj = {\n      Data: null,\n      Links: []\n    }\n\n    if (Buffer.isBuffer(obj)) {\n      if (!options.enc) {\n        tmpObj = {\n          Data: obj.toString(),\n          Links: []\n        }\n      }\n    } else if (DAGNode.isDAGNode(obj)) {\n      tmpObj = {\n        Data: obj.Data.toString(),\n        Links: obj.Links.map(l => ({\n          Name: l.Name,\n          Hash: l.Hash.toString(),\n          Size: l.Tsize\n        }))\n      }\n    } else if (typeof obj === 'object') {\n      tmpObj.Data = obj.Data.toString()\n      tmpObj.Links = obj.Links\n    } else {\n      throw new Error('obj not recognized')\n    }\n\n    let buf\n    if (Buffer.isBuffer(obj) && options.enc) {\n      buf = obj\n    } else {\n      buf = Buffer.from(JSON.stringify(tmpObj))\n    }\n\n    const searchParams = new URLSearchParams(options.searchParams)\n    if (options.enc) searchParams.set('inputenc', options.enc)\n    if (options.pin != null) searchParams.set('pin', options.pin)\n    if (options.quiet != null) searchParams.set('quiet', options.quiet)\n\n    const { Hash } = await ky.post('object/put', {\n      timeout: options.timeout,\n      signal: options.signal,\n      headers: options.headers,\n      searchParams,\n      body: toFormData(buf)\n    }).json()\n\n    return new CID(Hash)\n  }\n})\n"
  },
  {
    "path": "src/object/stat.js",
    "content": "'use strict'\n\nconst { Buffer } = require('buffer')\nconst CID = require('cids')\nconst configure = require('../lib/configure')\n\nmodule.exports = configure(({ ky }) => {\n  return async (cid, options) => {\n    options = options || {}\n\n    const searchParams = new URLSearchParams(options.searchParams)\n    searchParams.set('arg', `${Buffer.isBuffer(cid) ? new CID(cid) : cid}`)\n\n    let res\n    try {\n      res = await ky.post('object/stat', {\n        timeout: options.timeout,\n        signal: options.signal,\n        headers: options.headers,\n        searchParams\n      }).json()\n    } catch (err) {\n      if (err.name === 'TimeoutError') {\n        err.message = `failed to get block for ${Buffer.isBuffer(cid) ? new CID(cid) : cid}: context deadline exceeded`\n      }\n      throw err\n    }\n\n    return res\n  }\n})\n"
  },
  {
    "path": "src/pin/add.js",
    "content": "'use strict'\n\nconst CID = require('cids')\nconst configure = require('../lib/configure')\n\nmodule.exports = configure(({ ky }) => {\n  return async (paths, options) => {\n    paths = Array.isArray(paths) ? paths : [paths]\n    options = options || {}\n\n    const searchParams = new URLSearchParams(options.searchParams)\n    paths.forEach(path => searchParams.append('arg', `${path}`))\n    if (options.recursive != null) searchParams.set('recursive', options.recursive)\n\n    const res = await ky.post('pin/add', {\n      timeout: options.timeout,\n      signal: options.signal,\n      headers: options.headers,\n      searchParams\n    }).json()\n\n    return (res.Pins || []).map(cid => ({ cid: new CID(cid) }))\n  }\n})\n"
  },
  {
    "path": "src/pin/index.js",
    "content": "'use strict'\n\nmodule.exports = config => ({\n  add: require('./add')(config),\n  rm: require('./rm')(config),\n  ls: require('./ls')(config)\n})\n"
  },
  {
    "path": "src/pin/ls.js",
    "content": "'use strict'\n\nconst ndjson = require('iterable-ndjson')\nconst CID = require('cids')\nconst configure = require('../lib/configure')\nconst toIterable = require('stream-to-it/source')\n\nmodule.exports = configure(({ ky }) => {\n  return async function * ls (path, options) {\n    if (path && path.type) {\n      options = path\n      path = null\n    }\n\n    path = path || []\n    path = Array.isArray(path) ? path : [path]\n    options = options || {}\n\n    const searchParams = new URLSearchParams(options.searchParams)\n    searchParams.set('stream', options.stream == null ? true : options.stream)\n    path.forEach(p => searchParams.append('arg', `${p}`))\n    if (options.type) searchParams.set('type', options.type)\n\n    const res = await ky.post('pin/ls', {\n      timeout: options.timeout,\n      signal: options.signal,\n      headers: options.headers,\n      searchParams\n    })\n\n    for await (const pin of ndjson(toIterable(res.body))) {\n      if (pin.Keys) { // non-streaming response\n        for (const cid of Object.keys(pin.Keys)) {\n          yield { cid: new CID(cid), type: pin.Keys[cid].Type }\n        }\n        return\n      }\n      yield { cid: new CID(pin.Cid), type: pin.Type }\n    }\n  }\n})\n"
  },
  {
    "path": "src/pin/rm.js",
    "content": "'use strict'\n\nconst CID = require('cids')\nconst configure = require('../lib/configure')\n\nmodule.exports = configure(({ ky }) => {\n  return async (path, options) => {\n    options = options || {}\n\n    const searchParams = new URLSearchParams(options.searchParams)\n    searchParams.set('arg', `${path}`)\n    if (options.recursive != null) searchParams.set('recursive', options.recursive)\n\n    const res = await ky.post('pin/rm', {\n      timeout: options.timeout,\n      signal: options.signal,\n      headers: options.headers,\n      searchParams\n    }).json()\n\n    return (res.Pins || []).map(cid => ({ cid: new CID(cid) }))\n  }\n})\n"
  },
  {
    "path": "src/ping.js",
    "content": "'use strict'\n\nconst ndjson = require('iterable-ndjson')\nconst configure = require('./lib/configure')\nconst toIterable = require('stream-to-it/source')\nconst toCamel = require('./lib/object-to-camel')\n\nmodule.exports = configure(({ ky }) => {\n  return async function * ping (peerId, options) {\n    options = options || {}\n\n    const searchParams = new URLSearchParams(options.searchParams)\n    searchParams.set('arg', `${peerId}`)\n    if (options.count != null) searchParams.set('count', options.count)\n\n    const res = await ky.post('ping', {\n      timeout: options.timeout,\n      signal: options.signal,\n      headers: options.headers,\n      searchParams\n    })\n\n    for await (const chunk of ndjson(toIterable(res.body))) {\n      yield toCamel(chunk)\n    }\n  }\n})\n"
  },
  {
    "path": "src/pubsub/index.js",
    "content": "'use strict'\n\nmodule.exports = config => ({\n  ls: require('./ls')(config),\n  peers: require('./peers')(config),\n  publish: require('./publish')(config),\n  subscribe: require('./subscribe')(config),\n  unsubscribe: require('./unsubscribe')(config)\n})\n"
  },
  {
    "path": "src/pubsub/ls.js",
    "content": "'use strict'\n\nconst configure = require('../lib/configure')\n\nmodule.exports = configure(({ ky }) => {\n  return async (options) => {\n    options = options || {}\n\n    const { Strings } = await ky.post('pubsub/ls', {\n      timeout: options.timeout,\n      signal: options.signal,\n      headers: options.headers,\n      searchParams: options.searchParams\n    }).json()\n\n    return Strings || []\n  }\n})\n"
  },
  {
    "path": "src/pubsub/peers.js",
    "content": "'use strict'\n\nconst configure = require('../lib/configure')\n\nmodule.exports = configure(({ ky }) => {\n  return async (topic, options) => {\n    if (!options && typeof topic === 'object') {\n      options = topic\n      topic = null\n    }\n\n    options = options || {}\n\n    const searchParams = new URLSearchParams(options.searchParams)\n    searchParams.set('arg', topic)\n\n    const { Strings } = await ky.post('pubsub/peers', {\n      timeout: options.timeout,\n      signal: options.signal,\n      headers: options.headers,\n      searchParams\n    }).json()\n\n    return Strings || []\n  }\n})\n"
  },
  {
    "path": "src/pubsub/publish.js",
    "content": "'use strict'\n\nconst { Buffer } = require('buffer')\nconst configure = require('../lib/configure')\nconst encodeBuffer = require('../lib/encode-buffer-uri-component')\n\nmodule.exports = configure(({ ky }) => {\n  return async (topic, data, options) => {\n    options = options || {}\n    data = Buffer.from(data)\n\n    const searchParams = new URLSearchParams(options.searchParams)\n    searchParams.set('arg', topic)\n\n    const res = await ky.post(`pubsub/pub?${searchParams}&arg=${encodeBuffer(data)}`, {\n      timeout: options.timeout,\n      signal: options.signal,\n      headers: options.headers\n    }).text()\n\n    return res\n  }\n})\n"
  },
  {
    "path": "src/pubsub/subscribe.js",
    "content": "'use strict'\n\nconst ndjson = require('iterable-ndjson')\nconst bs58 = require('bs58')\nconst { Buffer } = require('buffer')\nconst log = require('debug')('ipfs-http-client:pubsub:subscribe')\nconst configure = require('../lib/configure')\nconst toIterable = require('stream-to-it/source')\nconst SubscriptionTracker = require('./subscription-tracker')\n\nmodule.exports = configure((config) => {\n  const ky = config.ky\n  const subsTracker = SubscriptionTracker.singleton()\n  const publish = require('./publish')(config)\n\n  return async (topic, handler, options) => {\n    options = options || {}\n    options.signal = subsTracker.subscribe(topic, handler, options.signal)\n\n    const searchParams = new URLSearchParams(options.searchParams)\n    searchParams.set('arg', topic)\n    if (options.discover != null) searchParams.set('discover', options.discover)\n\n    let res\n\n    // In Firefox, the initial call to fetch does not resolve until some data\n    // is received. If this doesn't happen within 1 second send an empty message\n    // to kickstart the process.\n    const ffWorkaround = setTimeout(async () => {\n      log(`Publishing empty message to \"${topic}\" to resolve subscription request`)\n      try {\n        await publish(topic, Buffer.alloc(0), options)\n      } catch (err) {\n        log('Failed to publish empty message', err)\n      }\n    }, 1000)\n\n    try {\n      res = await ky.post('pubsub/sub', {\n        timeout: options.timeout,\n        signal: options.signal,\n        headers: options.headers,\n        searchParams\n      })\n    } catch (err) { // Initial subscribe fail, ensure we clean up\n      subsTracker.unsubscribe(topic, handler)\n      throw err\n    }\n\n    clearTimeout(ffWorkaround)\n\n    readMessages(ndjson(toIterable(res.body)), {\n      onMessage: handler,\n      onEnd: () => subsTracker.unsubscribe(topic, handler),\n      onError: options.onError\n    })\n  }\n})\n\nasync function readMessages (msgStream, { onMessage, onEnd, onError }) {\n  onError = onError || log\n\n  try {\n    for await (const msg of msgStream) {\n      try {\n        onMessage({\n          from: bs58.encode(Buffer.from(msg.from, 'base64')).toString(),\n          data: Buffer.from(msg.data, 'base64'),\n          seqno: Buffer.from(msg.seqno, 'base64'),\n          topicIDs: msg.topicIDs\n        })\n      } catch (err) {\n        err.message = `Failed to parse pubsub message: ${err.message}`\n        onError(err, false, msg) // Not fatal\n      }\n    }\n  } catch (err) {\n    // FIXME: In testing with Chrome, err.type is undefined (should not be!)\n    // Temporarily use the name property instead.\n    if (err.type !== 'aborted' && err.name !== 'AbortError') {\n      onError(err, true) // Fatal\n    }\n  } finally {\n    onEnd()\n  }\n}\n"
  },
  {
    "path": "src/pubsub/subscription-tracker.js",
    "content": "'use strict'\n\nconst AbortController = require('abort-controller')\n\nclass SubscriptionTracker {\n  constructor () {\n    this._subs = new Map()\n  }\n\n  static singleton () {\n    if (SubscriptionTracker.instance) return SubscriptionTracker.instance\n    SubscriptionTracker.instance = new SubscriptionTracker()\n    return SubscriptionTracker.instance\n  }\n\n  subscribe (topic, handler, signal) {\n    const topicSubs = this._subs.get(topic) || []\n\n    if (topicSubs.find(s => s.handler === handler)) {\n      throw new Error(`Already subscribed to ${topic} with this handler`)\n    }\n\n    // Create controller so a call to unsubscribe can cancel the request\n    const controller = new AbortController()\n\n    this._subs.set(topic, [{ handler, controller }].concat(topicSubs))\n\n    // If there is an external signal, forward the abort event\n    if (signal) {\n      signal.addEventListener('abort', () => this.unsubscribe(topic, handler))\n    }\n\n    return controller.signal\n  }\n\n  unsubscribe (topic, handler) {\n    const subs = this._subs.get(topic) || []\n    let unsubs\n\n    if (handler) {\n      this._subs.set(topic, subs.filter(s => s.handler !== handler))\n      unsubs = subs.filter(s => s.handler === handler)\n    } else {\n      this._subs.set(topic, [])\n      unsubs = subs\n    }\n\n    unsubs.forEach(s => s.controller.abort())\n  }\n}\n\nmodule.exports = SubscriptionTracker\n"
  },
  {
    "path": "src/pubsub/unsubscribe.js",
    "content": "'use strict'\n\nconst configure = require('../lib/configure')\nconst SubscriptionTracker = require('./subscription-tracker')\n\nmodule.exports = configure(({ ky }) => {\n  const subsTracker = SubscriptionTracker.singleton()\n  // eslint-disable-next-line require-await\n  return async (topic, handler) => subsTracker.unsubscribe(topic, handler)\n})\n"
  },
  {
    "path": "src/refs/index.js",
    "content": "'use strict'\n\nconst configure = require('../lib/configure')\nconst { Buffer } = require('buffer')\nconst CID = require('cids')\nconst ndjson = require('iterable-ndjson')\nconst toIterable = require('stream-to-it/source')\nconst toCamel = require('../lib/object-to-camel')\n\nmodule.exports = config => {\n  const refs = (configure(({ ky }) => {\n    return async function * refs (args, options) {\n      options = options || {}\n\n      const searchParams = new URLSearchParams()\n\n      if (options.format !== undefined) {\n        searchParams.set('format', options.format)\n      }\n\n      if (options.edges !== undefined) {\n        searchParams.set('edges', options.edges)\n      }\n\n      if (options.unique !== undefined) {\n        searchParams.set('unique', options.unique)\n      }\n\n      if (options.recursive !== undefined) {\n        searchParams.set('recursive', options.recursive)\n      }\n\n      if (options.maxDepth !== undefined) {\n        searchParams.set('max-depth', options.maxDepth)\n      }\n\n      if (!Array.isArray(args)) {\n        args = [args]\n      }\n\n      for (const arg of args) {\n        searchParams.append('arg', `${Buffer.isBuffer(arg) ? new CID(arg) : arg}`)\n      }\n\n      const res = await ky.post('refs', {\n        timeout: options.timeout,\n        signal: options.signal,\n        headers: options.headers,\n        searchParams\n      })\n\n      for await (const file of ndjson(toIterable(res.body))) {\n        yield toCamel(file)\n      }\n    }\n  }))(config)\n\n  refs.local = require('./local')(config)\n\n  return refs\n}\n"
  },
  {
    "path": "src/refs/local.js",
    "content": "'use strict'\n\nconst configure = require('../lib/configure')\nconst ndjson = require('iterable-ndjson')\nconst toIterable = require('stream-to-it/source')\nconst toCamel = require('../lib/object-to-camel')\n\nmodule.exports = configure(({ ky }) => {\n  return async function * refsLocal (options) {\n    options = options || {}\n\n    const res = await ky.post('refs/local', {\n      timeout: options.timeout,\n      signal: options.signal,\n      headers: options.headers\n    })\n\n    for await (const file of ndjson(toIterable(res.body))) {\n      yield toCamel(file)\n    }\n  }\n})\n"
  },
  {
    "path": "src/repo/gc.js",
    "content": "'use strict'\n\nconst CID = require('cids')\nconst ndjson = require('iterable-ndjson')\nconst configure = require('../lib/configure')\nconst toIterable = require('stream-to-it/source')\n\nmodule.exports = configure(({ ky }) => {\n  return async function * gc (peerId, options) {\n    options = options || {}\n\n    const searchParams = new URLSearchParams(options.searchParams)\n    if (options.streamErrors) searchParams.set('stream-errors', options.streamErrors)\n\n    const res = await ky.post('repo/gc', {\n      timeout: options.timeout,\n      signal: options.signal,\n      headers: options.headers,\n      searchParams\n    })\n\n    for await (const gcResult of ndjson(toIterable(res.body))) {\n      yield {\n        err: gcResult.Error ? new Error(gcResult.Error) : null,\n        cid: (gcResult.Key || {})['/'] ? new CID(gcResult.Key['/']) : null\n      }\n    }\n  }\n})\n"
  },
  {
    "path": "src/repo/index.js",
    "content": "'use strict'\n\nmodule.exports = config => ({\n  gc: require('./gc')(config),\n  stat: require('./stat')(config),\n  version: require('./version')(config)\n})\n"
  },
  {
    "path": "src/repo/stat.js",
    "content": "'use strict'\n\nconst Big = require('bignumber.js')\nconst configure = require('../lib/configure')\n\nmodule.exports = configure(({ ky }) => {\n  return async options => {\n    options = options || {}\n\n    const searchParams = new URLSearchParams(options.searchParams)\n    if (options.sizeOnly) searchParams.set('size-only', options.sizeOnly)\n\n    const res = await ky.post('repo/stat', {\n      timeout: options.timeout,\n      signal: options.signal,\n      headers: options.headers,\n      searchParams\n    }).json()\n\n    return {\n      numObjects: new Big(res.NumObjects),\n      repoSize: new Big(res.RepoSize),\n      repoPath: res.RepoPath,\n      version: res.Version,\n      storageMax: new Big(res.StorageMax)\n    }\n  }\n})\n"
  },
  {
    "path": "src/repo/version.js",
    "content": "'use strict'\n\nconst configure = require('../lib/configure')\n\nmodule.exports = configure(({ ky }) => {\n  return async options => {\n    options = options || {}\n\n    const searchParams = new URLSearchParams(options.searchParams)\n    if (options.sizeOnly) searchParams.set('size-only', options.sizeOnly)\n\n    const res = await ky.post('repo/version', {\n      timeout: options.timeout,\n      signal: options.signal,\n      headers: options.headers,\n      searchParams\n    }).json()\n\n    return res.Version\n  }\n})\n"
  },
  {
    "path": "src/resolve.js",
    "content": "'use strict'\n\nconst configure = require('./lib/configure')\n\nmodule.exports = configure(({ ky }) => {\n  return async (path, options) => {\n    options = options || {}\n\n    const searchParams = new URLSearchParams(options.searchParams)\n    searchParams.set('arg', `${path}`)\n    if (options.cidBase) searchParams.set('cid-base', options.cidBase)\n    if (options.dhtRecordCount) searchParams.set('dht-record-count', options.dhtRecordCount)\n    if (options.dhtTimeout) searchParams.set('dht-timeout', options.dhtTimeout)\n    if (options.recursive != null) searchParams.set('recursive', options.recursive)\n\n    const res = await ky.post('resolve', {\n      timeout: options.timeout,\n      signal: options.signal,\n      headers: options.headers,\n      searchParams\n    }).json()\n\n    return res.Path\n  }\n})\n"
  },
  {
    "path": "src/stats/bw.js",
    "content": "'use strict'\n\nconst ndjson = require('iterable-ndjson')\nconst Big = require('bignumber.js')\nconst configure = require('../lib/configure')\nconst toIterable = require('stream-to-it/source')\n\nmodule.exports = configure(({ ky }) => {\n  return async function * bw (options) {\n    options = options || {}\n\n    const searchParams = new URLSearchParams(options.searchParams)\n    if (options.interval) searchParams.set('interval', options.interval)\n    if (options.peer) searchParams.set('peer', options.peer)\n    if (options.poll != null) searchParams.set('poll', options.poll)\n    if (options.proto) searchParams.set('proto', options.proto)\n\n    const res = await ky.post('stats/bw', {\n      timeout: options.timeout,\n      signal: options.signal,\n      headers: options.headers,\n      searchParams\n    })\n\n    for await (const stats of ndjson(toIterable(res.body))) {\n      yield {\n        totalIn: new Big(stats.TotalIn),\n        totalOut: new Big(stats.TotalOut),\n        rateIn: new Big(stats.RateIn),\n        rateOut: new Big(stats.RateOut)\n      }\n    }\n  }\n})\n"
  },
  {
    "path": "src/stats/index.js",
    "content": "'use strict'\n\nmodule.exports = config => ({\n  bitswap: require('../bitswap/stat')(config),\n  bw: require('./bw')(config),\n  repo: require('../repo/stat')(config)\n})\n"
  },
  {
    "path": "src/stop.js",
    "content": "'use strict'\n\nconst configure = require('./lib/configure')\n\nmodule.exports = configure(({ ky }) => {\n  return options => {\n    options = options || {}\n\n    return ky.post('shutdown', {\n      timeout: options.timeout,\n      signal: options.signal,\n      headers: options.headers,\n      searchParams: options.searchParams\n    }).text()\n  }\n})\n"
  },
  {
    "path": "src/swarm/addrs.js",
    "content": "'use strict'\n\nconst multiaddr = require('multiaddr')\nconst configure = require('../lib/configure')\n\nmodule.exports = configure(({ ky }) => {\n  return async options => {\n    options = options || {}\n\n    const res = await ky.post('swarm/addrs', {\n      timeout: options.timeout,\n      signal: options.signal,\n      headers: options.headers,\n      searchParams: options.searchParams\n    }).json()\n\n    return Object.keys(res.Addrs).map(id => ({\n      id,\n      addrs: (res.Addrs[id] || []).map(a => multiaddr(a))\n    }))\n  }\n})\n"
  },
  {
    "path": "src/swarm/connect.js",
    "content": "'use strict'\n\nconst configure = require('../lib/configure')\n\nmodule.exports = configure(({ ky }) => {\n  return async (addrs, options) => {\n    addrs = Array.isArray(addrs) ? addrs : [addrs]\n    options = options || {}\n\n    const searchParams = new URLSearchParams(options.searchParams)\n    addrs.forEach(addr => searchParams.append('arg', addr))\n\n    const res = await ky.post('swarm/connect', {\n      timeout: options.timeout,\n      signal: options.signal,\n      headers: options.headers,\n      searchParams\n    }).json()\n\n    return res.Strings || []\n  }\n})\n"
  },
  {
    "path": "src/swarm/disconnect.js",
    "content": "'use strict'\n\nconst configure = require('../lib/configure')\n\nmodule.exports = configure(({ ky }) => {\n  return async (addrs, options) => {\n    addrs = Array.isArray(addrs) ? addrs : [addrs]\n    options = options || {}\n\n    const searchParams = new URLSearchParams(options.searchParams)\n    addrs.forEach(addr => searchParams.append('arg', `${addr}`))\n\n    const res = await ky.post('swarm/disconnect', {\n      timeout: options.timeout,\n      signal: options.signal,\n      headers: options.headers,\n      searchParams\n    }).json()\n\n    return res.Strings || []\n  }\n})\n"
  },
  {
    "path": "src/swarm/index.js",
    "content": "'use strict'\n\nmodule.exports = config => ({\n  addrs: require('./addrs')(config),\n  connect: require('./connect')(config),\n  disconnect: require('./disconnect')(config),\n  localAddrs: require('./localAddrs')(config),\n  peers: require('./peers')(config)\n})\n"
  },
  {
    "path": "src/swarm/localAddrs.js",
    "content": "'use strict'\n\nconst multiaddr = require('multiaddr')\nconst configure = require('../lib/configure')\n\nmodule.exports = configure(({ ky }) => {\n  return async options => {\n    options = options || {}\n\n    const searchParams = new URLSearchParams(options.searchParams)\n    if (options.id != null) searchParams.append('id', options.id)\n\n    const res = await ky.post('swarm/addrs/local', {\n      timeout: options.timeout,\n      signal: options.signal,\n      headers: options.headers,\n      searchParams\n    }).json()\n\n    return (res.Strings || []).map(a => multiaddr(a))\n  }\n})\n"
  },
  {
    "path": "src/swarm/peers.js",
    "content": "'use strict'\n\nconst multiaddr = require('multiaddr')\nconst configure = require('../lib/configure')\n\nmodule.exports = configure(({ ky }) => {\n  return async options => {\n    options = options || {}\n\n    const searchParams = new URLSearchParams(options.searchParams)\n    if (options.direction != null) searchParams.append('direction', options.direction)\n    if (options.latency != null) searchParams.append('latency', options.latency)\n    if (options.streams != null) searchParams.append('streams', options.streams)\n    if (options.verbose != null) searchParams.append('verbose', options.verbose)\n\n    const res = await ky.post('swarm/peers', {\n      timeout: options.timeout,\n      signal: options.signal,\n      headers: options.headers,\n      searchParams\n    }).json()\n\n    return (res.Peers || []).map(peer => {\n      const info = {}\n      try {\n        info.addr = multiaddr(peer.Addr)\n        info.peer = peer.Peer\n      } catch (error) {\n        info.error = error\n        info.rawPeerInfo = peer\n      }\n      if (peer.Muxer) {\n        info.muxer = peer.Muxer\n      }\n      if (peer.Latency) {\n        info.latency = peer.Latency\n      }\n      if (peer.Streams) {\n        info.streams = peer.Streams\n      }\n      if (peer.Direction != null) {\n        info.direction = peer.Direction\n      }\n      return info\n    })\n  }\n})\n"
  },
  {
    "path": "src/update.js",
    "content": "'use strict'\n\nconst configure = require('./lib/configure')\n\nmodule.exports = configure(({ ky }) => {\n  return options => {\n    options = options || {}\n\n    return ky.post('update', {\n      timeout: options.timeout,\n      signal: options.signal,\n      headers: options.headers,\n      searchParams: options.searchParams\n    }).text()\n  }\n})\n"
  },
  {
    "path": "src/version.js",
    "content": "'use strict'\n\nconst configure = require('./lib/configure')\nconst toCamel = require('./lib/object-to-camel')\n\nmodule.exports = configure(({ ky }) => {\n  return async options => {\n    options = options || {}\n\n    const res = await ky.post('version', {\n      timeout: options.timeout,\n      signal: options.signal,\n      headers: options.headers,\n      searchParams: options.searchParams\n    }).json()\n\n    return toCamel(res)\n  }\n})\n"
  },
  {
    "path": "test/commands.spec.js",
    "content": "/* eslint-env mocha */\n'use strict'\n\nconst { expect } = require('interface-ipfs-core/src/utils/mocha')\nconst f = require('./utils/factory')()\n\ndescribe('.commands', function () {\n  this.timeout(60 * 1000)\n\n  let ipfs\n\n  before(async () => {\n    ipfs = (await f.spawn()).api\n  })\n\n  after(() => f.clean())\n\n  it('lists commands', async () => {\n    const res = await ipfs.commands()\n\n    expect(res).to.exist()\n  })\n})\n"
  },
  {
    "path": "test/constructor.spec.js",
    "content": "/* eslint-env mocha, browser */\n'use strict'\n\nconst multiaddr = require('multiaddr')\nconst { expect } = require('interface-ipfs-core/src/utils/mocha')\nconst f = require('./utils/factory')()\nconst ipfsClient = require('../src/index.js')\n\ndescribe('ipfs-http-client constructor tests', () => {\n  describe('parameter permuations', () => {\n    it('none', () => {\n      const ipfs = ipfsClient()\n      if (typeof self !== 'undefined') {\n        const { hostname, port } = self.location\n        expectConfig(ipfs, { host: hostname, port })\n      } else {\n        expectConfig(ipfs, {})\n      }\n    })\n\n    it('opts', () => {\n      const host = 'wizard.world'\n      const port = '999'\n      const protocol = 'https'\n      const ipfs = ipfsClient({ host, port, protocol })\n      expectConfig(ipfs, { host, port, protocol })\n    })\n\n    it('multiaddr dns4 string (implicit http)', () => {\n      const host = 'foo.com'\n      const port = '1001'\n      const protocol = 'http' // default to http if not specified in multiaddr\n      const addr = `/dns4/${host}/tcp/${port}`\n      const ipfs = ipfsClient(addr)\n      expectConfig(ipfs, { host, port, protocol })\n    })\n\n    it('multiaddr dns4 string (explicit https)', () => {\n      const host = 'foo.com'\n      const port = '1001'\n      const protocol = 'https'\n      const addr = `/dns4/${host}/tcp/${port}/${protocol}`\n      const ipfs = ipfsClient(addr)\n      expectConfig(ipfs, { host, port, protocol })\n    })\n\n    it('multiaddr ipv4 string (implicit http)', () => {\n      const host = '101.101.101.101'\n      const port = '1001'\n      const protocol = 'http'\n      const addr = `/ip4/${host}/tcp/${port}`\n      const ipfs = ipfsClient(addr)\n      expectConfig(ipfs, { host, port, protocol })\n    })\n\n    it('multiaddr ipv4 string (explicit https)', () => {\n      const host = '101.101.101.101'\n      const port = '1001'\n      const protocol = 'https'\n      const addr = `/ip4/${host}/tcp/${port}/${protocol}`\n      const ipfs = ipfsClient(addr)\n      expectConfig(ipfs, { host, port, protocol })\n    })\n\n    it('multiaddr instance', () => {\n      const host = 'ace.place'\n      const port = '1001'\n      const addr = multiaddr(`/dns4/${host}/tcp/${port}`)\n      const ipfs = ipfsClient(addr)\n      expectConfig(ipfs, { host, port })\n    })\n\n    it('host and port strings', () => {\n      const host = '1.1.1.1'\n      const port = '9999'\n      const ipfs = ipfsClient({ host, port })\n      expectConfig(ipfs, { host, port })\n    })\n\n    it('host, port and api path', () => {\n      const host = '10.100.100.255'\n      const port = '9999'\n      const apiPath = '/future/api/v1/'\n      const ipfs = ipfsClient({ host, port, apiPath })\n      expectConfig(ipfs, { host, port, apiPath: apiPath.slice(0, -1) })\n    })\n\n    it('throws on invalid multiaddr', () => {\n      expect(() => ipfsClient('/dns4')).to.throw('invalid address')\n      expect(() => ipfsClient('/hello')).to.throw('no protocol with name')\n      expect(() => ipfsClient('/dns4/ipfs.io')).to.throw()\n    })\n  })\n\n  describe('integration', () => {\n    let ipfsd\n\n    before(async function () {\n      this.timeout(60 * 1000) // slow CI\n\n      ipfsd = await f.spawn()\n    })\n\n    after(() => f.clean())\n\n    it('can connect to an ipfs http api', async () => {\n      await clientWorks(ipfsClient(ipfsd.apiAddr))\n    })\n  })\n})\n\nasync function clientWorks (client) {\n  const id = await client.id()\n\n  expect(id).to.have.a.property('id')\n  expect(id).to.have.a.property('publicKey')\n}\n\nfunction expectConfig (ipfs, { host, port, protocol, apiPath }) {\n  const conf = ipfs.getEndpointConfig()\n  expect(conf.host).to.be.oneOf([host, 'localhost', ''])\n  expect(conf.port).to.be.oneOf([port, '5001', '80'])\n  expect(conf.protocol).to.equal(protocol || 'http')\n  expect(conf['api-path']).to.equal(apiPath || '/api/v0')\n}\n"
  },
  {
    "path": "test/custom-headers.spec.js",
    "content": "/* eslint-env mocha */\n'use strict'\n\nconst { isNode } = require('ipfs-utils/src/env')\nconst { expect } = require('interface-ipfs-core/src/utils/mocha')\nconst ipfsClient = require('../src')\n\ndescribe('custom headers', function () {\n  // do not test in browser\n  if (!isNode) { return }\n  let ipfs\n  // initialize ipfs with custom headers\n  before(() => {\n    ipfs = ipfsClient({\n      host: 'localhost',\n      port: 6001,\n      protocol: 'http',\n      headers: {\n        authorization: 'Bearer ' + 'YOLO'\n      }\n    })\n  })\n\n  it('are supported', (done) => {\n    // spin up a test http server to inspect the requests made by the library\n    const server = require('http').createServer((req, res) => {\n      req.on('data', () => {})\n      req.on('end', () => {\n        res.writeHead(200)\n        res.write(JSON.stringify({}))\n        res.end()\n        // ensure custom headers are present\n        expect(req.headers.authorization).to.equal('Bearer ' + 'YOLO')\n        server.close()\n        done()\n      })\n    })\n\n    server.listen(6001, () => {\n      ipfs.id((err, res) => {\n        if (err) {\n          throw err\n        }\n        // this call is used to test that headers are being sent.\n      })\n    })\n  })\n})\n"
  },
  {
    "path": "test/dag.spec.js",
    "content": "/* eslint-env mocha */\n/* eslint max-nested-callbacks: [\"error\", 8] */\n\n'use strict'\n\nconst { expect } = require('interface-ipfs-core/src/utils/mocha')\nconst { DAGNode } = require('ipld-dag-pb')\nconst CID = require('cids')\nconst f = require('./utils/factory')()\n\nlet ipfs\n\ndescribe('.dag', function () {\n  this.timeout(20 * 1000)\n  before(async function () {\n    ipfs = (await f.spawn()).api\n  })\n\n  after(() => f.clean())\n\n  it('should be able to put and get a DAG node with format dag-pb', async () => {\n    const data = Buffer.from('some data')\n    const node = new DAGNode(data)\n\n    let cid = await ipfs.dag.put(node, { format: 'dag-pb', hashAlg: 'sha2-256' })\n    cid = cid.toV0()\n    expect(cid.codec).to.equal('dag-pb')\n    cid = cid.toBaseEncodedString('base58btc')\n    // expect(cid).to.equal('bafybeig3t3eugdchignsgkou3ly2mmy4ic4gtfor7inftnqn3yq4ws3a5u')\n    expect(cid).to.equal('Qmd7xRhW5f29QuBFtqu3oSD27iVy35NRB91XFjmKFhtgMr')\n\n    const result = await ipfs.dag.get(cid)\n\n    expect(result.value.Data).to.deep.equal(data)\n  })\n\n  it('should be able to put and get a DAG node with format dag-cbor', async () => {\n    const cbor = { foo: 'dag-cbor-bar' }\n    let cid = await ipfs.dag.put(cbor, { format: 'dag-cbor', hashAlg: 'sha2-256' })\n\n    expect(cid.codec).to.equal('dag-cbor')\n    cid = cid.toBaseEncodedString('base32')\n    expect(cid).to.equal('bafyreic6f672hnponukaacmk2mmt7vs324zkagvu4hcww6yba6kby25zce')\n\n    const result = await ipfs.dag.get(cid)\n\n    expect(result.value).to.deep.equal(cbor)\n  })\n\n  it('should callback with error when missing DAG resolver for multicodec from requested CID', async () => {\n    const block = await ipfs.block.put(Buffer.from([0, 1, 2, 3]), {\n      cid: new CID('z8mWaJ1dZ9fH5EetPuRsj8jj26pXsgpsr')\n    })\n\n    await expect(ipfs.dag.get(block.cid)).to.be.rejectedWith('Missing IPLD format \"git-raw\"')\n  })\n})\n"
  },
  {
    "path": "test/diag.spec.js",
    "content": "/* eslint-env mocha */\n'use strict'\n\nconst { expect } = require('interface-ipfs-core/src/utils/mocha')\nconst platform = require('browser-process-platform')\nconst f = require('./utils/factory')()\n\ndescribe('.diag', function () {\n  this.timeout(50 * 1000)\n\n  // go-ipfs does not support these on Windows\n  if (platform === 'win32') { return }\n\n  let ipfs\n\n  before(async () => {\n    ipfs = (await f.spawn()).api\n  })\n\n  after(() => f.clean())\n\n  describe('api API', () => {\n    // Disabled in go-ipfs 0.4.10\n    it.skip('.diag.net', async () => {\n      const res = await ipfs.diag.net()\n\n      expect(res).to.exist()\n    })\n\n    it('.diag.sys', async () => {\n      const res = await ipfs.diag.sys()\n\n      expect(res).to.exist()\n      expect(res).to.have.a.property('memory')\n      expect(res).to.have.a.property('diskinfo')\n    })\n\n    it('.diag.cmds', async () => {\n      const res = await ipfs.diag.cmds()\n\n      expect(res).to.exist()\n    })\n  })\n})\n"
  },
  {
    "path": "test/endpoint-config.spec.js",
    "content": "/* eslint-env mocha */\n/* eslint max-nested-callbacks: [\"error\", 8] */\n'use strict'\n\nconst { expect } = require('interface-ipfs-core/src/utils/mocha')\nconst ipfsClient = require('../src')\n\ndescribe('.getEndpointConfig', () => {\n  it('should return the endpoint configuration', function () {\n    const ipfs = ipfsClient('https://127.0.0.1:5501/ipfs/api/')\n    const endpoint = ipfs.getEndpointConfig()\n\n    expect(endpoint.host).to.equal('127.0.0.1')\n    expect(endpoint.protocol).to.equal('https')\n    expect(endpoint['api-path']).to.equal('/ipfs/api')\n    expect(endpoint.port).to.equal('5501')\n  })\n})\n"
  },
  {
    "path": "test/exports.spec.js",
    "content": "/* eslint-env mocha, browser */\n'use strict'\n\nconst CID = require('cids')\nconst multiaddr = require('multiaddr')\nconst multibase = require('multibase')\nconst multicodec = require('multicodec')\nconst multihash = require('multihashes')\nconst { expect } = require('interface-ipfs-core/src/utils/mocha')\n\nconst IpfsHttpClient = require('../')\n\ndescribe('exports', () => {\n  it('should export the expected types and utilities', () => {\n    expect(IpfsHttpClient.Buffer).to.equal(Buffer)\n    expect(IpfsHttpClient.CID).to.equal(CID)\n    expect(IpfsHttpClient.multiaddr).to.equal(multiaddr)\n    expect(IpfsHttpClient.multibase).to.equal(multibase)\n    expect(IpfsHttpClient.multicodec).to.equal(multicodec)\n    expect(IpfsHttpClient.multihash).to.equal(multihash)\n  })\n})\n"
  },
  {
    "path": "test/files-mfs.spec.js",
    "content": "/* eslint-env mocha */\n/* eslint max-nested-callbacks: [\"error\", 8] */\n'use strict'\n\nconst { expect } = require('interface-ipfs-core/src/utils/mocha')\nconst loadFixture = require('aegir/fixtures')\nconst mh = require('multihashes')\nconst all = require('it-all')\nconst pipe = require('it-pipe')\nconst { TimeoutError } = require('ky-universal')\n\nconst f = require('./utils/factory')()\n\nconst testfile = loadFixture('test/fixtures/testfile.txt')\n\n// TODO: Test against all algorithms Object.keys(mh.names)\n// This subset is known to work with both go-ipfs and js-ipfs as of 2017-09-05\nconst HASH_ALGS = [\n  'sha1',\n  'sha2-256',\n  'sha2-512',\n  // 'keccak-224', // go throws\n  'keccak-256',\n  // 'keccak-384', // go throws\n  'keccak-512'\n]\n\ndescribe('.files (the MFS API part)', function () {\n  this.timeout(20 * 1000)\n\n  let ipfs\n\n  const expectedMultihash = 'Qma4hjFTnCasJ8PVp3mZbZK5g2vGDT4LByLJ7m8ciyRFZP'\n\n  before(async () => {\n    ipfs = (await f.spawn()).api\n  })\n\n  after(() => f.clean())\n\n  it('.add file for testing', async () => {\n    const res = await all(ipfs.add(testfile))\n\n    expect(res).to.have.length(1)\n    expect(res[0].cid.toString()).to.equal(expectedMultihash)\n    expect(res[0].path).to.equal(expectedMultihash)\n  })\n\n  it('.add with Buffer module', async () => {\n    const { Buffer } = require('buffer')\n\n    const expectedBufferMultihash = 'QmWfVY9y3xjsixTgbd9AorQxH7VtMpzfx2HaWtsoUYecaX'\n    const file = Buffer.from('hello')\n\n    const res = await all(ipfs.add(file))\n\n    expect(res).to.have.length(1)\n    expect(res[0].cid.toString()).to.equal(expectedBufferMultihash)\n    expect(res[0].path).to.equal(expectedBufferMultihash)\n  })\n\n  it('.add with empty path and buffer content', async () => {\n    const expectedHash = 'QmWfVY9y3xjsixTgbd9AorQxH7VtMpzfx2HaWtsoUYecaX'\n    const content = Buffer.from('hello')\n\n    const res = await all(ipfs.add([{ path: '', content }]))\n\n    expect(res).to.have.length(1)\n    expect(res[0].cid.toString()).to.equal(expectedHash)\n    expect(res[0].path).to.equal(expectedHash)\n  })\n\n  it('.add with cid-version=1 and raw-leaves=false', async () => {\n    const expectedCid = 'bafybeifogzovjqrcxvgt7g36y7g63hvwvoakledwk4b2fr2dl4wzawpnny'\n    const options = { cidVersion: 1, rawLeaves: false }\n\n    const res = await all(ipfs.add(testfile, options))\n\n    expect(res).to.have.length(1)\n    expect(res[0].cid.toString()).to.equal(expectedCid)\n    expect(res[0].path).to.equal(expectedCid)\n  })\n\n  it('.add with only-hash=true', async () => {\n    const content = String(Math.random() + Date.now())\n\n    const files = await all(ipfs.add(Buffer.from(content), { onlyHash: true }))\n    expect(files).to.have.length(1)\n\n    // 'ipfs.object.get(<hash>)' should timeout because content wasn't actually added\n    return expect(ipfs.object.get(files[0].cid, { timeout: 2000 }))\n      .to.be.rejectedWith(TimeoutError)\n  })\n\n  it('.add with options', async () => {\n    const res = await all(ipfs.add(testfile, { pin: false }))\n\n    expect(res).to.have.length(1)\n    expect(res[0].cid.toString()).to.equal(expectedMultihash)\n    expect(res[0].path).to.equal(expectedMultihash)\n  })\n\n  it('.add pins by default', async () => {\n    const newContent = Buffer.from(String(Math.random()))\n\n    const initialPins = await all(ipfs.pin.ls())\n\n    await all(ipfs.add(newContent))\n\n    const pinsAfterAdd = await all(ipfs.pin.ls())\n\n    expect(pinsAfterAdd.length).to.eql(initialPins.length + 1)\n  })\n\n  it('.add with pin=false', async () => {\n    const newContent = Buffer.from(String(Math.random()))\n\n    const initialPins = await all(ipfs.pin.ls())\n\n    await all(ipfs.add(newContent, { pin: false }))\n\n    const pinsAfterAdd = await all(ipfs.pin.ls())\n\n    expect(pinsAfterAdd.length).to.eql(initialPins.length)\n  })\n\n  HASH_ALGS.forEach((name) => {\n    it(`.add with hash=${name} and raw-leaves=false`, async () => {\n      const content = String(Math.random() + Date.now())\n      const file = {\n        path: content + '.txt',\n        content: Buffer.from(content)\n      }\n      const options = { hashAlg: name, rawLeaves: false }\n\n      const res = await all(ipfs.add([file], options))\n\n      expect(res).to.have.length(1)\n      const { cid } = res[0]\n      expect(mh.decode(cid.multihash).name).to.equal(name)\n    })\n  })\n\n  it('.add file with progress option', async () => {\n    let progress\n    let progressCount = 0\n\n    const progressHandler = (p) => {\n      progressCount += 1\n      progress = p\n    }\n\n    const res = await all(ipfs.add(testfile, { progress: progressHandler }))\n\n    expect(res).to.have.length(1)\n    expect(progress).to.be.equal(testfile.byteLength)\n    expect(progressCount).to.be.equal(1)\n  })\n\n  it('.add big file with progress option', async () => {\n    let progress = 0\n    let progressCount = 0\n\n    const progressHandler = (p) => {\n      progressCount += 1\n      progress = p\n    }\n\n    // TODO: needs to be using a big file\n    const res = await all(ipfs.add(testfile, { progress: progressHandler }))\n\n    expect(res).to.have.length(1)\n    expect(progress).to.be.equal(testfile.byteLength)\n    expect(progressCount).to.be.equal(1)\n  })\n\n  it('.add directory with progress option', async () => {\n    let progress = 0\n    let progressCount = 0\n\n    const progressHandler = (p) => {\n      progressCount += 1\n      progress = p\n    }\n\n    // TODO: needs to be using a directory\n    const res = await all(ipfs.add(testfile, { progress: progressHandler }))\n\n    expect(res).to.have.length(1)\n    expect(progress).to.be.equal(testfile.byteLength)\n    expect(progressCount).to.be.equal(1)\n  })\n\n  it('.add without progress options', async () => {\n    const res = await all(ipfs.add(testfile))\n\n    expect(res).to.have.length(1)\n  })\n\n  HASH_ALGS.forEach((name) => {\n    it(`.add with hash=${name} and raw-leaves=false`, async () => {\n      const content = String(Math.random() + Date.now())\n      const file = {\n        path: content + '.txt',\n        content: Buffer.from(content)\n      }\n      const options = { hashAlg: name, rawLeaves: false }\n\n      const res = await all(ipfs.add([file], options))\n\n      expect(res).to.have.length(1)\n      const { cid } = res[0]\n      expect(mh.decode(cid.multihash).name).to.equal(name)\n    })\n  })\n\n  it('.add with object chunks and iterable content', async () => {\n    const expectedCid = 'QmRf22bZar3WKmojipms22PkXH1MZGmvsqzQtuSvQE3uhm'\n\n    const res = await pipe(\n      [{ content: [Buffer.from('test')] }],\n      ipfs.add,\n      all\n    )\n\n    expect(res).to.have.length(1)\n    res[0].cid = res[0].cid.toString()\n    expect(res[0]).to.deep.equal({ path: expectedCid, cid: expectedCid, size: 12 })\n  })\n\n  it('.add with iterable', async () => {\n    const expectedCid = 'QmRf22bZar3WKmojipms22PkXH1MZGmvsqzQtuSvQE3uhm'\n    const res = await all(ipfs.add([Buffer.from('test')]))\n\n    expect(res).to.have.length(1)\n    res[0].cid = res[0].cid.toString()\n    expect(res[0]).to.deep.equal({ path: expectedCid, cid: expectedCid, size: 12 })\n  })\n\n  it('files.mkdir', async () => {\n    await ipfs.files.mkdir('/test-folder')\n  })\n\n  it('files.flush', async () => {\n    await ipfs.files.flush('/')\n  })\n\n  it('files.cp', async () => {\n    const folder = `/test-folder-${Math.random()}`\n\n    await ipfs.files.mkdir(folder)\n    await ipfs.files.cp([\n      '/ipfs/Qma4hjFTnCasJ8PVp3mZbZK5g2vGDT4LByLJ7m8ciyRFZP',\n      `${folder}/test-file-${Math.random()}`\n    ])\n  })\n\n  it('files.cp with non-array arguments', async () => {\n    const folder = `/test-folder-${Math.random()}`\n\n    await ipfs.files.mkdir(folder)\n    await ipfs.files.cp(\n      '/ipfs/Qma4hjFTnCasJ8PVp3mZbZK5g2vGDT4LByLJ7m8ciyRFZP',\n      `${folder}/test-file-${Math.random()}`\n    )\n  })\n\n  it('files.mv', async () => {\n    const folder = `/test-folder-${Math.random()}`\n    const source = `${folder}/test-file-${Math.random()}`\n    const dest = `${folder}/test-file-${Math.random()}`\n\n    await ipfs.files.mkdir(folder)\n    await ipfs.files.cp(\n      '/ipfs/Qma4hjFTnCasJ8PVp3mZbZK5g2vGDT4LByLJ7m8ciyRFZP',\n      source\n    )\n    await ipfs.files.mv([\n      source,\n      dest\n    ])\n  })\n\n  it('files.mv with non-array arguments', async () => {\n    const folder = `/test-folder-${Math.random()}`\n    const source = `${folder}/test-file-${Math.random()}`\n    const dest = `${folder}/test-file-${Math.random()}`\n\n    await ipfs.files.mkdir(folder)\n    await ipfs.files.cp(\n      '/ipfs/Qma4hjFTnCasJ8PVp3mZbZK5g2vGDT4LByLJ7m8ciyRFZP',\n      source\n    )\n    await ipfs.files.mv(\n      source,\n      dest\n    )\n  })\n\n  it('files.ls', async () => {\n    const folder = `/test-folder-${Math.random()}`\n    const file = `${folder}/test-file-${Math.random()}`\n\n    await ipfs.files.mkdir(folder)\n    await ipfs.files.write(file, Buffer.from('Hello, world'), {\n      create: true\n    })\n    const files = await all(ipfs.files.ls(folder))\n\n    expect(files.length).to.equal(1)\n  })\n\n  it('files.ls mfs root by default', async () => {\n    const folder = `test-folder-${Math.random()}`\n\n    await ipfs.files.mkdir(`/${folder}`)\n    const files = await all(ipfs.files.ls())\n\n    expect(files.find(file => file.name === folder)).to.be.ok()\n  })\n\n  it('files.write', async () => {\n    await ipfs.files.write('/test-folder/test-file-2.txt', Buffer.from('hello world'), {\n      create: true\n    })\n\n    const buf = Buffer.concat(await all(ipfs.files.read('/test-folder/test-file-2.txt')))\n\n    expect(buf.toString()).to.be.equal('hello world')\n  })\n\n  it('files.write without options', async () => {\n    await ipfs.files.write('/test-folder/test-file-2.txt', Buffer.from('hello world'))\n\n    const buf = Buffer.concat(await all(ipfs.files.read('/test-folder/test-file-2.txt')))\n\n    expect(buf.toString()).to.be.equal('hello world')\n  })\n\n  it('files.stat', async () => {\n    const folder = `/test-folder-${Math.random()}`\n    const file = `${folder}/test-file-${Math.random()}`\n\n    await ipfs.files.mkdir(folder)\n    await ipfs.files.write(file, testfile, {\n      create: true\n    })\n\n    const stats = await ipfs.files.stat(file)\n    stats.cid = stats.cid.toString()\n\n    expect(stats).to.deep.equal({\n      cid: 'QmQhouoDPAnzhVM148yCa9CbUXK65wSEAZBtgrLGHtmdmP',\n      size: 12,\n      cumulativeSize: 70,\n      blocks: 1,\n      type: 'file',\n      withLocality: false\n    })\n  })\n\n  it('files.stat file that does not exist()', async () => {\n    await expect(ipfs.files.stat('/test-folder/does-not-exist()')).to.be.rejectedWith({\n      code: 0,\n      type: 'error'\n    })\n  })\n\n  it('files.read', async () => {\n    const folder = `/test-folder-${Math.random()}`\n    const file = `${folder}/test-file-${Math.random()}`\n\n    await ipfs.files.mkdir(folder)\n    await ipfs.files.write(file, testfile, {\n      create: true\n    })\n    const buf = Buffer.concat(await all(ipfs.files.read(file)))\n\n    expect(Buffer.from(buf)).to.deep.equal(testfile)\n  })\n\n  it('files.rm without options', async () => {\n    await ipfs.files.rm('/test-folder/test-file-2.txt')\n  })\n\n  it('files.rm', async () => {\n    await ipfs.files.rm('/test-folder', { recursive: true })\n  })\n})\n"
  },
  {
    "path": "test/fixtures/.gitattributes",
    "content": "* -text\n"
  },
  {
    "path": "test/fixtures/r-config.json",
    "content": "{}\n"
  },
  {
    "path": "test/fixtures/ssl/cert.pem",
    "content": "-----BEGIN CERTIFICATE-----\nMIIDOzCCAiMCCQCVqVeRIp9pFDANBgkqhkiG9w0BAQUFADBnMQswCQYDVQQGEwJV\nUzENMAsGA1UECAwEVXRhaDEOMAwGA1UEBwwFUHJvdm8xIzAhBgNVBAoMGkFDTUUg\nU2lnbmluZyBBdXRob3JpdHkgSW5jMRQwEgYDVQQDDAtleGFtcGxlLmNvbTAeFw0x\nODA4MTQyMDEzNTdaFw0xOTEyMjcyMDEzNTdaMFgxCzAJBgNVBAYTAlVTMQ0wCwYD\nVQQIDARVdGFoMQ4wDAYDVQQHDAVQcm92bzEWMBQGA1UECgwNQUNNRSBUZWNoIElu\nYzESMBAGA1UEAwwJMTI3LjAuMC4xMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB\nCgKCAQEA6x6mTXV+rC35QW/sPutT1O1cugtnw+UsJx7EGgzyjh7EoXE3gb7sO96P\ntOI5zknb0vecckbiVkesmLnAs2iNa1u9EiRr6WHdc+1MfUCxyHRfP731vRZyo0kx\nbSXerE0qZ2N3M1XyndZF7VMthKDKIg0ZR0TvdjwLqyLYEHAnRBhJLRS0Oy0fC6Of\nVWCO3gIuk1HkTXH+/ZMA/obqrtlisxY85mMdlRz+1PNdZBMf+NxmrXN59uq+JqUu\n8/v1oQ8jH2iU9IWeqyawHDEvPW3aDorfaWGyats5Xd3cT2Ph4xF9tBLT+3PDGU8c\noBmTHWDenYn+TCkCseayo1JCO5igJQIDAQABMA0GCSqGSIb3DQEBBQUAA4IBAQCr\nR7eZxicHjJoRcbsPBDQpzx9uSux3uvpN93pyJrXXHiil/5SE7CYeDqv5+nV2p6HA\n6KONUAmpId0iHAEi9u+0/LgPWyYQMzT3sfBhkO8RRaMYI87VuKbk5PFmlZbD843+\nQmg3Se2F7BDnTf88xA6QWR4DCejy+ZHfDRFrh3xfFl4tX1UNgqiTGfjPCzblhWx9\nygzlT+flN2j3NkAlhUEV89pnH4EQWILePMTT4wh2XOQj1VFJ+2ATojHFVUTtNWAJ\nxrY/Q9cMYsZ++I8i9bHMZoyc1bSUd5CNFpQdfjVzlgMPT9Jj/fzWIQz+wq0KeRLI\ndLWsa2MZr0GZnTU39YwH\n-----END CERTIFICATE-----\n"
  },
  {
    "path": "test/fixtures/ssl/privkey.pem",
    "content": "-----BEGIN RSA PRIVATE KEY-----\nMIIEogIBAAKCAQEA6x6mTXV+rC35QW/sPutT1O1cugtnw+UsJx7EGgzyjh7EoXE3\ngb7sO96PtOI5zknb0vecckbiVkesmLnAs2iNa1u9EiRr6WHdc+1MfUCxyHRfP731\nvRZyo0kxbSXerE0qZ2N3M1XyndZF7VMthKDKIg0ZR0TvdjwLqyLYEHAnRBhJLRS0\nOy0fC6OfVWCO3gIuk1HkTXH+/ZMA/obqrtlisxY85mMdlRz+1PNdZBMf+NxmrXN5\n9uq+JqUu8/v1oQ8jH2iU9IWeqyawHDEvPW3aDorfaWGyats5Xd3cT2Ph4xF9tBLT\n+3PDGU8coBmTHWDenYn+TCkCseayo1JCO5igJQIDAQABAoIBAH5fbfFqOpie6T8T\nwj4bTGbA4bsZkD9JeU7ZiXubA/ABd5xyduwky2JugH0vrvRC3IVrE0qU8OiBA7Le\n/EUx5/kRSPFsZBf/wwChRiB4WlYsvllLZ76nRxyepZNN7H5dx3Hkk1gjVREi71jd\nATUtGxfsRG77DV5WbcshIlLLhT9iaohsalmClAFBmwhqnRMvOXHiQyRbvB0fOX08\nuVlObOqo9jLB8N5C/ux+wFEP4wi/AxVqs9ih7Ss7T7+pmOCVWhOnbYcoY2jdaJ11\niLK4F3rv/jQ82OwUpzrWsPedmZUzlOO8xdV3b8hOcPHs/BKvYed7aHSn6b5eVKKT\nzT8vQoECgYEA+K9pvw9K/7+F810MHG+nZ0gtVWmXJp49jB7zQ6QMIex2sUajY2y9\nbEJX8T6rdu3qd+HYU4zl3qt+MUnsVQEBNkLPAn3od0qIWXxu1SL2GF8SDV1xJWK1\nFp0YDe9blaz1JsmSgieNcSoSwqE2V97Wfd/m+EUfyhQt9HX55H5UgAUCgYEA8gkW\n0xZKuHhBMYpcES2P5H5q6HN2fcEQycMuS3agAOhrFPYUT1DVNhbfNVmbOvL2NRWI\nhXixo5SkuEuq2fjmEoeLPTmeKO5LM4IVqovWCYomSftKDpzw4HRn2jvKzi2+mg8J\nqktIMqRqHu/O1NUIsszCIu4c5DzUdhr4N7GXOaECgYAEd1oF1Wd6al0kfsJN7G9s\nOm6d/xR43BSs5I1n5JVXMqD7FBKxIW3ReOuNaJu5uhIg7wxsi7ZBJoFQr0wwRqFX\n8SE4oTxAkDUcrlBrQYJ785Embkwu6LPp4Q5iia7yZDXO6YXZEo7GvoOxvSV1tInT\nnubOBKfKgExG/KttQBuSZQKBgAzYOqPdLP35M8yDQTuQJXDE3LuVVRZ7Zn6uowhS\nNU+XBgfIv28uJQKH2DSmmrxYJITQrbwXmaXKv6sgKOMEeIFHPDZ1llUpwEftgWTZ\novRCpqGKenWoEoh25QQJ5Eto1hKq9aJZ+GznmNIne9yDqcCDaVIdPN9H8yaJa97Y\nx+PBAoGAOiK6xAbPyJSKDSTGZzdv8+yeOdNeJjRHxKJs+4YsDchmdumrqow83DBP\n7ulIJD9pcmsWj+8fntMcsTX5mvzJd5LsKc7Maa5/LtitsLsynu78QFg4Njj8sAKn\n3991i8J98DZ9zqmkxJJhGwstCHG+c+Q7lA6kZ1UdbWJwYwIHjAs=\n-----END RSA PRIVATE KEY-----\n"
  },
  {
    "path": "test/fixtures/test-folder/.hiddenTest.txt",
    "content": "Aha! You found me!\n"
  },
  {
    "path": "test/fixtures/test-folder/add",
    "content": "'use strict'\n\nconst ipfs = require('../src')('localhost', 5001)\n\nconst f1 = 'Hello'\nconst f2 = 'World'\n\nipfs.add([new Buffer(f1), new Buffer(f2)], function (err, res) {\n  if (err || !res) return console.log(err)\n\n  for (let i = 0; i < res.length; i++) {\n    console.log(res[i])\n  }\n})\n\nipfs.add(['./files/hello.txt', './files/ipfs.txt'], function (err, res) {\n  if (err || !res) return console.log(err)\n\n  for (let i = 0; i < res.length; i++) {\n    console.log(res[i])\n  }\n})\n"
  },
  {
    "path": "test/fixtures/test-folder/cat",
    "content": "'use strict'\n\nconst ipfs = require('../src')('localhost', 5001)\n\nconst hash = [\n  'QmdFyxZXsFiP4csgfM5uPu99AvFiKH62CSPDw5TP92nr7w',\n  'QmY9cxiHqTFoWamkQVkpmmqzBrY3hCBEL2XNu3NtX74Fuu'\n]\n\nipfs.cat(hash, function (err, res) {\n  if (err || !res) return console.log(err)\n\n  if (res.readable) {\n    res.pipe(process.stdout)\n  } else {\n    console.log(res)\n  }\n})\n"
  },
  {
    "path": "test/fixtures/test-folder/files/hello.txt",
    "content": "Hello\n"
  },
  {
    "path": "test/fixtures/test-folder/files/ipfs.txt",
    "content": "IPFS\n"
  },
  {
    "path": "test/fixtures/test-folder/ipfs-add",
    "content": "#!/usr/bin/env node\n\n'use strict'\n\nconst ipfs = require('../src')('localhost', 5001)\nconst files = process.argv.slice(2)\n\nipfs.add(files, {recursive: true}, function (err, res) {\n  if (err || !res) return console.log(err)\n\n  for (let i = 0; i < res.length; i++) {\n    console.log('added', res[i].Hash, res[i].Name)\n  }\n})\n"
  },
  {
    "path": "test/fixtures/test-folder/ls",
    "content": "'use strict'\n\nconst ipfs = require('../src')('localhost', 5001)\n\nconst hash = ['QmdbHK6gMiecyjjSoPnfJg6iKMF7v6E2NkoBgGpmyCoevh']\n\nipfs.ls(hash, function (err, res) {\n  if (err || !res) return console.log(err)\n\n  res.Objects.forEach(function (node) {\n    console.log(node.Hash)\n\n    console.log('Links [%d]', node.Links.length)\n    node.Links.forEach(function (link, i) {\n      console.log('[%d]', i, link)\n    })\n  })\n})\n"
  },
  {
    "path": "test/fixtures/test-folder/version",
    "content": "'use strict'\n\nconst ipfs = require('../src')('localhost', 5001)\n\nipfs.commands(function (err, res) {\n  if (err) throw err\n  console.log(res)\n})\n"
  },
  {
    "path": "test/fixtures/testconfig.json",
    "content": "{\n  \"test\": \"beep boop\",\n  \"Addresses\": {\n    \"API\": \"/ip4/127.0.0.1/tcp/5001\",\n    \"Gateway\": \"/ip4/127.0.0.1/tcp/8080\",\n    \"Swarm\": [\n      \"/ip4/0.0.0.0/tcp/4001\"\n    ]\n  },\n  \"Bootstrap\": [\n    \"/ip4/104.131.131.82/tcp/4001/ipfs/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ\",\n    \"/ip4/104.236.176.52/tcp/4001/ipfs/QmSoLnSGccFuZQJzRadHn95W2CrSFmZuTdDWP8HXaHca9z\",\n    \"/ip4/104.236.179.241/tcp/4001/ipfs/QmSoLpPVmHKQ4XTPdz8tjDFgdeRFkpV8JgYq8JVJ69RrZm\",\n    \"/ip4/162.243.248.213/tcp/4001/ipfs/QmSoLueR4xBeUbY9WZ9xGUUxunbKWcrNFTDAadQJmocnWm\",\n    \"/ip4/128.199.219.111/tcp/4001/ipfs/QmSoLSafTMBsPKadTEgaXctDQVcqN88CNLHXMkTNwMKPnu\",\n    \"/ip4/104.236.76.40/tcp/4001/ipfs/QmSoLV4Bbm51jM9C4gDYZQ9Cy3U6aXMJDAbzgu2fzaDs64\",\n    \"/ip4/178.62.158.247/tcp/4001/ipfs/QmSoLer265NRgSp2LA3dPaeykiS1J6DifTC88f5uVQKNAd\",\n    \"/ip4/178.62.61.185/tcp/4001/ipfs/QmSoLMeWqB7YGVLJN3pNLQpmmEk35v6wYtsMGLzSr5QBU3\",\n    \"/ip4/104.236.151.122/tcp/4001/ipfs/QmSoLju6m7xTh3DuokvT3886QRYqxAzb1kShaanJgW36yx\"\n  ],\n  \"Datastore\": {\n    \"Path\": \"/home/krl/.ipfs/datastore\",\n    \"Type\": \"leveldb\"\n  },\n  \"Discovery\": {\n    \"MDNS\": {\n      \"Enabled\": false,\n      \"Interval\": 0\n    }\n  },\n  \"Gateway\": {\n    \"RootRedirect\": \"\",\n    \"Writable\": false\n  },\n  \"Identity\": {\n    \"PeerID\": \"QmTF1MqD5hFgRztwxeosess2S1PpSm6fpy2jt15gZjr39c\",\n    \"PrivKey\": \"CAASqxIwggknAgEAAoICAQC8RXr0/XtKFAn5ReHm0AoUQYpMxckyISsdKkDiGTXQW6h3IuU7kypoeSUNPerp+/+dJCXe5dY+GnT9jRXbZBUfVWYuEnMbCCnGHhi28wD71TYgfLuJlZjRKy1eBIz57bOtAVY8CnLM4WPLQLhcwgSZ1G83D6sRTKNOOqZMf37V/I1dxDg2kqi0JujBodlIP0WjDyBJvtPfLUSoytYznIOmJfi/K5ofPm54y5zX81lwuRGAdCXDIwCwcIwFY2EC6gWVECDLTTBnr7ZXITNtTBOWx6tIEmTF8K/hQN3KzazVEkYn7p4r0QL4zJnQCBIr09HhvOuNTK9XdqBeQJsVVm2uM+//acgdlYS8V+F8FQQHCihsaKAEYeDSGuKuzEbLohc8donWy+3k5jn/SwY8jJLaXtBJpux1sGdRG+ko5mFdXViII5e8gbiSdC1JiDKdeYmUSAm27IvuGay4FplK8wczZrComdsS3sxpSvTrS6KulNv7WTZEKPAWtMFGX+58krOpDgOkKg8IvwucmXsrYD5Q+razorP3v4QAVhouhxQNKzVpmOYZemOeJrTf5smUBjTGLIp343N36kWqZVp+bqTjl8x5uRbgn/wthDWHsyV81M6OwCCPtiKLJMKkztlArFnnT5sZ3aG7sFj4AgnxcqHHDo4nUAI+t4tOb9WxcAMR2wIDAQABAoICAG7OxetjNSkIWkZoJujeENCTMn60+hGTC/kCYWWxSMb061YTJ6/EkfUjN/dvNc+5DVzDZbamt02d7LU+UFrrsLLcZGNBYJXMXCnKlOk4ZJ/TgSPlxcrYTTTuoKjxLLf8ev+cBdEYpTCIh1+dG+UcG/Ed4scZZams3YCxbCch8tim590EG8Gi18AQFnXAeE3ZT3cE9A/zTGfSENL3btK5j5I+TwTU+MTizcoyrIE9LKr3gaGEuqT6+PDfjMmvD+3TJq3w7Bw7tf2QoVTuqYHugKkBo4Grsbv+SMXek6tFGi/drYTbICTRw1oDsZOK7Ib3CFRACLMFKz3jB8fxZlVMpQgawiyeBPx0Z4xf6+OG0yUGxGUKBcuATzON29NJWplZxPtfClCozdsm/3VCCPe7ruDUoDEWobhvKh3Ax+8Cdvt9ajoon6qNK3QgJqrm8Xc50MtjaPhZASGw1YweOfxAeQRHVYAJHrkBwblNzOnCMT8F4uKpeI4C9rUjKTOJu53qV1shwIM+zUGtmRvJUTKA15twqnntQrkhO990Dtl3tON/yx/D2ilLYCVuEPqfmW5/xiOrabgS1OlXLZ7teat85JOyqgZ1R/uxFzQljRwVsnCG6DlobkGHbnKwHq4zyV5UXZUDTM1QAgw6ksmkDWOQ9iYJrTk7UTmnNeAb0g4G2tJhAoIBAQDyT8qoPmZkONFktdnUUnjAeuNZ55b2u7pBq+1b2N4ZzhZQjCRCJwK3zxDYpoxWmH9etJcvv1RvZRaWngr9vECMzUEJmklZlCpW2fdxhvprABHaywklFt2heOo8krmfvbZIVMQ6Q9xWRz5sfiV+k3C8q2Y6RIMLuGquYzk8o2pAPG5aD7gHxIeq4JRGCXyJyovgX2AOZmtZe9ttc+dhxKm71V8bI0e88JrusKeapUnVJUm8qgP6PBg+F8MZh1U3kjHczKeB1ND3X9oFQtLP9ypsi4Ngqgvw0O3+CGY/nvJ6c6ynryiVcmURdQY66f+57CtPjjdUVsSoR/bce5S2lrHNAoIBAQDG6C5iHVuX9OplWcA70U7Tc4eiac803QRUL+zdDOC74Qw2Coxr5Nsxjz8/i+6DnOCeWkJBh/uGEaxdYYZHU90LVf/NSA3zguGt6Z0g3MMvMNT9KGgoZl2T5Y/CCgCfrt6gTGRy7PmF+uLtgHcsKQLqCzMarOSVyue35ztxuI6NeRPvlNkoJ54F/+jnY1/6MrMTPXpybHXwf40piyLPuyapqBgyWkRBwPORR9Ucdiz7KhBnZhj7NYpwvut/KgufuU3WF9bkknfFlOJzVp8ZgefxHE8lHPuR0PnWyHwv3v5hgALYwenREcM5MUbRZ7tc18FkWBVOPlvszqSGujq3nMpHAoIBAGV2R9OfHVzF9dgH1Yh0aB+g1WYl9S6neNxa027sJkQD6ZAcvmn8z8SLrfAp/QWdoWfUkqHpqb9jQswarVuF4jmTELKmqiQaSIhJiLU+4cjAJLnK3q9rHa6pZNusTJG47ITpCamkFLUD6/2d7LFNp5043/tyCLV1qSYQYj0j6C+xnjuT7WlDP9OrairRehZwe5WeGiitdjHoDP+N0ss7gB8ov0Qrx7Qzw4xC6Et2/q2DiZa4UiYL19LYPFeKNYKpcruT7mgM5ttOhYpCaueuBVOiL4bgbVOPCLigZ8AoHDxuB1PHomTBm9RtfghZRz1gyNntIPntwzb7u0Cjdqfl/dkCggEAauDxo3jg8ZsBpCoA2GOUtpw6gnPWijJElDQYU4MK8wlvNU6fu44ClfPB6ZR4OjI+o/gd5/Z4mca/VoID1Cnk+aVhSV3xWSq3t2pzKuhU3POhTtK6fRLcL49Hmt0jDqq5J2tFAlgBkBOKglHoN0tmLHqOIERMo4yezDusvmOL/crUgoT51tDK4bBr5oGIXfmGLc14ESnkibEQGgWQVAzdLoaLUesdCDP07NirU5rQerlUjSrYO4u+cuyzv+XIzy+T+nle1/037Gwe7hjabqtWBUHP6UJUjzq6NMYPrO1mxN8zKGOyDsw7mWy3/+d8TtwEJ7YI5L0vSeSTlW1WBblzGwKCAQBeL4WoC0rH7B+MBw/+q3NMozlq4pE1vAC/7L06GhTPQi3Sklz/HHfw1g2aeYYIYpZ3S0Q+QHBs+fpspuPIBE0xTZPNJIAPTOW3WxODCya1rl521Syy8t57m9UPyVG3scSbWrJxH99BQVSPZzVMI3WO2XWGYupUIkVo+MW4WKhBkHd6a8inuJmjExDWm+bwaoQgUxNwE3c1C5OFwkAU1ofhNijE02IJX0EOaYjvNELT0Na3B0T7KZ72Ut4u33byPgEHa9SsPEurctbHy2HdpOGHdpxx4r+7ZQUtg1UZ0ZRQN8B8TyozD05AXQ9V8ybdzU1jSpQYWqbfkXl+LllJBa4E\"\n  },\n  \"Log\": {\n    \"MaxAgeDays\": 0,\n    \"MaxBackups\": 1,\n    \"MaxSizeMB\": 250\n  },\n  \"Mounts\": {\n    \"FuseAllowOther\": false,\n    \"IPFS\": \"/ipfs\",\n    \"IPNS\": \"/ipns\"\n  },\n  \"SupernodeRouting\": {\n    \"Servers\": [\n      \"/ip4/104.236.176.52/tcp/4002/ipfs/QmXdb7tWTxdFEQEFgWBqkuYSrZd3mXrC7HxkD4krGNYx2U\",\n      \"/ip4/104.236.179.241/tcp/4002/ipfs/QmVRqViDByUxjUMoPnjurjKvZhaEMFDtK35FJXHAM4Lkj6\",\n      \"/ip4/104.236.151.122/tcp/4002/ipfs/QmSZwGx8Tn8tmcM4PtDJaMeUQNRhNFdBLVGPzRiNaRJtFH\",\n      \"/ip4/162.243.248.213/tcp/4002/ipfs/QmbHVEEepCi7rn7VL7Exxpd2Ci9NNB6ifvqwhsrbRMgQFP\",\n      \"/ip4/128.199.219.111/tcp/4002/ipfs/Qmb3brdCYmKG1ycwqCbo6LUwWxTuo3FisnJV2yir7oN92R\",\n      \"/ip4/104.236.76.40/tcp/4002/ipfs/QmdRBCV8Cz2dGhoKLkD3YjPwVFECmqADQkx5ZteF2c6Fy4\",\n      \"/ip4/178.62.158.247/tcp/4002/ipfs/QmUdiMPci7YoEUBkyFZAh2pAbjqcPr7LezyiPD2artLw3v\",\n      \"/ip4/178.62.61.185/tcp/4002/ipfs/QmVw6fGNqBixZE4bewRLT2VXX7fAHUHs8JyidDiJ1P7RUN\"\n    ]\n  },\n  \"Tour\": {\n    \"Last\": \"\"\n  },\n  \"Version\": {\n    \"AutoUpdate\": \"minor\",\n    \"Check\": \"error\",\n    \"CheckDate\": \"0001-01-01T00:00:00Z\",\n    \"CheckPeriod\": \"172800000000000\",\n    \"Current\": \"0.3.0\"\n  }\n}\n"
  },
  {
    "path": "test/fixtures/testfile.txt",
    "content": "Plz add me!\n"
  },
  {
    "path": "test/get.spec.js",
    "content": "/* eslint-env mocha */\n/* eslint max-nested-callbacks: [\"error\", 8] */\n\n'use strict'\n\nconst { expect } = require('interface-ipfs-core/src/utils/mocha')\nconst loadFixture = require('aegir/fixtures')\nconst all = require('it-all')\nconst concat = require('it-concat')\n\nconst f = require('./utils/factory')()\n\ndescribe('.get (specific go-ipfs features)', function () {\n  this.timeout(60 * 1000)\n\n  function fixture (path) {\n    return loadFixture(path, 'interface-ipfs-core')\n  }\n\n  const smallFile = {\n    cid: 'Qma4hjFTnCasJ8PVp3mZbZK5g2vGDT4LByLJ7m8ciyRFZP',\n    data: fixture('test/fixtures/testfile.txt')\n  }\n\n  let ipfs\n\n  before(async () => {\n    ipfs = (await f.spawn()).api\n    await all(ipfs.add(smallFile.data))\n  })\n\n  after(() => f.clean())\n\n  it('no compression args', async () => {\n    const files = await all(ipfs.get(smallFile.cid))\n\n    expect(files).to.be.length(1)\n    const content = await concat(files[0].content)\n    expect(content.toString()).to.contain(smallFile.data.toString())\n  })\n\n  it('archive true', async () => {\n    const files = await all(ipfs.get(smallFile.cid, { archive: true }))\n\n    expect(files).to.be.length(1)\n    const content = await concat(files[0].content)\n    expect(content.toString()).to.contain(smallFile.data.toString())\n  })\n\n  it('err with out of range compression level', async () => {\n    await expect(all(ipfs.get(smallFile.cid, {\n      compress: true,\n      compressionLevel: 10\n    }))).to.be.rejectedWith('compression level must be between 1 and 9')\n  })\n\n  // TODO Understand why this test started failing\n  it.skip('with compression level', async () => {\n    await all(ipfs.get(smallFile.cid, { compress: true, 'compression-level': 1 }))\n  })\n\n  it('add path containing \"+\"s (for testing get)', async () => {\n    const filename = 'ti,c64x+mega++mod-pic.txt'\n    const subdir = 'tmp/c++files'\n    const expectedCid = 'QmPkmARcqjo5fqK1V1o8cFsuaXxWYsnwCNLJUYS4KeZyff'\n    const path = `${subdir}/${filename}`\n    const files = await all(ipfs.add([{\n      path,\n      content: Buffer.from(path)\n    }]))\n\n    expect(files[2].cid.toString()).to.equal(expectedCid)\n  })\n\n  it('get path containing \"+\"s', async () => {\n    const cid = 'QmPkmARcqjo5fqK1V1o8cFsuaXxWYsnwCNLJUYS4KeZyff'\n    const files = await all(ipfs.get(cid))\n\n    expect(files).to.be.an('array').with.lengthOf(3)\n    expect(files[0]).to.have.property('path', cid)\n    expect(files[1]).to.have.property('path', `${cid}/c++files`)\n    expect(files[2]).to.have.property('path', `${cid}/c++files/ti,c64x+mega++mod-pic.txt`)\n  })\n})\n"
  },
  {
    "path": "test/interface.spec.js",
    "content": "/* eslint-env mocha */\n'use strict'\n\nconst tests = require('interface-ipfs-core')\nconst factory = require('./utils/factory')\nconst isWindows = process.platform && process.platform === 'win32'\n\n/** @typedef {import(\"ipfsd-ctl\").ControllerOptions} ControllerOptions */\n\ndescribe('interface-ipfs-core tests', () => {\n  const commonFactory = factory()\n\n  tests.root(commonFactory, {\n    skip: [\n      {\n        name: 'should add with mode as string',\n        reason: 'TODO not implemented in go-ipfs yet'\n      },\n      {\n        name: 'should add with mode as number',\n        reason: 'TODO not implemented in go-ipfs yet'\n      },\n      {\n        name: 'should add with mtime as Date',\n        reason: 'TODO not implemented in go-ipfs yet'\n      },\n      {\n        name: 'should add with mtime as { nsecs, secs }',\n        reason: 'TODO not implemented in go-ipfs yet'\n      },\n      {\n        name: 'should add with mtime as timespec',\n        reason: 'TODO not implemented in go-ipfs yet'\n      },\n      {\n        name: 'should add with mtime as hrtime',\n        reason: 'TODO not implemented in go-ipfs yet'\n      },\n      {\n        name: 'should export a chunk of a file',\n        reason: 'TODO not implemented in go-ipfs yet'\n      },\n      {\n        name: 'should ls with metadata',\n        reason: 'TODO not implemented in go-ipfs yet'\n      }\n    ]\n  })\n\n  tests.bitswap(commonFactory)\n\n  tests.block(commonFactory, {\n    skip: [{\n      name: 'should get a block added as CIDv1 with a CIDv0',\n      reason: 'go-ipfs does not support the `version` param'\n    }]\n  })\n\n  tests.bootstrap(commonFactory, {\n    skip: [{\n      name: 'should return a list containing the bootstrap peer when called with a valid arg (ip4)',\n      reason: 'TODO unskip when go-ipfs switches to p2p for libp2p keys'\n    }, {\n      name: 'should prevent duplicate inserts of bootstrap peers',\n      reason: 'TODO unskip when go-ipfs switches to p2p for libp2p keys'\n    }, {\n      name: 'should return a list containing the peer removed when called with a valid arg (ip4)',\n      reason: 'TODO unskip when go-ipfs switches to p2p for libp2p keys'\n    }]\n  })\n\n  tests.config(commonFactory, {\n    skip: [\n      // config.replace\n      {\n        name: 'replace',\n        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'\n      },\n      {\n        name: 'should list config profiles',\n        reason: 'TODO: Not implemented in go-ipfs'\n      },\n      {\n        name: 'should strip private key from diff output',\n        reason: 'TODO: Not implemented in go-ipfs'\n      }\n    ]\n  })\n\n  tests.dag(commonFactory, {\n    skip: [\n      // dag.tree\n      {\n        name: 'tree',\n        reason: 'TODO vmx 2018-02-22: Currently the tree API is not exposed in go-ipfs'\n      },\n      // dag.get:\n      {\n        name: 'should get a dag-pb node local value',\n        reason: 'FIXME vmx 2018-02-22: Currently not supported in go-ipfs, it might be possible once https://github.com/ipfs/go-ipfs/issues/4728 is done'\n      },\n      {\n        name: 'should get dag-pb value via dag-cbor node',\n        reason: 'FIXME vmx 2018-02-22: Currently not supported in go-ipfs, it might be possible once https://github.com/ipfs/go-ipfs/issues/4728 is done'\n      },\n      {\n        name: 'should get by CID string + path',\n        reason: 'FIXME vmx 2018-02-22: Currently not supported in go-ipfs, it might be possible once https://github.com/ipfs/go-ipfs/issues/4728 is done'\n      },\n      {\n        name: 'should get only a CID, due to resolving locally only',\n        reason: 'FIXME: go-ipfs does not support localResolve option'\n      }\n    ]\n  })\n\n  tests.dht(commonFactory)\n\n  tests.files(commonFactory, {\n    skip: [\n      {\n        name: 'should ls directory',\n        reason: 'TODO unskip when go-ipfs supports --long https://github.com/ipfs/go-ipfs/pull/6528'\n      },\n      {\n        name: 'should list a file directly',\n        reason: 'TODO unskip when go-ipfs supports --long https://github.com/ipfs/go-ipfs/pull/6528'\n      },\n      {\n        name: 'should ls directory and include metadata',\n        reason: 'TODO not implemented in go-ipfs yet'\n      },\n      {\n        name: 'should read from outside of mfs',\n        reason: 'TODO not implemented in go-ipfs yet'\n      },\n      {\n        name: 'should ls from outside of mfs',\n        reason: 'TODO not implemented in go-ipfs yet'\n      },\n      {\n        name: 'should change file mode',\n        reason: 'TODO not implemented in go-ipfs yet'\n      },\n      {\n        name: 'should change directory mode',\n        reason: 'TODO not implemented in go-ipfs yet'\n      },\n      {\n        name: 'should change file mode as string',\n        reason: 'TODO not implemented in go-ipfs yet'\n      },\n      {\n        name: 'should change file mode to 0',\n        reason: 'TODO not implemented in go-ipfs yet'\n      },\n      {\n        name: 'should update file mtime',\n        reason: 'TODO not implemented in go-ipfs yet'\n      },\n      {\n        name: 'should update directory mtime',\n        reason: 'TODO not implemented in go-ipfs yet'\n      },\n      {\n        name: 'should make directory and specify mode',\n        reason: 'TODO not implemented in go-ipfs yet'\n      },\n      {\n        name: 'should make directory and specify mtime',\n        reason: 'TODO not implemented in go-ipfs yet'\n      },\n      {\n        name: 'should write file and specify mode',\n        reason: 'TODO not implemented in go-ipfs yet'\n      },\n      {\n        name: 'should write file and specify mtime',\n        reason: 'TODO not implemented in go-ipfs yet'\n      },\n      {\n        name: 'should respect metadata when copying files',\n        reason: 'TODO not implemented in go-ipfs yet'\n      },\n      {\n        name: 'should respect metadata when copying directories',\n        reason: 'TODO not implemented in go-ipfs yet'\n      },\n      {\n        name: 'should respect metadata when copying from outside of mfs',\n        reason: 'TODO not implemented in go-ipfs yet'\n      },\n      {\n        name: 'should have default mtime',\n        reason: 'TODO not implemented in go-ipfs yet'\n      },\n      {\n        name: 'should set mtime as Date',\n        reason: 'TODO not implemented in go-ipfs yet'\n      },\n      {\n        name: 'should set mtime as { nsecs, secs }',\n        reason: 'TODO not implemented in go-ipfs yet'\n      },\n      {\n        name: 'should set mtime as timespec',\n        reason: 'TODO not implemented in go-ipfs yet'\n      },\n      {\n        name: 'should set mtime as hrtime',\n        reason: 'TODO not implemented in go-ipfs yet'\n      },\n      {\n        name: 'should make directory and have default mode',\n        reason: 'TODO not implemented in go-ipfs yet'\n      },\n      {\n        name: 'should make directory and specify mode as string',\n        reason: 'TODO not implemented in go-ipfs yet'\n      },\n      {\n        name: 'should make directory and specify mode as number',\n        reason: 'TODO not implemented in go-ipfs yet'\n      },\n      {\n        name: 'should make directory and specify mtime as Date',\n        reason: 'TODO not implemented in go-ipfs yet'\n      },\n      {\n        name: 'should make directory and specify mtime as { nsecs, secs }',\n        reason: 'TODO not implemented in go-ipfs yet'\n      },\n      {\n        name: 'should make directory and specify mtime as timespec',\n        reason: 'TODO not implemented in go-ipfs yet'\n      },\n      {\n        name: 'should make directory and specify mtime as hrtime',\n        reason: 'TODO not implemented in go-ipfs yet'\n      },\n      {\n        name: 'should write file and specify mode as a string',\n        reason: 'TODO not implemented in go-ipfs yet'\n      },\n      {\n        name: 'should write file and specify mode as a number',\n        reason: 'TODO not implemented in go-ipfs yet'\n      },\n      {\n        name: 'should write file and specify mtime as Date',\n        reason: 'TODO not implemented in go-ipfs yet'\n      },\n      {\n        name: 'should write file and specify mtime as { nsecs, secs }',\n        reason: 'TODO not implemented in go-ipfs yet'\n      },\n      {\n        name: 'should write file and specify mtime as timespec',\n        reason: 'TODO not implemented in go-ipfs yet'\n      },\n      {\n        name: 'should write file and specify mtime as hrtime',\n        reason: 'TODO not implemented in go-ipfs yet'\n      },\n      {\n        name: 'should stat file with mode',\n        reason: 'TODO not implemented in go-ipfs yet'\n      },\n      {\n        name: 'should stat file with mtime',\n        reason: 'TODO not implemented in go-ipfs yet'\n      },\n      {\n        name: 'should stat dir with mode',\n        reason: 'TODO not implemented in go-ipfs yet'\n      },\n      {\n        name: 'should stat dir with mtime',\n        reason: 'TODO not implemented in go-ipfs yet'\n      },\n      {\n        name: 'should stat sharded dir with mode',\n        reason: 'TODO not implemented in go-ipfs yet'\n      },\n      {\n        name: 'should stat sharded dir with mtime',\n        reason: 'TODO not implemented in go-ipfs yet'\n      }\n    ]\n  })\n\n  tests.key(commonFactory, {\n    skip: [\n      // key.export\n      {\n        name: 'export',\n        reason: 'TODO not implemented in go-ipfs yet'\n      },\n      // key.import\n      {\n        name: 'import',\n        reason: 'TODO not implemented in go-ipfs yet'\n      }\n    ]\n  })\n\n  tests.miscellaneous(commonFactory)\n\n  tests.name(factory(\n    {\n      ipfsOptions: {\n        offline: true\n      }\n    }\n  ), {\n    skip: [\n      {\n        name: 'should resolve a record from peerid as cidv1 in base32',\n        reason: 'TODO not implemented in go-ipfs yet: https://github.com/ipfs/go-ipfs/issues/5287'\n      }\n    ]\n  })\n\n  tests.namePubsub(factory(\n    {\n      ipfsOptions: {\n        EXPERIMENTAL: {\n          ipnsPubsub: true\n        }\n      }\n    }\n  ), {\n    skip: [\n      // name.pubsub.cancel\n      {\n        name: 'should cancel a subscription correctly returning true',\n        reason: 'go-ipfs is really slow for publishing and resolving ipns records, unless in offline mode'\n      },\n      // name.pubsub.subs\n      {\n        name: 'should get the list of subscriptions updated after a resolve',\n        reason: 'go-ipfs is really slow for publishing and resolving ipns records, unless in offline mode'\n      }\n    ]\n  })\n\n  tests.object(commonFactory)\n\n  tests.pin(commonFactory)\n\n  tests.ping(commonFactory, {\n    skip: [\n      {\n        name: 'should fail when pinging a peer that is not available',\n        reason: 'FIXME go-ipfs return success with text: Looking up peer <cid>'\n      }\n    ]\n  })\n\n  tests.pubsub(factory({}, {\n    go: {\n      args: ['--enable-pubsub-experiment']\n    }\n  }), {\n    skip: isWindows ? [\n      // pubsub.subscribe\n      {\n        name: 'should send/receive 100 messages',\n        reason: 'FIXME https://github.com/ipfs/interface-ipfs-core/pull/188#issuecomment-354673246 and https://github.com/ipfs/go-ipfs/issues/4778'\n      },\n      {\n        name: 'should receive multiple messages',\n        reason: 'FIXME https://github.com/ipfs/interface-ipfs-core/pull/188#issuecomment-354673246 and https://github.com/ipfs/go-ipfs/issues/4778'\n      }\n    ] : null\n  })\n\n  tests.repo(commonFactory)\n\n  tests.stats(commonFactory)\n\n  tests.swarm(commonFactory)\n})\n"
  },
  {
    "path": "test/key.spec.js",
    "content": "/* eslint-env mocha */\n'use strict'\n\nconst { expect } = require('interface-ipfs-core/src/utils/mocha')\nconst f = require('./utils/factory')()\n\ndescribe('.key', function () {\n  this.timeout(50 * 1000)\n\n  let ipfs\n\n  before(async () => {\n    ipfs = (await f.spawn()).api\n  })\n\n  after(() => f.clean())\n\n  describe('.gen', () => {\n    it('create a new rsa key', async () => {\n      const res = await ipfs.key.gen('foobarsa', { type: 'rsa', size: 2048 })\n\n      expect(res).to.exist()\n    })\n\n    it('create a new ed25519 key', async () => {\n      const res = await ipfs.key.gen('bazed', { type: 'ed25519' })\n\n      expect(res).to.exist()\n    })\n  })\n\n  describe('.list', () => {\n    it('both keys show up + self', async () => {\n      const res = await ipfs.key.list()\n\n      expect(res).to.exist()\n      expect(res.length).to.equal(3)\n    })\n  })\n})\n"
  },
  {
    "path": "test/lib.configure.spec.js",
    "content": "/* eslint-env mocha, browser */\n'use strict'\n\nconst { expect } = require('interface-ipfs-core/src/utils/mocha')\nconst Multiaddr = require('multiaddr')\nconst { isBrowser, isWebWorker } = require('ipfs-utils/src/env')\nconst configure = require('../src/lib/configure')\n\ndescribe('lib/configure', () => {\n  it('should accept no config', () => {\n    configure(config => {\n      if (isBrowser || isWebWorker) {\n        expect(config.apiAddr).to.eql(location.origin)\n      } else {\n        expect(config.apiAddr).to.eql('http://localhost:5001')\n      }\n    })()\n  })\n\n  it('should accept string multiaddr', () => {\n    const input = '/ip4/127.0.0.1/tcp/5001'\n    configure(config => {\n      expect(config.apiAddr).to.eql('http://127.0.0.1:5001')\n    })(input)\n  })\n\n  it('should accept string url', () => {\n    const input = 'http://127.0.0.1:5001'\n    configure(config => {\n      expect(config.apiAddr).to.eql('http://127.0.0.1:5001')\n    })(input)\n  })\n\n  it('should accept multiaddr instance', () => {\n    const input = Multiaddr('/ip4/127.0.0.1/tcp/5001')\n    configure(config => {\n      expect(config.apiAddr).to.eql('http://127.0.0.1:5001')\n    })(input)\n  })\n\n  it('should accept object with protocol, host and port', () => {\n    const input = { protocol: 'https', host: 'ipfs.io', port: 138 }\n    configure(config => {\n      expect(config.apiAddr).to.eql('https://ipfs.io:138')\n    })(input)\n  })\n\n  it('should accept object with protocol only', () => {\n    const input = { protocol: 'https' }\n    configure(config => {\n      if (isBrowser || isWebWorker) {\n        expect(config.apiAddr).to.eql(`https://${location.host}`)\n      } else {\n        expect(config.apiAddr).to.eql('https://localhost:5001')\n      }\n    })(input)\n  })\n\n  it('should accept object with host only', () => {\n    const input = { host: 'ipfs.io' }\n    configure(config => {\n      if (isBrowser || isWebWorker) {\n        expect(config.apiAddr).to.eql(`http://ipfs.io:${location.port}`)\n      } else {\n        expect(config.apiAddr).to.eql('http://ipfs.io:5001')\n      }\n    })(input)\n  })\n\n  it('should accept object with port only', () => {\n    const input = { port: 138 }\n    configure(config => {\n      if (isBrowser || isWebWorker) {\n        expect(config.apiAddr).to.eql(`http://${location.hostname}:138`)\n      } else {\n        expect(config.apiAddr).to.eql('http://localhost:138')\n      }\n    })(input)\n  })\n})\n"
  },
  {
    "path": "test/lib.error-handler.spec.js",
    "content": "/* eslint-env mocha */\n'use strict'\n\nconst { expect } = require('interface-ipfs-core/src/utils/mocha')\nconst { HTTPError } = require('ky-universal')\nconst throwsAsync = require('./utils/throws-async')\nconst errorHandler = require('../src/lib/error-handler')\n\ndescribe('lib/error-handler', () => {\n  it('should parse json error response', async () => {\n    const res = {\n      ok: false,\n      headers: { get: () => 'application/json' },\n      json: () => Promise.resolve({\n        Message: 'boom',\n        Code: 0,\n        Type: 'error'\n      }),\n      status: 500\n    }\n\n    const err = await throwsAsync(errorHandler(null, null, res))\n\n    expect(err instanceof HTTPError).to.be.true()\n    expect(err.message).to.eql('boom')\n    expect(err.response.status).to.eql(500)\n  })\n\n  it('should gracefully fail on parse json', async () => {\n    const res = {\n      ok: false,\n      headers: { get: () => 'application/json' },\n      json: () => 'boom', // not valid json!\n      status: 500\n    }\n\n    const err = await throwsAsync(errorHandler(null, null, res))\n    expect(err instanceof HTTPError).to.be.true()\n  })\n\n  it('should gracefully fail on read text', async () => {\n    const res = {\n      ok: false,\n      headers: { get: () => 'text/plain' },\n      text: () => Promise.reject(new Error('boom')),\n      status: 500\n    }\n\n    const err = await throwsAsync(errorHandler(null, null, res))\n    expect(err instanceof HTTPError).to.be.true()\n  })\n})\n"
  },
  {
    "path": "test/log.spec.js",
    "content": "/* eslint-env mocha */\n/* eslint max-nested-callbacks: [\"error\", 8] */\n'use strict'\n\nconst { expect } = require('interface-ipfs-core/src/utils/mocha')\nconst all = require('it-all')\nconst f = require('./utils/factory')()\n\ndescribe('.log', function () {\n  this.timeout(100 * 1000)\n\n  let ipfs\n\n  before(async () => {\n    ipfs = (await f.spawn()).api\n  })\n\n  after(() => f.clean())\n\n  it('.log.tail', async () => {\n    const i = setInterval(async () => {\n      try {\n        await all(ipfs.add(Buffer.from('just adding some data to generate logs')))\n      } catch (_) {\n        // this can error if the test has finished and we're shutting down the node\n      }\n    }, 1000)\n\n    for await (const message of ipfs.log.tail()) {\n      clearInterval(i)\n      expect(message).to.be.an('object')\n      break\n    }\n  })\n\n  it('.log.ls', async () => {\n    const res = await ipfs.log.ls()\n\n    expect(res).to.exist()\n    expect(res).to.be.an('array')\n  })\n\n  it('.log.level', async () => {\n    const res = await ipfs.log.level('all', 'error')\n\n    expect(res).to.exist()\n    expect(res).to.be.an('object')\n    expect(res).to.not.have.property('error')\n    expect(res).to.have.property('message')\n  })\n})\n"
  },
  {
    "path": "test/node/swarm.js",
    "content": "/* eslint-env mocha */\n'use strict'\n\nconst { expect } = require('interface-ipfs-core/src/utils/mocha')\nconst nock = require('nock')\nconst ipfsClient = require('../../src')\n\ndescribe('.swarm.peers', function () {\n  this.timeout(50 * 1000) // slow CI\n\n  const ipfs = ipfsClient('/ip4/127.0.0.1/tcp/5001')\n  const apiUrl = 'http://127.0.0.1:5001'\n\n  it('handles a peer response', async () => {\n    const response = { Peers: [{ Addr: '/ip4/104.131.131.82/tcp/4001', Peer: 'QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ', Latency: '', Muxer: '', Streams: null }] }\n\n    const scope = nock(apiUrl)\n      .post('/api/v0/swarm/peers')\n      .query(true)\n      .reply(200, response)\n\n    const res = await ipfs.swarm.peers()\n\n    expect(res).to.be.a('array')\n    expect(res.length).to.equal(1)\n    expect(res[0].error).to.not.exist()\n    expect(res[0].addr.toString()).to.equal(response.Peers[0].Addr)\n    expect(res[0].peer.toString()).to.equal(response.Peers[0].Peer)\n    expect(scope.isDone()).to.equal(true)\n  })\n\n  it('handles an ip6 quic peer', async () => {\n    const response = { Peers: [{ Addr: '/ip6/2001:8a0:7ac5:4201:3ac9:86ff:fe31:7095/udp/4001/quic', Peer: 'QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC', Latency: '', Muxer: '', Streams: null }] }\n\n    const scope = nock(apiUrl)\n      .post('/api/v0/swarm/peers')\n      .query(true)\n      .reply(200, response)\n\n    const res = await ipfs.swarm.peers()\n\n    expect(res).to.be.a('array')\n    expect(res.length).to.equal(1)\n    expect(res[0].error).to.not.exist()\n    expect(res[0].addr.toString()).to.equal(response.Peers[0].Addr)\n    expect(res[0].peer.toString()).to.equal(response.Peers[0].Peer)\n    expect(scope.isDone()).to.equal(true)\n  })\n\n  it('handles unvalidatable peer addr', async () => {\n    const response = { Peers: [{ Addr: '/ip4/104.131.131.82/future-tech', Peer: 'QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC', Latency: '', Muxer: '', Streams: null }] }\n\n    const scope = nock(apiUrl)\n      .post('/api/v0/swarm/peers')\n      .query(true)\n      .reply(200, response)\n\n    const res = await ipfs.swarm.peers()\n\n    expect(res).to.be.a('array')\n    expect(res.length).to.equal(1)\n    expect(res[0].error).to.exist()\n    expect(res[0].rawPeerInfo).to.deep.equal(response.Peers[0])\n    expect(scope.isDone()).to.equal(true)\n  })\n\n  it('handles an error response', async () => {\n    const scope = nock(apiUrl)\n      .post('/api/v0/swarm/peers')\n      .query(true)\n      .replyWithError('something awful happened')\n\n    await expect(ipfs.swarm.peers()).to.be.rejectedWith('something awful happened')\n\n    expect(scope.isDone()).to.equal(true)\n  })\n})\n"
  },
  {
    "path": "test/node.js",
    "content": "'use strict'\nrequire('./node/swarm')\n"
  },
  {
    "path": "test/ping.spec.js",
    "content": "/* eslint-env mocha */\n'use strict'\n\nconst { expect } = require('interface-ipfs-core/src/utils/mocha')\nconst all = require('it-all')\n\nconst f = require('./utils/factory')()\n\n// Determine if a ping response object is a pong, or something else, like a status message\nfunction isPong (pingResponse) {\n  return Boolean(pingResponse && pingResponse.success && !pingResponse.text)\n}\n\ndescribe('.ping', function () {\n  this.timeout(20 * 1000)\n\n  let ipfs\n  let other\n  let otherId\n\n  before(async function () {\n    this.timeout(30 * 1000) // slow CI\n\n    ipfs = (await f.spawn()).api\n    other = (await f.spawn()).api\n\n    const ma = (await ipfs.id()).addresses[0]\n    await other.swarm.connect(ma)\n\n    otherId = (await other.id()).id\n  })\n\n  after(() => f.clean())\n\n  it('.ping with default count', async () => {\n    const res = await all(ipfs.ping(otherId))\n    expect(res).to.be.an('array')\n    expect(res.filter(isPong)).to.have.lengthOf(10)\n    res.forEach(packet => {\n      expect(packet).to.have.keys('success', 'time', 'text')\n      expect(packet.time).to.be.a('number')\n    })\n    const resultMsg = res.find(packet => packet.text.includes('Average latency'))\n    expect(resultMsg).to.exist()\n  })\n\n  it('.ping with count = 2', async () => {\n    const res = await all(ipfs.ping(otherId, { count: 2 }))\n    expect(res).to.be.an('array')\n    expect(res.filter(isPong)).to.have.lengthOf(2)\n    res.forEach(packet => {\n      expect(packet).to.have.keys('success', 'time', 'text')\n      expect(packet.time).to.be.a('number')\n    })\n    const resultMsg = res.find(packet => packet.text.includes('Average latency'))\n    expect(resultMsg).to.exist()\n  })\n})\n"
  },
  {
    "path": "test/repo.spec.js",
    "content": "/* eslint-env mocha */\n'use strict'\n\nconst { expect } = require('interface-ipfs-core/src/utils/mocha')\nconst f = require('./utils/factory')()\n\ndescribe('.repo', function () {\n  this.timeout(50 * 1000) // slow CI\n\n  let ipfs\n\n  before(async () => {\n    ipfs = (await f.spawn()).api\n  })\n\n  after(() => f.clean())\n\n  it('.repo.gc', async () => {\n    const res = await ipfs.repo.gc()\n\n    expect(res).to.exist()\n  })\n\n  it('.repo.stat', async () => {\n    const res = await ipfs.repo.stat()\n\n    expect(res).to.exist()\n    expect(res).to.have.a.property('numObjects')\n    expect(res).to.have.a.property('repoSize')\n  })\n\n  it('.repo.version', async () => {\n    const res = await ipfs.repo.version()\n\n    expect(res).to.exist()\n  })\n})\n"
  },
  {
    "path": "test/request-api.spec.js",
    "content": "/* eslint-env mocha */\n'use strict'\n\nconst { expect } = require('interface-ipfs-core/src/utils/mocha')\nconst { isNode } = require('ipfs-utils/src/env')\nconst ipfsClient = require('../src/index.js')\n\ndescribe('\\'deal with HTTP weirdness\\' tests', () => {\n  it('does not crash if no content-type header is provided', async function () {\n    if (!isNode) return this.skip()\n\n    // go-ipfs always (currently) adds a content-type header, even if no content is present,\n    // the standard behaviour for an http-api is to omit this header if no content is present\n    const server = require('http').createServer((req, res) => {\n      // Consume the entire request, before responding.\n      req.on('data', () => {})\n      req.on('end', () => {\n        res.writeHead(200)\n        res.end()\n      })\n    })\n\n    await new Promise(resolve => server.listen(6001, resolve))\n    await ipfsClient('/ip4/127.0.0.1/tcp/6001').config.replace('test/fixtures/r-config.json')\n\n    server.close()\n  })\n})\n\ndescribe('trailer headers', () => {\n  // TODO: needs fixing https://github.com/ipfs/js-ipfs-http-client/pull/624#issuecomment-344181950\n  it.skip('should deal with trailer x-stream-error correctly', (done) => {\n    if (!isNode) { return done() }\n\n    const server = require('http').createServer((req, res) => {\n      res.setHeader('x-chunked-output', '1')\n      res.setHeader('content-type', 'application/json')\n      res.setHeader('Trailer', 'X-Stream-Error')\n      res.addTrailers({ 'X-Stream-Error': JSON.stringify({ Message: 'ups, something went wrong', Code: 500 }) })\n      res.write(JSON.stringify({ Bytes: 1 }))\n      res.end()\n    })\n\n    server.listen(6001, () => {\n      const ipfs = ipfsClient('/ip4/127.0.0.1/tcp/6001')\n      /* eslint-disable */\n      ipfs.add(Buffer.from('Hello there!'), (err, res) => {\n        // TODO: error's are not being correctly\n        // propagated with Trailer headers yet\n        // expect(err).to.exist()\n        expect(res).to.not.equal(0)\n        server.close(done)\n      })\n      /* eslint-enable */\n    })\n  })\n})\n\ndescribe('error handling', () => {\n  it('should handle plain text error response', async function () {\n    if (!isNode) return this.skip()\n\n    const server = require('http').createServer((req, res) => {\n      // Consume the entire request, before responding.\n      req.on('data', () => {})\n      req.on('end', () => {\n        // Write a text/plain response with a 403 (forbidden) status\n        res.writeHead(403, { 'Content-Type': 'text/plain' })\n        res.write('ipfs method not allowed')\n        res.end()\n      })\n    })\n\n    await new Promise(resolve => server.listen(6001, resolve))\n\n    await expect(ipfsClient('/ip4/127.0.0.1/tcp/6001').config.replace('test/fixtures/r-config.json'))\n      .to.eventually.be.rejectedWith('ipfs method not allowed')\n      .and.to.have.nested.property('response.status').that.equals(403)\n\n    server.close()\n  })\n\n  it('should handle JSON error response', async function () {\n    if (!isNode) return this.skip()\n\n    const server = require('http').createServer((req, res) => {\n      // Consume the entire request, before responding.\n      req.on('data', () => {})\n      req.on('end', () => {\n        // Write a application/json response with a 400 (bad request) header\n        res.writeHead(400, { 'Content-Type': 'application/json' })\n        res.write(JSON.stringify({ Message: 'client error', Code: 1 }))\n        res.end()\n      })\n    })\n\n    await new Promise(resolve => server.listen(6001, resolve))\n\n    await expect(ipfsClient('/ip4/127.0.0.1/tcp/6001').config.replace('test/fixtures/r-config.json'))\n      .to.eventually.be.rejectedWith('client error')\n      .and.to.have.nested.property('response.status').that.equals(400)\n\n    server.close()\n  })\n\n  it('should handle JSON error response with invalid JSON', async function () {\n    if (!isNode) return this.skip()\n\n    const server = require('http').createServer((req, res) => {\n      // Consume the entire request, before responding.\n      req.on('data', () => {})\n      req.on('end', () => {\n        // Write a application/json response with a 400 (bad request) header\n        res.writeHead(400, { 'Content-Type': 'application/json' })\n        res.write('{ Message: ')\n        res.end()\n      })\n    })\n\n    await new Promise(resolve => server.listen(6001, resolve))\n\n    await expect(ipfsClient('/ip4/127.0.0.1/tcp/6001').config.replace('test/fixtures/r-config.json'))\n      .to.eventually.be.rejected()\n      .and.to.have.property('message').that.includes('Unexpected token M in JSON at position 2')\n\n    server.close()\n  })\n})\n"
  },
  {
    "path": "test/stats.spec.js",
    "content": "/* eslint-env mocha */\n'use strict'\n\nconst { expect } = require('interface-ipfs-core/src/utils/mocha')\nconst all = require('it-all')\nconst f = require('./utils/factory')()\n\ndescribe('stats', function () {\n  this.timeout(50 * 1000) // slow CI\n\n  let ipfs\n\n  before(async () => {\n    ipfs = (await f.spawn()).api\n  })\n\n  after(() => f.clean())\n\n  it('.stats.bitswap', async () => {\n    const res = await ipfs.stats.bitswap()\n\n    expect(res).to.exist()\n    expect(res).to.have.a.property('provideBufLen')\n    expect(res).to.have.a.property('wantlist')\n    expect(res).to.have.a.property('peers')\n    expect(res).to.have.a.property('blocksReceived')\n    expect(res).to.have.a.property('dataReceived')\n    expect(res).to.have.a.property('blocksSent')\n    expect(res).to.have.a.property('dataSent')\n    expect(res).to.have.a.property('dupBlksReceived')\n    expect(res).to.have.a.property('dupDataReceived')\n  })\n\n  it('.stats.bw', async () => {\n    const res = (await all(ipfs.stats.bw()))[0]\n\n    expect(res).to.exist()\n    expect(res).to.have.a.property('totalIn')\n    expect(res).to.have.a.property('totalOut')\n    expect(res).to.have.a.property('rateIn')\n    expect(res).to.have.a.property('rateOut')\n  })\n\n  it('.stats.repo', async () => {\n    const res = await ipfs.stats.repo()\n\n    expect(res).to.exist()\n    expect(res).to.have.a.property('numObjects')\n    expect(res).to.have.a.property('repoSize')\n    expect(res).to.have.a.property('repoPath')\n    expect(res).to.have.a.property('version')\n    expect(res).to.have.a.property('storageMax')\n  })\n})\n"
  },
  {
    "path": "test/sub-modules.spec.js",
    "content": "/* eslint-env mocha */\n'use strict'\n\nconst { expect } = require('interface-ipfs-core/src/utils/mocha')\n\ndescribe('submodules', () => {\n  it('bitswap', () => {\n    const bitswap = require('../src/bitswap')()\n\n    expect(bitswap.wantlist).to.be.a('function')\n    expect(bitswap.stat).to.be.a('function')\n    expect(bitswap.unwant).to.be.a('function')\n  })\n\n  it('block', () => {\n    const block = require('../src/block')()\n\n    expect(block.get).to.be.a('function')\n    expect(block.stat).to.be.a('function')\n    expect(block.put).to.be.a('function')\n  })\n\n  it('bootstrap', () => {\n    const bootstrap = require('../src/bootstrap')()\n\n    expect(bootstrap.add).to.be.a('function')\n    expect(bootstrap.rm).to.be.a('function')\n    expect(bootstrap.list).to.be.a('function')\n  })\n\n  it('config', () => {\n    const cfg = require('../src/config')()\n\n    expect(cfg.get).to.be.a('function')\n    expect(cfg.set).to.be.a('function')\n    expect(cfg.replace).to.be.a('function')\n    expect(cfg).to.have.a.property('profiles')\n    expect(cfg.profiles.list).to.be.a('function')\n    expect(cfg.profiles.apply).to.be.a('function')\n  })\n\n  it('dht', () => {\n    const dht = require('../src/dht')()\n\n    expect(dht.get).to.be.a('function')\n    expect(dht.put).to.be.a('function')\n    expect(dht.findProvs).to.be.a('function')\n    expect(dht.findPeer).to.be.a('function')\n    expect(dht.provide).to.be.a('function')\n    expect(dht.query).to.be.a('function')\n  })\n\n  it('id', () => {\n    const id = require('../src/id')()\n\n    expect(id).to.be.a('function')\n  })\n\n  it('version', () => {\n    const version = require('../src/version')()\n\n    expect(version).to.be.a('function')\n  })\n\n  it('ping', () => {\n    const ping = require('../src')().ping\n\n    expect(ping).to.be.a('function')\n  })\n\n  it('log', () => {\n    const log = require('../src/log')()\n\n    expect(log.ls).to.be.a('function')\n    expect(log.tail).to.be.a('function')\n    expect(log.level).to.be.a('function')\n  })\n\n  it('key', () => {\n    const key = require('../src/key')()\n\n    expect(key.gen).to.be.a('function')\n    expect(key.list).to.be.a('function')\n  })\n\n  it('name', () => {\n    const name = require('../src/name')()\n\n    expect(name.publish).to.be.a('function')\n    expect(name.resolve).to.be.a('function')\n  })\n\n  it('pin', () => {\n    const pin = require('../src/pin')()\n\n    expect(pin.add).to.be.a('function')\n    expect(pin.rm).to.be.a('function')\n    expect(pin.ls).to.be.a('function')\n  })\n\n  it('repo', () => {\n    const repo = require('../src/repo')()\n\n    expect(repo.gc).to.be.a('function')\n    expect(repo.stat).to.be.a('function')\n  })\n\n  it('stats', () => {\n    const stats = require('../src/stats')()\n\n    expect(stats.bitswap).to.be.a('function')\n    expect(stats.bw).to.be.a('function')\n    expect(stats.repo).to.be.a('function')\n  })\n\n  it('swarm', () => {\n    const swarm = require('../src/swarm')()\n\n    expect(swarm.peers).to.be.a('function')\n    expect(swarm.connect).to.be.a('function')\n    expect(swarm.disconnect).to.be.a('function')\n    expect(swarm.addrs).to.be.a('function')\n    expect(swarm.localAddrs).to.be.a('function')\n  })\n\n  it('diag', () => {\n    const diag = require('../src/diag')()\n\n    expect(diag.net).to.be.a('function')\n    expect(diag.sys).to.be.a('function')\n    expect(diag.cmds).to.be.a('function')\n  })\n\n  it('object', () => {\n    const object = require('../src/object')()\n\n    expect(object.get).to.be.a('function')\n    expect(object.put).to.be.a('function')\n    expect(object.data).to.be.a('function')\n    expect(object.links).to.be.a('function')\n    expect(object.stat).to.be.a('function')\n    expect(object.new).to.be.a('function')\n    expect(object.patch.rmLink).to.be.a('function')\n    expect(object.patch.addLink).to.be.a('function')\n    expect(object.patch.setData).to.be.a('function')\n    expect(object.patch.appendData).to.be.a('function')\n  })\n\n  it('pubsub', () => {\n    const pubsub = require('../src/pubsub')()\n\n    expect(pubsub.subscribe).to.be.a('function')\n    expect(pubsub.unsubscribe).to.be.a('function')\n    expect(pubsub.publish).to.be.a('function')\n    expect(pubsub.ls).to.be.a('function')\n    expect(pubsub.peers).to.be.a('function')\n  })\n\n  it('files regular API', () => {\n    const filesRegular = require('../src')()\n\n    expect(filesRegular.add).to.be.a('function')\n    expect(filesRegular.get).to.be.a('function')\n    expect(filesRegular.cat).to.be.a('function')\n    expect(filesRegular.ls).to.be.a('function')\n    expect(filesRegular.refs).to.be.a('function')\n    expect(filesRegular.refs.local).to.be.a('function')\n  })\n\n  it('files MFS API', () => {\n    const files = require('../src/files')()\n\n    expect(files.cp).to.be.a('function')\n    expect(files.ls).to.be.a('function')\n    expect(files.mkdir).to.be.a('function')\n    expect(files.stat).to.be.a('function')\n    expect(files.rm).to.be.a('function')\n    expect(files.read).to.be.a('function')\n    expect(files.write).to.be.a('function')\n    expect(files.mv).to.be.a('function')\n  })\n\n  it('commands', () => {\n    const commands = require('../src/commands')()\n\n    expect(commands).to.be.a('function')\n  })\n\n  it('mount', () => {\n    const mount = require('../src/mount')()\n\n    expect(mount).to.be.a('function')\n  })\n})\n"
  },
  {
    "path": "test/utils/factory.js",
    "content": "'use strict'\n\nconst { createFactory } = require('ipfsd-ctl')\nconst merge = require('merge-options')\nconst { isNode } = require('ipfs-utils/src/env')\n\nconst commonOptions = {\n  test: 'true',\n  type: 'go',\n  ipfsHttpModule: require('../../src')\n}\n\nconst commonOverrides = {\n  go: {\n    ipfsBin: isNode ? require('go-ipfs-dep').path() : undefined\n  }\n}\n\nconst factory = (options = {}, overrides = {}) => createFactory(\n  merge(commonOptions, options),\n  merge(commonOverrides, overrides)\n)\n\nmodule.exports = factory\n"
  },
  {
    "path": "test/utils/throws-async.js",
    "content": "'use strict'\n\nmodule.exports = async fnOrPromise => {\n  try {\n    await (fnOrPromise.then ? fnOrPromise : fnOrPromise())\n  } catch (err) {\n    return err\n  }\n  throw new Error('did not throw')\n}\n"
  }
]