diff --git a/README.md b/README.md index 9c6d3a3c7..88ed592f8 100644 --- a/README.md +++ b/README.md @@ -53,6 +53,8 @@ - [Additional Options](#additional-options) - [Instance Utils](#instance-utils) - [Static Types and Utils](#static-types-and-utils) + - [Glob source](#glob-source) + - [URL source](#url-source) - [Development](#development) - [Testing](#testing) - [Contribute](#contribute) @@ -210,34 +212,20 @@ const ipfs = ipfsClient({ timeout: '2m' }) - [Regular Files API](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md) - [`ipfs.add(data, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#add) - - [`ipfs.addPullStream([options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#addpullstream) - - [`ipfs.addReadableStream([options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#addreadablestream) - - [`ipfs.addFromStream(stream)`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#addfromstream) - - [`ipfs.addFromFs(path, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#addfromfs) - - [`ipfs.addFromURL(url, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#addfromurl) - [`ipfs.cat(ipfsPath, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#cat) - - [`ipfs.catPullStream(ipfsPath, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#catpullstream) - - [`ipfs.catReadableStream(ipfsPath, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#catreadablestream) - [`ipfs.get(ipfsPath, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#get) - - [`ipfs.getPullStream(ipfsPath, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#getpullstream) - - [`ipfs.getReadableStream(ipfsPath, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#getreadablestream) - [`ipfs.ls(ipfsPath)`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#ls) - - [`ipfs.lsPullStream(ipfsPath)`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#lspullstream) - - [`ipfs.lsReadableStream(ipfsPath)`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#lsreadablestream) - [MFS (mutable file system) specific](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#mutable-file-system) - - _Explore the Mutable File System through interactive coding challenges in our [ProtoSchool tutorial](https://proto.school/#/mutable-file-system/)._ - [`ipfs.files.cp([from, to])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#filescp) - [`ipfs.files.flush([path])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#filesflush) - [`ipfs.files.ls([path], [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#filesls) - [`ipfs.files.mkdir(path, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#filesmkdir) - [`ipfs.files.mv([from, to])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#filesmv) - [`ipfs.files.read(path, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#filesread) - - [`ipfs.files.readPullStream(path, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#filesreadpullstream) - - [`ipfs.files.readReadableStream(path, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#filesreadreadablestream) - [`ipfs.files.rm(path, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#filesrm) - [`ipfs.files.stat(path, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#filesstat) - [`ipfs.files.write(path, content, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#fileswrite) + _Explore the Mutable File System through interactive coding challenges in our [ProtoSchool tutorial](https://proto.school/#/mutable-file-system/)._ - [block](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/BLOCK.md) - [`ipfs.block.get(cid, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/BLOCK.md#blockget) @@ -246,20 +234,15 @@ const ipfs = ipfsClient({ timeout: '2m' }) - [refs](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/REFS.md) - [`ipfs.refs(ipfsPath, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/REFS.md#refs) - - [`ipfs.refsReadableStream(ipfsPath, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/REFS.md#refsreadablestream) - - [`ipfs.refsPullStream(ipfsPath, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/REFS.md#refspullstream) - [`ipfs.refs.local()`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/REFS.md#refslocal) - - [`ipfs.refs.localReadableStream()`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/REFS.md#refslocalreadablestream) - - [`ipfs.refs.localPullStream()`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/REFS.md#refslocalpullstream) #### Graph - [dag](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/DAG.md) - - _Explore the DAG API through interactive coding challenges in our [ProtoSchool tutorial](https://proto.school/#/basics)._ - [`ipfs.dag.get(cid, [path], [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/DAG.md#dagget) - [`ipfs.dag.put(dagNode, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/DAG.md#dagput) - [`ipfs.dag.tree(cid, [path], [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/DAG.md#dagtree) + _Explore the DAG API through interactive coding challenges in our [ProtoSchool tutorial](https://proto.school/#/basics)._ - [object](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/OBJECT.md) - [`ipfs.object.data(multihash, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/OBJECT.md#objectdata) @@ -278,9 +261,6 @@ const ipfs = ipfsClient({ timeout: '2m' }) - [`ipfs.pin.ls([hash], [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/PIN.md#pinls) - [`ipfs.pin.rm(hash, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/PIN.md#pinrm) -- refs - - `ipfs.refs.local()` - #### Network - [bootstrap](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/BOOTSTRAP.md) @@ -326,8 +306,6 @@ const ipfs = ipfsClient({ timeout: '2m' }) - [`ipfs.dns(domain)`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/MISCELLANEOUS.md#dns) - [`ipfs.id()`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/MISCELLANEOUS.md#id) - [`ipfs.ping(id, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/MISCELLANEOUS.md#ping) - - [`ipfs.pingPullStream(id, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/MISCELLANEOUS.md#pingpullstream) - - [`ipfs.pingReadableStream(id, [options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/MISCELLANEOUS.md#pingreadablestream) - [`ipfs.stop()`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/MISCELLANEOUS.md#stop). Alias to `ipfs.shutdown`. - [`ipfs.version()`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/MISCELLANEOUS.md#version) @@ -341,8 +319,6 @@ const ipfs = ipfsClient({ timeout: '2m' }) - [stats](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/STATS.md) - [`ipfs.stats.bitswap()`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/STATS.md#statsbitswap) - [`ipfs.stats.bw([options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/STATS.md#statsbw) - - [`ipfs.stats.bwPullStream([options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/STATS.md#statsbwpullstream) - - [`ipfs.stats.bwReadableStream([options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/STATS.md#statsbwreadablestream) - [`ipfs.stats.repo([options])`](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/STATS.md#statsrepo) - log @@ -382,15 +358,14 @@ Call this on your client instance to return an object containing the `host`, `po Aside from the default export, `ipfs-http-client` exports various types and utilities that are included in the bundle: -- [`isIPFS`](https://www.npmjs.com/package/is-ipfs) - [`Buffer`](https://www.npmjs.com/package/buffer) -- [`PeerId`](https://www.npmjs.com/package/peer-id) -- [`PeerInfo`](https://www.npmjs.com/package/peer-info) - [`multiaddr`](https://www.npmjs.com/package/multiaddr) - [`multibase`](https://www.npmjs.com/package/multibase) - [`multicodec`](https://www.npmjs.com/package/multicodec) -- [`multihash`](https://www.npmjs.com/package/multihash) +- [`multihash`](https://www.npmjs.com/package/multihashes) - [`CID`](https://www.npmjs.com/package/cids) +- [`globSource`](https://github.com/ipfs/js-ipfs-utils/blob/master/src/files/glob-source.js) (not available in the browser) +- [`urlSource`](https://github.com/ipfs/js-ipfs-utils/blob/master/src/files/url-source.js) These can be accessed like this, for example: @@ -400,6 +375,74 @@ const { CID } = require('ipfs-http-client') import { CID } from 'ipfs-http-client' ``` +##### Glob source + +A utility to allow files on the file system to be easily added to IPFS. + +###### `globSource(path, [options])` + +- `path`: A path to a single file or directory to glob from +- `options`: Optional options +- `options.recursive`: If `path` is a directory, use option `{ recursive: true }` to add the directory and all its sub-directories. +- `options.ignore`: To exclude file globs from the directory, use option `{ ignore: ['ignore/this/folder/**', 'and/this/file'] }`. +- `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 }`. + +Returns an async iterable that yields `{ path, content }` objects suitable for passing to `ipfs.add`. + +###### Example + +```js +const IpfsHttpClient = require('ipfs-http-client') +const { globSource } = IpfsHttpClient +const ipfs = IpfsHttpClient() + +for await (const file of ipfs.add(globSource('./docs', { recursive: true }))) { + console.log(file) +} +/* +{ + path: 'docs/assets/anchor.js', + cid: CID('QmVHxRocoWgUChLEvfEyDuuD6qJ4PhdDL2dTLcpUy3dSC2'), + size: 15347 +} +{ + path: 'docs/assets/bass-addons.css', + cid: CID('QmPiLWKd6yseMWDTgHegb8T7wVS7zWGYgyvfj7dGNt2viQ'), + size: 232 +} +... +*/ +``` + +##### URL source + +A utility to allow content from the internet to be easily added to IPFS. + +###### `urlSource(url)` + +- `url`: A string URL or [`URL`](https://developer.mozilla.org/en-US/docs/Web/API/URL) instance to send HTTP GET request to + +Returns an async iterable that yields `{ path, content }` objects suitable for passing to `ipfs.add`. + +###### Example + +```js +const IpfsHttpClient = require('ipfs-http-client') +const { urlSource } = IpfsHttpClient +const ipfs = IpfsHttpClient() + +for await (const file of ipfs.add(urlSource('https://ipfs.io/images/ipfs-logo.svg'))) { + console.log(file) +} +/* +{ + path: 'ipfs-logo.svg', + cid: CID('QmTqZhR6f7jzdhLgPArDPnsbZpvvgxzCZycXK7ywkLxSyU'), + size: 3243 +} +*/ +``` + ## Development ### Testing diff --git a/package.json b/package.json index 033449aad..add5c2ebb 100644 --- a/package.json +++ b/package.json @@ -15,13 +15,9 @@ ], "main": "src/index.js", "browser": { - "glob": false, - "fs": false, - "stream": "readable-stream", - "ky-universal": "ky/umd", "./src/add/form-data.js": "./src/add/form-data.browser.js", - "./src/add-from-fs/index.js": "./src/add-from-fs/index.browser.js", - "./src/lib/buffer-to-form-data.js": "./src/lib/buffer-to-form-data.browser.js" + "./src/lib/buffer-to-form-data.js": "./src/lib/buffer-to-form-data.browser.js", + "ipfs-utils/src/files/glob-source": false }, "repository": "github:ipfs/js-ipfs-http-client", "scripts": { @@ -42,55 +38,42 @@ }, "dependencies": { "abort-controller": "^3.0.0", - "async-iterator-to-pull-stream": "^1.3.0", "bignumber.js": "^9.0.0", - "bl": "^4.0.0", "bs58": "^4.0.1", "buffer": "^5.4.2", - "callbackify": "^1.1.0", "cids": "~0.7.1", "debug": "^4.1.0", - "err-code": "^2.0.0", - "explain-error": "^1.0.4", "form-data": "^3.0.0", "ipfs-block": "~0.8.1", - "ipfs-utils": "^0.4.2", - "ipld-dag-cbor": "~0.15.0", - "ipld-dag-pb": "^0.18.1", - "ipld-raw": "^4.0.0", - "is-ipfs": "~0.6.1", - "it-all": "^1.0.1", - "it-glob": "0.0.7", + "ipfs-utils": "^0.7.1", + "ipld-dag-cbor": "^0.15.1", + "ipld-dag-pb": "^0.18.2", + "ipld-raw": "^4.0.1", "it-tar": "^1.1.1", "it-to-stream": "^0.1.1", "iterable-ndjson": "^1.1.0", "ky": "^0.15.0", "ky-universal": "^0.3.0", "merge-options": "^2.0.0", - "multiaddr": "^6.0.6", - "multiaddr-to-uri": "^5.0.0", + "multiaddr": "^7.2.1", + "multiaddr-to-uri": "^5.1.0", "multibase": "~0.6.0", "multicodec": "^1.0.0", "multihashes": "~0.4.14", "parse-duration": "^0.1.1", - "peer-id": "~0.12.3", - "peer-info": "~0.15.1", - "promise-nodeify": "^3.0.1" + "stream-to-it": "^0.2.0" }, "devDependencies": { "aegir": "^20.4.1", "async": "^3.1.0", "browser-process-platform": "~0.1.1", - "cross-env": "^6.0.0", - "detect-node": "^2.0.4", "go-ipfs-dep": "^0.4.22", - "interface-ipfs-core": "^0.128.0", - "ipfsd-ctl": "^1.0.0", - "ndjson": "^1.5.0", - "nock": "^11.4.0", - "pull-stream": "^3.6.14", - "pump": "^3.0.0", - "stream-equal": "^1.1.1" + "interface-ipfs-core": "^0.129.0", + "ipfsd-ctl": "^1.0.2", + "it-all": "^1.0.1", + "it-concat": "^1.0.0", + "it-pipe": "^1.1.0", + "nock": "^11.7.2" }, "engines": { "node": ">=10.3.0", diff --git a/src/add-from-fs/index.browser.js b/src/add-from-fs/index.browser.js deleted file mode 100644 index 81d551294..000000000 --- a/src/add-from-fs/index.browser.js +++ /dev/null @@ -1,3 +0,0 @@ -'use strict' - -module.exports = () => () => { throw new Error('unavailable in the browser') } diff --git a/src/add-from-fs/index.js b/src/add-from-fs/index.js deleted file mode 100644 index 7403f7e46..000000000 --- a/src/add-from-fs/index.js +++ /dev/null @@ -1,8 +0,0 @@ -'use strict' - -const globSource = require('ipfs-utils/src/files/glob-source') - -module.exports = (config) => { - const add = require('../add')(config) - return (path, options) => add(globSource(path, options), options) -} diff --git a/src/add-from-url.js b/src/add-from-url.js deleted file mode 100644 index deb3f4bad..000000000 --- a/src/add-from-url.js +++ /dev/null @@ -1,21 +0,0 @@ -'use strict' - -const kyDefault = require('ky-universal').default -const toIterable = require('./lib/stream-to-iterable') - -module.exports = (config) => { - const add = require('./add')(config) - - return async function * addFromURL (url, options) { - options = options || {} - - const { body } = await kyDefault.get(url) - - const input = { - path: decodeURIComponent(new URL(url).pathname.split('/').pop() || ''), - content: toIterable(body) - } - - yield * add(input, options) - } -} diff --git a/src/add/index.js b/src/add/index.js index e8b3c22f0..cd162c2f9 100644 --- a/src/add/index.js +++ b/src/add/index.js @@ -1,8 +1,9 @@ 'use strict' const ndjson = require('iterable-ndjson') +const CID = require('cids') const configure = require('../lib/configure') -const toIterable = require('../lib/stream-to-iterable') +const toIterable = require('stream-to-it/source') const { toFormData } = require('./form-data') const toCamel = require('../lib/object-to-camel') @@ -55,7 +56,7 @@ module.exports = configure(({ ky }) => { function toCoreInterface ({ name, hash, size, mode, mtime, mtimeNsecs }) { const output = { path: name, - hash, + cid: new CID(hash), size: parseInt(size) } diff --git a/src/bitswap/index.js b/src/bitswap/index.js index fb47d4da0..5c8354498 100644 --- a/src/bitswap/index.js +++ b/src/bitswap/index.js @@ -1,9 +1,7 @@ 'use strict' -const callbackify = require('callbackify') - -module.exports = (config) => ({ - wantlist: callbackify.variadic(require('./wantlist')(config)), - stat: callbackify.variadic(require('./stat')(config)), - unwant: callbackify.variadic(require('./unwant')(config)) +module.exports = config => ({ + wantlist: require('./wantlist')(config), + stat: require('./stat')(config), + unwant: require('./unwant')(config) }) diff --git a/src/bitswap/stat.js b/src/bitswap/stat.js index fee13c355..e041f5d9d 100644 --- a/src/bitswap/stat.js +++ b/src/bitswap/stat.js @@ -2,6 +2,7 @@ const configure = require('../lib/configure') const Big = require('bignumber.js') +const CID = require('cids') module.exports = configure(({ ky }) => { return async (options) => { @@ -21,8 +22,8 @@ module.exports = configure(({ ky }) => { function toCoreInterface (res) { return { provideBufLen: res.ProvideBufLen, - wantlist: res.Wantlist || [], - peers: res.Peers || [], + wantlist: (res.Wantlist || []).map(k => new CID(k['/'])), + peers: (res.Peers || []).map(p => new CID(p)), blocksReceived: new Big(res.BlocksReceived), dataReceived: new Big(res.DataReceived), blocksSent: new Big(res.BlocksSent), diff --git a/src/bitswap/wantlist.js b/src/bitswap/wantlist.js index 6b087db1b..d917d6747 100644 --- a/src/bitswap/wantlist.js +++ b/src/bitswap/wantlist.js @@ -24,6 +24,6 @@ module.exports = configure(({ ky }) => { searchParams }).json() - return res + return (res.Keys || []).map(k => new CID(k['/'])) } }) diff --git a/src/block/index.js b/src/block/index.js index 8c683dd83..f25c73366 100644 --- a/src/block/index.js +++ b/src/block/index.js @@ -1,23 +1,8 @@ 'use strict' -const nodeify = require('promise-nodeify') -const callbackify = require('callbackify') -const { collectify } = require('../lib/converters') - -module.exports = config => { - const rm = require('./rm-async-iterator')(config) - - return { - get: callbackify.variadic(require('./get')(config)), - stat: callbackify.variadic(require('./stat')(config)), - put: callbackify.variadic(require('./put')(config)), - rm: (input, options, callback) => { - if (typeof options === 'function') { - callback = options - options = {} - } - return nodeify(collectify(rm)(input, options), callback) - }, - _rmAsyncIterator: rm - } -} +module.exports = config => ({ + get: require('./get')(config), + stat: require('./stat')(config), + put: require('./put')(config), + rm: require('./rm')(config) +}) diff --git a/src/block/rm-async-iterator.js b/src/block/rm.js similarity index 76% rename from src/block/rm-async-iterator.js rename to src/block/rm.js index e44aedcd2..f8fc8c103 100644 --- a/src/block/rm-async-iterator.js +++ b/src/block/rm.js @@ -3,8 +3,7 @@ const CID = require('cids') const ndjson = require('iterable-ndjson') const configure = require('../lib/configure') -const toIterable = require('../lib/stream-to-iterable') -const toCamel = require('../lib/object-to-camel') +const toIterable = require('stream-to-it/source') module.exports = configure(({ ky }) => { return async function * rm (cid, options) { @@ -31,7 +30,19 @@ module.exports = configure(({ ky }) => { }) for await (const removed of ndjson(toIterable(res.body))) { - yield toCamel(removed) + yield toCoreInterface(removed) } } }) + +function toCoreInterface (removed) { + const out = { + cid: new CID(removed.Hash) + } + + if (removed.Error) { + out.error = new Error(removed.Error) + } + + return out +} diff --git a/src/block/stat.js b/src/block/stat.js index 9063d137c..24b4256fc 100644 --- a/src/block/stat.js +++ b/src/block/stat.js @@ -3,7 +3,6 @@ const CID = require('cids') const { Buffer } = require('buffer') const configure = require('../lib/configure') -const toCamel = require('../lib/object-to-camel') module.exports = configure(({ ky }) => { return async (cid, options) => { @@ -23,6 +22,6 @@ module.exports = configure(({ ky }) => { searchParams }).json() - return toCamel(res) + return { cid: new CID(res.Key), size: res.Size } } }) diff --git a/src/bootstrap/index.js b/src/bootstrap/index.js index 032265803..519a7161e 100644 --- a/src/bootstrap/index.js +++ b/src/bootstrap/index.js @@ -1,9 +1,7 @@ 'use strict' -const callbackify = require('callbackify') - module.exports = config => ({ - add: callbackify.variadic(require('./add')(config)), - rm: callbackify.variadic(require('./rm')(config)), - list: callbackify.variadic(require('./list')(config)) + add: require('./add')(config), + rm: require('./rm')(config), + list: require('./list')(config) }) diff --git a/src/cat.js b/src/cat.js index 32bccf59e..3d4971a1c 100644 --- a/src/cat.js +++ b/src/cat.js @@ -3,7 +3,7 @@ const CID = require('cids') const { Buffer } = require('buffer') const configure = require('./lib/configure') -const toIterable = require('./lib/stream-to-iterable') +const toIterable = require('stream-to-it/source') module.exports = configure(({ ky }) => { return async function * cat (path, options) { diff --git a/src/config/index.js b/src/config/index.js index 36621fd39..cb56190a2 100644 --- a/src/config/index.js +++ b/src/config/index.js @@ -1,10 +1,8 @@ 'use strict' -const callbackify = require('callbackify') - module.exports = config => ({ - get: callbackify.variadic(require('./get')(config)), - set: callbackify.variadic(require('./set')(config)), - replace: callbackify.variadic(require('./replace')(config)), + get: require('./get')(config), + set: require('./set')(config), + replace: require('./replace')(config), profiles: require('./profiles')(config) }) diff --git a/src/config/profiles/index.js b/src/config/profiles/index.js index 57cd1ad7f..77b68de41 100644 --- a/src/config/profiles/index.js +++ b/src/config/profiles/index.js @@ -1,8 +1,6 @@ 'use strict' -const callbackify = require('callbackify') - module.exports = config => ({ - apply: callbackify.variadic(require('./apply')(config)), - list: callbackify.variadic(require('./list')(config)) + apply: require('./apply')(config), + list: require('./list')(config) }) diff --git a/src/dag/index.js b/src/dag/index.js index 06194e4a8..3cc4d410e 100644 --- a/src/dag/index.js +++ b/src/dag/index.js @@ -1,9 +1,7 @@ 'use strict' -const callbackify = require('callbackify') - module.exports = config => ({ - get: callbackify.variadic(require('./get')(config)), - put: callbackify.variadic(require('./put')(config)), - resolve: callbackify.variadic(require('./resolve')(config)) + get: require('./get')(config), + put: require('./put')(config), + resolve: require('./resolve')(config) }) diff --git a/src/dht/find-peer.js b/src/dht/find-peer.js index 71779952c..9d8f517e5 100644 --- a/src/dht/find-peer.js +++ b/src/dht/find-peer.js @@ -1,18 +1,18 @@ 'use strict' -const PeerId = require('peer-id') -const PeerInfo = require('peer-info') +const { Buffer } = require('buffer') +const CID = require('cids') const multiaddr = require('multiaddr') const ndjson = require('iterable-ndjson') const configure = require('../lib/configure') -const toIterable = require('../lib/stream-to-iterable') +const toIterable = require('stream-to-it/source') module.exports = configure(({ ky }) => { - return async function * findPeer (peerId, options) { + return async function findPeer (peerId, options) { options = options || {} const searchParams = new URLSearchParams(options.searchParams) - searchParams.set('arg', `${peerId}`) + searchParams.set('arg', `${Buffer.isBuffer(peerId) ? new CID(peerId) : peerId}`) if (options.verbose != null) searchParams.set('verbose', options.verbose) const res = await ky.post('dht/findpeer', { @@ -23,15 +23,27 @@ module.exports = configure(({ ky }) => { }) for await (const message of ndjson(toIterable(res.body))) { + // 3 = QueryError + // https://github.com/libp2p/go-libp2p-core/blob/6e566d10f4a5447317a66d64c7459954b969bdab/routing/query.go#L18 + // https://github.com/ipfs/go-ipfs/blob/eb11f569b064b960d1aba4b5b8ca155a3bd2cb21/core/commands/dht.go#L388-L389 + if (message.Type === 3) { + throw new Error(message.Extra) + } + // 2 = FinalPeer // https://github.com/libp2p/go-libp2p-core/blob/6e566d10f4a5447317a66d64c7459954b969bdab/routing/query.go#L18 if (message.Type === 2 && message.Responses) { + // There will only be 1: + // https://github.com/ipfs/go-ipfs/blob/eb11f569b064b960d1aba4b5b8ca155a3bd2cb21/core/commands/dht.go#L395-L396 for (const { ID, Addrs } of message.Responses) { - const peerInfo = new PeerInfo(PeerId.createFromB58String(ID)) - if (Addrs) Addrs.forEach(a => peerInfo.multiaddrs.add(multiaddr(a))) - yield peerInfo + return { + id: new CID(ID), + addrs: (Addrs || []).map(a => multiaddr(a)) + } } } } + + throw new Error('not found') } }) diff --git a/src/dht/find-provs.js b/src/dht/find-provs.js index a0fc35722..7adbaf38c 100644 --- a/src/dht/find-provs.js +++ b/src/dht/find-provs.js @@ -1,18 +1,17 @@ 'use strict' -const PeerId = require('peer-id') -const PeerInfo = require('peer-info') +const CID = require('cids') const multiaddr = require('multiaddr') const ndjson = require('iterable-ndjson') const configure = require('../lib/configure') -const toIterable = require('../lib/stream-to-iterable') +const toIterable = require('stream-to-it/source') module.exports = configure(({ ky }) => { return async function * findProvs (cid, options) { options = options || {} const searchParams = new URLSearchParams(options.searchParams) - searchParams.set('arg', `${cid}`) + searchParams.set('arg', `${new CID(cid)}`) if (options.numProviders) searchParams.set('num-providers', options.numProviders) if (options.verbose != null) searchParams.set('verbose', options.verbose) @@ -24,13 +23,21 @@ module.exports = configure(({ ky }) => { }) for await (const message of ndjson(toIterable(res.body))) { + // 3 = QueryError + // https://github.com/libp2p/go-libp2p-core/blob/6e566d10f4a5447317a66d64c7459954b969bdab/routing/query.go#L18 + // https://github.com/libp2p/go-libp2p-kad-dht/blob/master/routing.go#L525-L526 + if (message.Type === 3) { + throw new Error(message.Extra) + } + // 4 = Provider // https://github.com/libp2p/go-libp2p-core/blob/6e566d10f4a5447317a66d64c7459954b969bdab/routing/query.go#L20 if (message.Type === 4 && message.Responses) { for (const { ID, Addrs } of message.Responses) { - const peerInfo = new PeerInfo(PeerId.createFromB58String(ID)) - if (Addrs) Addrs.forEach(a => peerInfo.multiaddrs.add(multiaddr(a))) - yield peerInfo + yield { + id: new CID(ID), + addrs: (Addrs || []).map(a => multiaddr(a)) + } } } } diff --git a/src/dht/get.js b/src/dht/get.js index d2cd0db22..4be7b80c2 100644 --- a/src/dht/get.js +++ b/src/dht/get.js @@ -1,30 +1,43 @@ 'use strict' +const { Buffer } = require('buffer') const ndjson = require('iterable-ndjson') +const toIterable = require('stream-to-it/source') +const encodeBufferURIComponent = require('../lib/encode-buffer-uri-component') const configure = require('../lib/configure') -const toIterable = require('../lib/stream-to-iterable') module.exports = configure(({ ky }) => { - return async function * get (key, options) { + return async function get (key, options) { options = options || {} const searchParams = new URLSearchParams(options.searchParams) - searchParams.set('arg', `${key}`) if (options.verbose != null) searchParams.set('verbose', options.verbose) - const res = await ky.post('dht/get', { + if (!Buffer.isBuffer(key)) { + throw new Error('invalid key') + } + + const res = await ky.post(`dht/get?key=${encodeBufferURIComponent(key)}&${searchParams}`, { timeout: options.timeout, signal: options.signal, - headers: options.headers, - searchParams + headers: options.headers }) for await (const message of ndjson(toIterable(res.body))) { + // 3 = QueryError + // https://github.com/libp2p/go-libp2p-core/blob/6e566d10f4a5447317a66d64c7459954b969bdab/routing/query.go#L18 + // https://github.com/ipfs/go-ipfs/blob/eb11f569b064b960d1aba4b5b8ca155a3bd2cb21/core/commands/dht.go#L472-L473 + if (message.Type === 3) { + throw new Error(message.Extra) + } + // 5 = Value // https://github.com/libp2p/go-libp2p-core/blob/6e566d10f4a5447317a66d64c7459954b969bdab/routing/query.go#L21 if (message.Type === 5) { - yield message.Extra + return message.Extra } } + + throw new Error('not found') } }) diff --git a/src/dht/index.js b/src/dht/index.js index 5478876ff..754e57b83 100644 --- a/src/dht/index.js +++ b/src/dht/index.js @@ -1,30 +1,11 @@ 'use strict' -const callbackify = require('callbackify') -const errCode = require('err-code') -const { collectify } = require('../lib/converters') - -module.exports = config => { - const get = require('./get')(config) - const findPeer = require('./find-peer')(config) - - return { - get: callbackify.variadic(async (key, options) => { - for await (const value of get(key, options)) { - return value - } - throw errCode(new Error('value not found'), 'ERR_TYPE_5_NOT_FOUND') - }), - put: callbackify.variadic(collectify(require('./put')(config))), - findProvs: callbackify.variadic(collectify(require('./find-provs')(config))), - findPeer: callbackify.variadic(async (peerId, options) => { - for await (const peerInfo of findPeer(peerId, options)) { - return peerInfo - } - throw errCode(new Error('final peer not found'), 'ERR_TYPE_2_NOT_FOUND') - }), - provide: callbackify.variadic(collectify(require('./provide')(config))), - // find closest peerId to given peerId - query: callbackify.variadic(collectify(require('./query')(config))) - } -} +module.exports = config => ({ + get: require('./get')(config), + put: require('./put')(config), + findProvs: require('./find-provs')(config), + findPeer: require('./find-peer')(config), + provide: require('./provide')(config), + // find closest peerId to given peerId + query: require('./query')(config) +}) diff --git a/src/dht/provide.js b/src/dht/provide.js index cb72f9c6d..f9013bfed 100644 --- a/src/dht/provide.js +++ b/src/dht/provide.js @@ -1,11 +1,10 @@ 'use strict' -const PeerId = require('peer-id') -const PeerInfo = require('peer-info') +const CID = require('cids') const multiaddr = require('multiaddr') const ndjson = require('iterable-ndjson') const configure = require('../lib/configure') -const toIterable = require('../lib/stream-to-iterable') +const toIterable = require('stream-to-it/source') const toCamel = require('../lib/object-to-camel') module.exports = configure(({ ky }) => { @@ -14,7 +13,7 @@ module.exports = configure(({ ky }) => { options = options || {} const searchParams = new URLSearchParams(options.searchParams) - cids.forEach(cid => searchParams.append('arg', `${cid}`)) + cids.forEach(cid => searchParams.append('arg', `${new CID(cid)}`)) if (options.recursive != null) searchParams.set('recursive', options.recursive) if (options.verbose != null) searchParams.set('verbose', options.verbose) @@ -26,13 +25,22 @@ module.exports = configure(({ ky }) => { }) for await (let message of ndjson(toIterable(res.body))) { + // 3 = QueryError + // https://github.com/libp2p/go-libp2p-core/blob/6e566d10f4a5447317a66d64c7459954b969bdab/routing/query.go#L18 + // https://github.com/ipfs/go-ipfs/blob/eb11f569b064b960d1aba4b5b8ca155a3bd2cb21/core/commands/dht.go#L283-L284 + if (message.Type === 3) { + throw new Error(message.Extra) + } + message = toCamel(message) + message.id = new CID(message.id) if (message.responses) { - message.responses = message.responses.map(({ ID, Addrs }) => { - const peerInfo = new PeerInfo(PeerId.createFromB58String(ID)) - if (Addrs) Addrs.forEach(a => peerInfo.multiaddrs.add(multiaddr(a))) - return peerInfo - }) + message.responses = message.responses.map(({ ID, Addrs }) => ({ + id: new CID(ID), + addrs: (Addrs || []).map(a => multiaddr(a)) + })) + } else { + message.responses = [] } yield message } diff --git a/src/dht/put.js b/src/dht/put.js index 49a6947aa..6d0ecf6fc 100644 --- a/src/dht/put.js +++ b/src/dht/put.js @@ -1,11 +1,11 @@ 'use strict' -const PeerId = require('peer-id') -const PeerInfo = require('peer-info') +const { Buffer } = require('buffer') +const CID = require('cids') const multiaddr = require('multiaddr') const ndjson = require('iterable-ndjson') const configure = require('../lib/configure') -const toIterable = require('../lib/stream-to-iterable') +const toIterable = require('stream-to-it/source') const encodeBufferURIComponent = require('../lib/encode-buffer-uri-component') const toCamel = require('../lib/object-to-camel') @@ -27,13 +27,20 @@ module.exports = configure(({ ky }) => { }) for await (let message of ndjson(toIterable(res.body))) { + // 3 = QueryError + // https://github.com/libp2p/go-libp2p-core/blob/6e566d10f4a5447317a66d64c7459954b969bdab/routing/query.go#L18 + // https://github.com/ipfs/go-ipfs/blob/eb11f569b064b960d1aba4b5b8ca155a3bd2cb21/core/commands/dht.go#L472-L473 + if (message.Type === 3) { + throw new Error(message.Extra) + } + message = toCamel(message) + message.id = new CID(message.id) if (message.responses) { - message.responses = message.responses.map(({ ID, Addrs }) => { - const peerInfo = new PeerInfo(PeerId.createFromB58String(ID)) - if (Addrs) Addrs.forEach(a => peerInfo.multiaddrs.add(multiaddr(a))) - return peerInfo - }) + message.responses = message.responses.map(({ ID, Addrs }) => ({ + id: new CID(ID), + addrs: (Addrs || []).map(a => multiaddr(a)) + })) } yield message } diff --git a/src/dht/query.js b/src/dht/query.js index 5aefaf90d..1628c0cc8 100644 --- a/src/dht/query.js +++ b/src/dht/query.js @@ -1,17 +1,18 @@ 'use strict' -const PeerId = require('peer-id') -const PeerInfo = require('peer-info') +const CID = require('cids') const ndjson = require('iterable-ndjson') +const multiaddr = require('multiaddr') +const toIterable = require('stream-to-it/source') const configure = require('../lib/configure') -const toIterable = require('../lib/stream-to-iterable') +const toCamel = require('../lib/object-to-camel') module.exports = configure(({ ky }) => { return async function * query (peerId, options) { options = options || {} const searchParams = new URLSearchParams(options.searchParams) - searchParams.set('arg', `${peerId}`) + searchParams.set('arg', `${Buffer.isBuffer(peerId) ? new CID(peerId) : peerId}`) if (options.verbose != null) searchParams.set('verbose', options.verbose) const res = await ky.post('dht/query', { @@ -21,8 +22,14 @@ module.exports = configure(({ ky }) => { searchParams }) - for await (const message of ndjson(toIterable(res.body))) { - yield new PeerInfo(PeerId.createFromB58String(message.ID)) + for await (let message of ndjson(toIterable(res.body))) { + message = toCamel(message) + message.id = new CID(message.id) + message.responses = (message.responses || []).map(({ ID, Addrs }) => ({ + id: new CID(ID), + addrs: (Addrs || []).map(a => multiaddr(a)) + })) + yield message } } }) diff --git a/src/diag/index.js b/src/diag/index.js index 7e48d576d..d3ac85d55 100644 --- a/src/diag/index.js +++ b/src/diag/index.js @@ -1,9 +1,7 @@ 'use strict' -const callbackify = require('callbackify') - module.exports = config => ({ - net: callbackify.variadic(require('./net')(config)), - sys: callbackify.variadic(require('./sys')(config)), - cmds: callbackify.variadic(require('./cmds')(config)) + net: require('./net')(config), + sys: require('./sys')(config), + cmds: require('./cmds')(config) }) diff --git a/src/files/index.js b/src/files/index.js index ee6b7d8d8..5dbf395a2 100644 --- a/src/files/index.js +++ b/src/files/index.js @@ -1,27 +1,15 @@ 'use strict' -const callbackify = require('callbackify') -const { collectify, streamify, pullify, concatify } = require('../lib/converters') - -module.exports = config => { - const ls = require('./ls')(config) - const read = require('./read')(config) - - return { - chmod: callbackify.variadic(require('./chmod')(config)), - cp: callbackify.variadic(require('./cp')(config)), - mkdir: callbackify.variadic(require('./mkdir')(config)), - flush: callbackify.variadic(require('./flush')(config)), - stat: callbackify.variadic(require('./stat')(config)), - rm: callbackify.variadic(require('./rm')(config)), - ls: callbackify.variadic(collectify(ls)), - lsReadableStream: streamify.readable(ls), - lsPullStream: pullify.source(ls), - read: callbackify.variadic(concatify(read)), - readReadableStream: streamify.readable(read), - readPullStream: pullify.source(read), - touch: callbackify.variadic(require('./touch')(config)), - write: callbackify.variadic(require('./write')(config)), - mv: callbackify.variadic(require('./mv')(config)) - } -} +module.exports = config => ({ + chmod: require('./chmod')(config), + cp: require('./cp')(config), + mkdir: require('./mkdir')(config), + flush: require('./flush')(config), + stat: require('./stat')(config), + rm: require('./rm')(config), + ls: require('./ls')(config), + read: require('./read')(config), + touch: require('./touch')(config), + write: require('./write')(config), + mv: require('./mv')(config) +}) diff --git a/src/files/ls.js b/src/files/ls.js index 51ee33912..f07c65c09 100644 --- a/src/files/ls.js +++ b/src/files/ls.js @@ -2,7 +2,7 @@ const CID = require('cids') const ndjson = require('iterable-ndjson') -const toIterable = require('../lib/stream-to-iterable') +const toIterable = require('stream-to-it/source') const configure = require('../lib/configure') const toCamelWithMetadata = require('../lib/object-to-camel-with-metadata') @@ -17,9 +17,11 @@ module.exports = configure(({ ky }) => { const searchParams = new URLSearchParams(options.searchParams) searchParams.set('arg', CID.isCID(path) ? `/ipfs/${path}` : path) - searchParams.set('stream', true) + searchParams.set('stream', options.stream == null ? true : options.stream) if (options.cidBase) searchParams.set('cid-base', options.cidBase) - if (options.long != null) searchParams.set('long', options.long) + searchParams.set('long', options.long == null ? true : options.long) + // TODO: remove after go-ipfs 0.5 is released + searchParams.set('l', options.long == null ? true : options.long) const res = await ky.post('files/ls', { timeout: options.timeout, @@ -32,12 +34,17 @@ module.exports = configure(({ ky }) => { // go-ipfs does not yet support the "stream" option if ('Entries' in result) { for (const entry of result.Entries || []) { - yield toCamelWithMetadata(entry) + yield toCoreInterface(toCamelWithMetadata(entry)) } - return + } else { + yield toCoreInterface(toCamelWithMetadata(result)) } - - yield toCamelWithMetadata(result) } } }) + +function toCoreInterface (entry) { + if (entry.hash) entry.cid = new CID(entry.hash) + delete entry.hash + return entry +} diff --git a/src/files/read.js b/src/files/read.js index 5a6a14acb..1800609d0 100644 --- a/src/files/read.js +++ b/src/files/read.js @@ -2,7 +2,7 @@ const { Buffer } = require('buffer') const configure = require('../lib/configure') -const toIterable = require('../lib/stream-to-iterable') +const toIterable = require('stream-to-it/source') module.exports = configure(({ ky }) => { return async function * read (path, options) { diff --git a/src/files/stat.js b/src/files/stat.js index 1b4af061b..0d8c9caa1 100644 --- a/src/files/stat.js +++ b/src/files/stat.js @@ -1,5 +1,6 @@ 'use strict' +const CID = require('cids') const configure = require('../lib/configure') const toCamelWithMetadata = require('../lib/object-to-camel-with-metadata') @@ -27,7 +28,12 @@ module.exports = configure(({ ky }) => { }).json() res.WithLocality = res.WithLocality || false - - return toCamelWithMetadata(res) + return toCoreInterface(toCamelWithMetadata(res)) } }) + +function toCoreInterface (entry) { + entry.cid = new CID(entry.hash) + delete entry.hash + return entry +} diff --git a/src/get.js b/src/get.js index 1a5ebfd93..635f8b34f 100644 --- a/src/get.js +++ b/src/get.js @@ -4,7 +4,7 @@ const configure = require('./lib/configure') const Tar = require('it-tar') const { Buffer } = require('buffer') const CID = require('cids') -const toIterable = require('./lib/stream-to-iterable') +const toIterable = require('stream-to-it/source') module.exports = configure(({ ky }) => { return async function * get (path, options) { diff --git a/src/index.js b/src/index.js index 939f5986f..320a5a9a8 100644 --- a/src/index.js +++ b/src/index.js @@ -1,159 +1,51 @@ 'use strict' -const isIPFS = require('is-ipfs') const { Buffer } = require('buffer') const CID = require('cids') const multiaddr = require('multiaddr') const multibase = require('multibase') const multicodec = require('multicodec') const multihash = require('multihashes') -const PeerId = require('peer-id') -const PeerInfo = require('peer-info') -const nodeify = require('promise-nodeify') -const callbackify = require('callbackify') -const all = require('it-all') -const toPullStream = require('async-iterator-to-pull-stream') -const toStream = require('it-to-stream') -const BufferList = require('bl/BufferList') -const { concatify, collectify, pullify, streamify } = require('./lib/converters') +const globSource = require('ipfs-utils/src/files/glob-source') +const urlSource = require('ipfs-utils/src/files/url-source') function ipfsClient (config) { - const add = require('./add')(config) - const addFromFs = require('./add-from-fs')(config) - const addFromURL = require('./add-from-url')(config) - const cat = require('./cat')(config) - const get = require('./get')(config) - const ls = require('./ls')(config) - const ping = require('./ping')(config) - const refs = require('./refs')(config) - - const api = { - add: (input, options, callback) => { - if (typeof options === 'function') { - callback = options - options = {} - } - return nodeify(collectify(add)(input, options), callback) - }, - addReadableStream: streamify.transform(add), - addPullStream: pullify.transform(add), - addFromFs: (path, options, callback) => { - if (typeof options === 'function') { - callback = options - options = {} - } - return nodeify(collectify(addFromFs)(path, options), callback) - }, - addFromURL: (url, options, callback) => { - if (typeof options === 'function') { - callback = options - options = {} - } - return nodeify(collectify(addFromURL)(url, options), callback) - }, - addFromStream: (input, options, callback) => { - if (typeof options === 'function') { - callback = options - options = {} - } - return nodeify(collectify(add)(input, options), callback) - }, - _addAsyncIterator: add, + return { + add: require('./add')(config), bitswap: require('./bitswap')(config), block: require('./block')(config), bootstrap: require('./bootstrap')(config), - cat: callbackify.variadic((path, options) => concatify(cat)(path, options)), - catReadableStream: streamify.readable(cat), - catPullStream: pullify.source(cat), - _catAsyncIterator: cat, - commands: callbackify.variadic(require('./commands')(config)), + cat: require('./cat')(config), + commands: require('./commands')(config), config: require('./config')(config), dag: require('./dag')(config), dht: require('./dht')(config), diag: require('./diag')(config), - dns: callbackify.variadic(require('./dns')(config)), + dns: require('./dns')(config), files: require('./files')(config), - get: callbackify.variadic(async (path, options) => { - const output = [] - - for await (const entry of get(path, options)) { - if (entry.content) { - entry.content = new BufferList(await all(entry.content)).slice() - } - - output.push(entry) - } - - return output - }), + get: require('./get')(config), getEndpointConfig: require('./get-endpoint-config')(config), - getReadableStream: streamify.readable(async function * (path, options) { - for await (const file of get(path, options)) { - if (file.content) { - const { content } = file - file.content = toStream((async function * () { - for await (const chunk of content) { - yield chunk.slice() // Convert bl to Buffer - } - })()) - } - - yield file - } - }), - getPullStream: pullify.source(async function * (path, options) { - for await (const file of get(path, options)) { - if (file.content) { - const { content } = file - file.content = toPullStream((async function * () { - for await (const chunk of content) { - yield chunk.slice() // Convert bl to Buffer - } - })()) - } - - yield file - } - }), - _getAsyncIterator: get, - id: callbackify.variadic(require('./id')(config)), + id: require('./id')(config), key: require('./key')(config), log: require('./log')(config), - ls: callbackify.variadic((path, options) => collectify(ls)(path, options)), - lsReadableStream: streamify.readable(ls), - lsPullStream: pullify.source(ls), - _lsAsyncIterator: ls, - mount: callbackify.variadic(require('./mount')(config)), + ls: require('./ls')(config), + mount: require('./mount')(config), name: require('./name')(config), object: require('./object')(config), pin: require('./pin')(config), - ping: callbackify.variadic(collectify(ping)), - pingReadableStream: streamify.readable(ping), - pingPullStream: pullify.source(ping), + ping: require('./ping')(config), pubsub: require('./pubsub')(config), - refs: callbackify.variadic((path, options) => collectify(refs)(path, options)), - refsReadableStream: streamify.readable(refs), - refsPullStream: pullify.source(refs), - _refsAsyncIterator: refs, + refs: require('./refs')(config), repo: require('./repo')(config), - resolve: callbackify.variadic(require('./resolve')(config)), + resolve: require('./resolve')(config), stats: require('./stats')(config), - stop: callbackify.variadic(require('./stop')(config)), - shutdown: callbackify.variadic(require('./stop')(config)), + stop: require('./stop')(config), + shutdown: require('./stop')(config), swarm: require('./swarm')(config), - version: callbackify.variadic(require('./version')(config)) + version: require('./version')(config) } - - Object.assign(api.refs, { - local: callbackify.variadic(options => collectify(refs.local)(options)), - localReadableStream: streamify.readable(refs.local), - localPullStream: pullify.source(refs.local), - _localAsyncIterator: refs.local - }) - - return api } -Object.assign(ipfsClient, { isIPFS, Buffer, CID, multiaddr, multibase, multicodec, multihash, PeerId, PeerInfo }) +Object.assign(ipfsClient, { Buffer, CID, multiaddr, multibase, multicodec, multihash, globSource, urlSource }) module.exports = ipfsClient diff --git a/src/key/index.js b/src/key/index.js index 7293236f1..de12c732c 100644 --- a/src/key/index.js +++ b/src/key/index.js @@ -1,12 +1,10 @@ 'use strict' -const callbackify = require('callbackify') - module.exports = config => ({ - gen: callbackify.variadic(require('./gen')(config)), - list: callbackify.variadic(require('./list')(config)), - rename: callbackify.variadic(require('./rename')(config)), - rm: callbackify.variadic(require('./rm')(config)), - export: callbackify.variadic(require('./export')(config)), - import: callbackify.variadic(require('./import')(config)) + gen: require('./gen')(config), + list: require('./list')(config), + rename: require('./rename')(config), + rm: require('./rm')(config), + export: require('./export')(config), + import: require('./import')(config) }) diff --git a/src/lib/converters.js b/src/lib/converters.js deleted file mode 100644 index 4f42b3175..000000000 --- a/src/lib/converters.js +++ /dev/null @@ -1,20 +0,0 @@ -'use strict' - -const toPull = require('async-iterator-to-pull-stream') -const all = require('it-all') -const toStream = require('it-to-stream') -const { Buffer } = require('buffer') - -exports.collectify = fn => (...args) => all(fn(...args)) - -exports.concatify = fn => async (...args) => Buffer.concat(await all(fn(...args))) - -exports.pullify = { - source: fn => (...args) => toPull(fn(...args)), - transform: fn => (...args) => toPull.transform(source => fn(source, ...args)) -} - -exports.streamify = { - readable: fn => (...args) => toStream(fn(...args), { objectMode: true }), - transform: fn => (...args) => toStream.transform(source => fn(source, ...args), { objectMode: true }) -} diff --git a/src/lib/stream-to-iterable.js b/src/lib/stream-to-iterable.js deleted file mode 100644 index 5e06a99c6..000000000 --- a/src/lib/stream-to-iterable.js +++ /dev/null @@ -1,25 +0,0 @@ -'use strict' - -module.exports = function toIterable (body) { - // Node.js stream - if (body[Symbol.asyncIterator]) return body - - // Browser ReadableStream - if (body.getReader) { - return (async function * () { - const reader = body.getReader() - - try { - while (true) { - const { done, value } = await reader.read() - if (done) return - yield value - } - } finally { - reader.releaseLock() - } - })() - } - - throw new Error('unknown stream') -} diff --git a/src/log/index.js b/src/log/index.js index f7d94f910..3eea39fd5 100644 --- a/src/log/index.js +++ b/src/log/index.js @@ -1,9 +1,7 @@ 'use strict' -const callbackify = require('callbackify') - module.exports = config => ({ tail: require('./tail')(config), - ls: callbackify.variadic(require('./ls')(config)), - level: callbackify.variadic(require('./level')(config)) + ls: require('./ls')(config), + level: require('./level')(config) }) diff --git a/src/log/tail.js b/src/log/tail.js index 00708e9b9..74b72b2c2 100644 --- a/src/log/tail.js +++ b/src/log/tail.js @@ -2,7 +2,7 @@ const ndjson = require('iterable-ndjson') const configure = require('../lib/configure') -const toIterable = require('../lib/stream-to-iterable') +const toIterable = require('stream-to-it/source') module.exports = configure(({ ky }) => { return async function * tail (options) { diff --git a/src/ls.js b/src/ls.js index 43e92a54a..ec7e37dfb 100644 --- a/src/ls.js +++ b/src/ls.js @@ -2,6 +2,8 @@ const { Buffer } = require('buffer') const CID = require('cids') +const ndjson = require('iterable-ndjson') +const toIterable = require('stream-to-it/source') const configure = require('./lib/configure') module.exports = configure(({ ky }) => { @@ -10,18 +12,11 @@ module.exports = configure(({ ky }) => { const searchParams = new URLSearchParams() searchParams.set('arg', `${Buffer.isBuffer(path) ? new CID(path) : path}`) + searchParams.set('stream', options.stream == null ? true : options.stream) - if (options.long !== undefined) { - searchParams.set('long', options.long) - } - - if (options.unsorted !== undefined) { - searchParams.set('unsorted', options.unsorted) - } - - if (options.recursive !== undefined) { - searchParams.set('recursive', options.recursive) - } + if (options.long != null) searchParams.set('long', options.long) + if (options.unsorted != null) searchParams.set('unsorted', options.unsorted) + if (options.recursive != null) searchParams.set('recursive', options.recursive) const res = await ky.post('ls', { timeout: options.timeout, @@ -30,48 +25,49 @@ module.exports = configure(({ ky }) => { searchParams }) - let result = await res.json() - - result = result.Objects - if (!result) { - throw new Error('expected .Objects in results') - } - - result = result[0] - if (!result) { - throw new Error('expected one array in results.Objects') - } + for await (let result of ndjson(toIterable(res.body))) { + result = result.Objects - result = result.Links - if (!Array.isArray(result)) { - throw new Error('expected one array in results.Objects[0].Links') - } + if (!result) { + throw new Error('expected .Objects in results') + } - for (const link of result) { - const entry = { - name: link.Name, - path: path + '/' + link.Name, - size: link.Size, - hash: link.Hash, - type: typeOf(link), - depth: link.Depth || 1 + result = result[0] + if (!result) { + throw new Error('expected one array in results.Objects') } - if (link.Mode) { - entry.mode = parseInt(link.Mode, 8) + result = result.Links + if (!Array.isArray(result)) { + throw new Error('expected one array in results.Objects[0].Links') } - if (link.Mtime !== undefined && link.Mtime !== null) { - entry.mtime = { - secs: link.Mtime + for (const link of result) { + const entry = { + name: link.Name, + path: path + '/' + link.Name, + size: link.Size, + cid: new CID(link.Hash), + type: typeOf(link), + depth: link.Depth || 1 } - if (link.MtimeNsecs !== undefined && link.MtimeNsecs !== null) { - entry.mtime.nsecs = link.MtimeNsecs + if (link.Mode) { + entry.mode = parseInt(link.Mode, 8) } - } - yield entry + if (link.Mtime !== undefined && link.Mtime !== null) { + entry.mtime = { + secs: link.Mtime + } + + if (link.MtimeNsecs !== undefined && link.MtimeNsecs !== null) { + entry.mtime.nsecs = link.MtimeNsecs + } + } + + yield entry + } } } }) diff --git a/src/name/index.js b/src/name/index.js index 7a6837b82..65d1acca2 100644 --- a/src/name/index.js +++ b/src/name/index.js @@ -1,9 +1,7 @@ 'use strict' -const callbackify = require('callbackify') - module.exports = config => ({ - publish: callbackify.variadic(require('./publish')(config)), - resolve: callbackify.variadic(require('./resolve')(config)), + publish: require('./publish')(config), + resolve: require('./resolve')(config), pubsub: require('./pubsub')(config) }) diff --git a/src/name/pubsub/index.js b/src/name/pubsub/index.js index 70db19874..14ffd8852 100644 --- a/src/name/pubsub/index.js +++ b/src/name/pubsub/index.js @@ -1,9 +1,7 @@ 'use strict' -const callbackify = require('callbackify') - module.exports = config => ({ - cancel: callbackify.variadic(require('./cancel')(config)), - state: callbackify.variadic(require('./state')(config)), - subs: callbackify.variadic(require('./subs')(config)) + cancel: require('./cancel')(config), + state: require('./state')(config), + subs: require('./subs')(config) }) diff --git a/src/name/resolve.js b/src/name/resolve.js index b6e8db47e..e7eb20b4f 100644 --- a/src/name/resolve.js +++ b/src/name/resolve.js @@ -1,13 +1,16 @@ 'use strict' +const ndjson = require('iterable-ndjson') const configure = require('../lib/configure') +const toIterable = require('stream-to-it/source') module.exports = configure(({ ky }) => { - return async (path, options) => { + return async function * (path, options) { options = options || {} const searchParams = new URLSearchParams(options.searchParams) searchParams.set('arg', path) + searchParams.set('stream', options.stream == null ? true : options.stream) if (options.dhtRecordCount != null) searchParams.set('dht-record-count', options.dhtRecordCount) if (options.dhtTimeout != null) searchParams.set('dht-timeout', options.dhtTimeout) if (options.noCache != null) searchParams.set('nocache', options.noCache) @@ -18,8 +21,10 @@ module.exports = configure(({ ky }) => { signal: options.signal, headers: options.headers, searchParams - }).json() + }) - return res.Path + for await (const result of ndjson(toIterable(res.body))) { + yield result.Path + } } }) diff --git a/src/object/data.js b/src/object/data.js index 48291f722..5f40e0450 100644 --- a/src/object/data.js +++ b/src/object/data.js @@ -3,24 +3,21 @@ const { Buffer } = require('buffer') const CID = require('cids') const configure = require('../lib/configure') -const toIterable = require('../lib/stream-to-iterable') module.exports = configure(({ ky }) => { - return async function * data (cid, options) { + return async function data (cid, options) { options = options || {} const searchParams = new URLSearchParams(options.searchParams) searchParams.set('arg', `${Buffer.isBuffer(cid) ? new CID(cid) : cid}`) - const res = await ky.post('object/data', { + const data = await ky.post('object/data', { timeout: options.timeout, signal: options.signal, headers: options.headers, searchParams - }) + }).arrayBuffer() - for await (const chunk of toIterable(res.body)) { - yield Buffer.from(chunk) - } + return Buffer.from(data) } }) diff --git a/src/object/index.js b/src/object/index.js index dac85598c..ee7c85dd6 100644 --- a/src/object/index.js +++ b/src/object/index.js @@ -1,14 +1,11 @@ 'use strict' -const callbackify = require('callbackify') -const { concatify } = require('../lib/converters') - module.exports = config => ({ - data: callbackify.variadic(concatify(require('./data')(config))), - get: callbackify.variadic(require('./get')(config)), - links: callbackify.variadic(require('./links')(config)), - new: callbackify.variadic(require('./new')(config)), + data: require('./data')(config), + get: require('./get')(config), + links: require('./links')(config), + new: require('./new')(config), patch: require('./patch')(config), - put: callbackify.variadic(require('./put')(config)), - stat: callbackify.variadic(require('./stat')(config)) + put: require('./put')(config), + stat: require('./stat')(config) }) diff --git a/src/object/patch/index.js b/src/object/patch/index.js index 5711200ec..f886e288f 100644 --- a/src/object/patch/index.js +++ b/src/object/patch/index.js @@ -1,10 +1,8 @@ 'use strict' -const callbackify = require('callbackify') - module.exports = config => ({ - addLink: callbackify.variadic(require('./add-link')(config)), - appendData: callbackify.variadic(require('./append-data')(config)), - rmLink: callbackify.variadic(require('./rm-link')(config)), - setData: callbackify.variadic(require('./set-data')(config)) + addLink: require('./add-link')(config), + appendData: require('./append-data')(config), + rmLink: require('./rm-link')(config), + setData: require('./set-data')(config) }) diff --git a/src/pin/add.js b/src/pin/add.js index 74eb47a2d..41b119fe8 100644 --- a/src/pin/add.js +++ b/src/pin/add.js @@ -1,13 +1,15 @@ 'use strict' +const CID = require('cids') const configure = require('../lib/configure') module.exports = configure(({ ky }) => { - return async (path, options) => { + return async (paths, options) => { + paths = Array.isArray(paths) ? paths : [paths] options = options || {} const searchParams = new URLSearchParams(options.searchParams) - searchParams.set('arg', `${path}`) + paths.forEach(path => searchParams.append('arg', `${path}`)) if (options.recursive != null) searchParams.set('recursive', options.recursive) const res = await ky.post('pin/add', { @@ -17,6 +19,6 @@ module.exports = configure(({ ky }) => { searchParams }).json() - return (res.Pins || []).map(hash => ({ hash })) + return (res.Pins || []).map(cid => ({ cid: new CID(cid) })) } }) diff --git a/src/pin/index.js b/src/pin/index.js index c62d3a46a..ad43057ec 100644 --- a/src/pin/index.js +++ b/src/pin/index.js @@ -1,9 +1,7 @@ 'use strict' -const callbackify = require('callbackify') - module.exports = config => ({ - add: callbackify.variadic(require('./add')(config)), - rm: callbackify.variadic(require('./rm')(config)), - ls: callbackify.variadic(require('./ls')(config)) + add: require('./add')(config), + rm: require('./rm')(config), + ls: require('./ls')(config) }) diff --git a/src/pin/ls.js b/src/pin/ls.js index 9c42fd71d..f9e0968ac 100644 --- a/src/pin/ls.js +++ b/src/pin/ls.js @@ -1,9 +1,12 @@ 'use strict' +const ndjson = require('iterable-ndjson') +const CID = require('cids') const configure = require('../lib/configure') +const toIterable = require('stream-to-it/source') module.exports = configure(({ ky }) => { - return async (path, options) => { + return async function * ls (path, options) { if (path && path.type) { options = path path = null @@ -14,16 +17,25 @@ module.exports = configure(({ ky }) => { options = options || {} const searchParams = new URLSearchParams(options.searchParams) + searchParams.set('stream', options.stream == null ? true : options.stream) path.forEach(p => searchParams.append('arg', `${p}`)) if (options.type) searchParams.set('type', options.type) - const { Keys } = await ky.post('pin/ls', { + const res = await ky.post('pin/ls', { timeout: options.timeout, signal: options.signal, headers: options.headers, searchParams - }).json() + }) - return Object.keys(Keys).map(hash => ({ hash, type: Keys[hash].Type })) + for await (const pin of ndjson(toIterable(res.body))) { + if (pin.Keys) { // non-streaming response + for (const cid of Object.keys(pin.Keys)) { + yield { cid: new CID(cid), type: pin.Keys[cid].Type } + } + return + } + yield { cid: new CID(pin.Cid), type: pin.Type } + } } }) diff --git a/src/pin/rm.js b/src/pin/rm.js index 9f75307ff..83fbca93c 100644 --- a/src/pin/rm.js +++ b/src/pin/rm.js @@ -1,5 +1,6 @@ 'use strict' +const CID = require('cids') const configure = require('../lib/configure') module.exports = configure(({ ky }) => { @@ -17,6 +18,6 @@ module.exports = configure(({ ky }) => { searchParams }).json() - return (res.Pins || []).map(hash => ({ hash })) + return (res.Pins || []).map(cid => ({ cid: new CID(cid) })) } }) diff --git a/src/ping.js b/src/ping.js index 33b275617..332120934 100644 --- a/src/ping.js +++ b/src/ping.js @@ -2,7 +2,7 @@ const ndjson = require('iterable-ndjson') const configure = require('./lib/configure') -const toIterable = require('./lib/stream-to-iterable') +const toIterable = require('stream-to-it/source') const toCamel = require('./lib/object-to-camel') module.exports = configure(({ ky }) => { diff --git a/src/pubsub/index.js b/src/pubsub/index.js index 2738bd5ac..e369bb6f3 100644 --- a/src/pubsub/index.js +++ b/src/pubsub/index.js @@ -1,50 +1,9 @@ 'use strict' -const nodeify = require('promise-nodeify') - -// This file is temporary and for compatibility with legacy usage -module.exports = (send, options) => { - if (typeof send !== 'function') { - options = send - } - - const ls = require('./ls')(options) - const peers = require('./peers')(options) - const publish = require('./publish')(options) - const subscribe = require('./subscribe')(options) - const unsubscribe = require('./unsubscribe')(options) - - return { - ls: (options, callback) => { - if (typeof options === 'function') { - callback = options - options = {} - } - return nodeify(ls(options), callback) - }, - peers: (topic, options, callback) => { - if (typeof options === 'function') { - callback = options - options = {} - } - return nodeify(peers(topic, options), callback) - }, - publish: (topic, data, options, callback) => { - if (typeof options === 'function') { - callback = options - options = {} - } - return nodeify(publish(topic, data, options), callback) - }, - subscribe: (topic, handler, options, callback) => { - if (typeof options === 'function') { - callback = options - options = {} - } - return nodeify(subscribe(topic, handler, options), callback) - }, - unsubscribe: (topic, handler, callback) => { - return nodeify(unsubscribe(topic, handler), callback) - } - } -} +module.exports = config => ({ + ls: require('./ls')(config), + peers: require('./peers')(config), + publish: require('./publish')(config), + subscribe: require('./subscribe')(config), + unsubscribe: require('./unsubscribe')(config) +}) diff --git a/src/pubsub/subscribe.js b/src/pubsub/subscribe.js index 7950a274a..188a91664 100644 --- a/src/pubsub/subscribe.js +++ b/src/pubsub/subscribe.js @@ -1,12 +1,11 @@ 'use strict' const ndjson = require('iterable-ndjson') -const explain = require('explain-error') const bs58 = require('bs58') const { Buffer } = require('buffer') const log = require('debug')('ipfs-http-client:pubsub:subscribe') const configure = require('../lib/configure') -const toIterable = require('../lib/stream-to-iterable') +const toIterable = require('stream-to-it/source') const SubscriptionTracker = require('./subscription-tracker') module.exports = configure((config) => { @@ -71,7 +70,8 @@ async function readMessages (msgStream, { onMessage, onEnd, onError }) { topicIDs: msg.topicIDs }) } catch (err) { - onError(explain(err, 'Failed to parse pubsub message'), false, msg) // Not fatal + err.message = `Failed to parse pubsub message: ${err.message}` + onError(err, false, msg) // Not fatal } } } catch (err) { diff --git a/src/refs/index.js b/src/refs/index.js index b15f2cd0c..05a636feb 100644 --- a/src/refs/index.js +++ b/src/refs/index.js @@ -4,7 +4,7 @@ const configure = require('../lib/configure') const { Buffer } = require('buffer') const CID = require('cids') const ndjson = require('iterable-ndjson') -const toIterable = require('../lib/stream-to-iterable') +const toIterable = require('stream-to-it/source') const toCamel = require('../lib/object-to-camel') module.exports = config => { diff --git a/src/refs/local.js b/src/refs/local.js index afa1630ea..98e0fce40 100644 --- a/src/refs/local.js +++ b/src/refs/local.js @@ -2,7 +2,7 @@ const configure = require('../lib/configure') const ndjson = require('iterable-ndjson') -const toIterable = require('../lib/stream-to-iterable') +const toIterable = require('stream-to-it/source') const toCamel = require('../lib/object-to-camel') module.exports = configure(({ ky }) => { diff --git a/src/repo/gc.js b/src/repo/gc.js index 3d92dee4c..fc60a46bc 100644 --- a/src/repo/gc.js +++ b/src/repo/gc.js @@ -3,7 +3,7 @@ const CID = require('cids') const ndjson = require('iterable-ndjson') const configure = require('../lib/configure') -const toIterable = require('../lib/stream-to-iterable') +const toIterable = require('stream-to-it/source') module.exports = configure(({ ky }) => { return async function * gc (peerId, options) { diff --git a/src/repo/index.js b/src/repo/index.js index fe58504ad..4785f55db 100644 --- a/src/repo/index.js +++ b/src/repo/index.js @@ -1,10 +1,7 @@ 'use strict' -const callbackify = require('callbackify') -const { collectify } = require('../lib/converters') - module.exports = config => ({ - gc: callbackify.variadic(collectify(require('./gc')(config))), - stat: callbackify.variadic(require('./stat')(config)), - version: callbackify.variadic(require('./version')(config)) + gc: require('./gc')(config), + stat: require('./stat')(config), + version: require('./version')(config) }) diff --git a/src/stats/bw.js b/src/stats/bw.js index f68ad23ba..12bc6d44a 100644 --- a/src/stats/bw.js +++ b/src/stats/bw.js @@ -3,7 +3,7 @@ const ndjson = require('iterable-ndjson') const Big = require('bignumber.js') const configure = require('../lib/configure') -const toIterable = require('../lib/stream-to-iterable') +const toIterable = require('stream-to-it/source') module.exports = configure(({ ky }) => { return async function * bw (options) { diff --git a/src/stats/index.js b/src/stats/index.js index 4351d79e2..d13a534a7 100644 --- a/src/stats/index.js +++ b/src/stats/index.js @@ -1,19 +1,7 @@ 'use strict' -const callbackify = require('callbackify') -const { streamify, pullify } = require('../lib/converters') - -module.exports = config => { - const bw = require('./bw')(config) - return { - bitswap: callbackify.variadic(require('../bitswap/stat')(config)), - bw: callbackify.variadic(async options => { - for await (const stats of bw(options)) { - return stats - } - }), - bwReadableStream: streamify.readable(bw), - bwPullStream: pullify.source(bw), - repo: callbackify.variadic(require('../repo/stat')(config)) - } -} +module.exports = config => ({ + bitswap: require('../bitswap/stat')(config), + bw: require('./bw')(config), + repo: require('../repo/stat')(config) +}) diff --git a/src/swarm/addrs.js b/src/swarm/addrs.js index a786d32cb..25bd98d02 100644 --- a/src/swarm/addrs.js +++ b/src/swarm/addrs.js @@ -1,7 +1,6 @@ 'use strict' -const PeerInfo = require('peer-info') -const PeerId = require('peer-id') +const CID = require('cids') const multiaddr = require('multiaddr') const configure = require('../lib/configure') @@ -16,10 +15,9 @@ module.exports = configure(({ ky }) => { searchParams: options.searchParams }).json() - return Object.keys(res.Addrs).map(id => { - const peerInfo = new PeerInfo(PeerId.createFromB58String(id)) - res.Addrs[id].forEach(addr => peerInfo.multiaddrs.add(multiaddr(addr))) - return peerInfo - }) + return Object.keys(res.Addrs).map(id => ({ + id: new CID(id), + addrs: (res.Addrs[id] || []).map(a => multiaddr(a)) + })) } }) diff --git a/src/swarm/disconnect.js b/src/swarm/disconnect.js index a3d60d172..e83ca0dd4 100644 --- a/src/swarm/disconnect.js +++ b/src/swarm/disconnect.js @@ -8,7 +8,7 @@ module.exports = configure(({ ky }) => { options = options || {} const searchParams = new URLSearchParams(options.searchParams) - addrs.forEach(addr => searchParams.append('arg', addr)) + addrs.forEach(addr => searchParams.append('arg', `${addr}`)) const res = await ky.post('swarm/disconnect', { timeout: options.timeout, diff --git a/src/swarm/index.js b/src/swarm/index.js index e86a7c22c..84648439d 100644 --- a/src/swarm/index.js +++ b/src/swarm/index.js @@ -1,11 +1,9 @@ 'use strict' -const callbackify = require('callbackify') - module.exports = config => ({ - addrs: callbackify.variadic(require('./addrs')(config)), - connect: callbackify.variadic(require('./connect')(config)), - disconnect: callbackify.variadic(require('./disconnect')(config)), - localAddrs: callbackify.variadic(require('./localAddrs')(config)), - peers: callbackify.variadic(require('./peers')(config)) + addrs: require('./addrs')(config), + connect: require('./connect')(config), + disconnect: require('./disconnect')(config), + localAddrs: require('./localAddrs')(config), + peers: require('./peers')(config) }) diff --git a/src/swarm/peers.js b/src/swarm/peers.js index 3b897348c..f10035e06 100644 --- a/src/swarm/peers.js +++ b/src/swarm/peers.js @@ -1,7 +1,7 @@ 'use strict' const multiaddr = require('multiaddr') -const PeerId = require('peer-id') +const CID = require('cids') const configure = require('../lib/configure') module.exports = configure(({ ky }) => { @@ -25,7 +25,7 @@ module.exports = configure(({ ky }) => { const info = {} try { info.addr = multiaddr(peer.Addr) - info.peer = PeerId.createFromB58String(peer.Peer) + info.peer = new CID(peer.Peer) } catch (error) { info.error = error info.rawPeerInfo = peer diff --git a/test/custom-headers.spec.js b/test/custom-headers.spec.js index ce14a01e5..5e88b72a6 100644 --- a/test/custom-headers.spec.js +++ b/test/custom-headers.spec.js @@ -1,7 +1,7 @@ /* eslint-env mocha */ 'use strict' -const isNode = require('detect-node') +const { isNode } = require('ipfs-utils/src/env') const { expect } = require('interface-ipfs-core/src/utils/mocha') const ipfsClient = require('../src') diff --git a/test/exports.spec.js b/test/exports.spec.js index f97707e13..0df770da6 100644 --- a/test/exports.spec.js +++ b/test/exports.spec.js @@ -1,28 +1,22 @@ /* eslint-env mocha, browser */ 'use strict' -const isIPFS = require('is-ipfs') const CID = require('cids') const multiaddr = require('multiaddr') const multibase = require('multibase') const multicodec = require('multicodec') const multihash = require('multihashes') -const PeerId = require('peer-id') -const PeerInfo = require('peer-info') const { expect } = require('interface-ipfs-core/src/utils/mocha') const IpfsHttpClient = require('../') describe('exports', () => { it('should export the expected types and utilities', () => { - expect(IpfsHttpClient.isIPFS).to.equal(isIPFS) expect(IpfsHttpClient.Buffer).to.equal(Buffer) expect(IpfsHttpClient.CID).to.equal(CID) expect(IpfsHttpClient.multiaddr).to.equal(multiaddr) expect(IpfsHttpClient.multibase).to.equal(multibase) expect(IpfsHttpClient.multicodec).to.equal(multicodec) expect(IpfsHttpClient.multihash).to.equal(multihash) - expect(IpfsHttpClient.PeerId).to.equal(PeerId) - expect(IpfsHttpClient.PeerInfo).to.equal(PeerInfo) }) }) diff --git a/test/files-mfs.spec.js b/test/files-mfs.spec.js index 0e3d6b1af..edc7698e1 100644 --- a/test/files-mfs.spec.js +++ b/test/files-mfs.spec.js @@ -5,13 +5,11 @@ const { expect } = require('interface-ipfs-core/src/utils/mocha') const loadFixture = require('aegir/fixtures') const mh = require('multihashes') -const CID = require('cids') -const values = require('pull-stream/sources/values') -const pull = require('pull-stream/pull') -const collect = require('pull-stream/sinks/collect') +const all = require('it-all') +const pipe = require('it-pipe') +const { TimeoutError } = require('ky-universal') const f = require('./utils/factory') -const expectTimeout = require('./utils/expect-timeout') const testfile = loadFixture('test/fixtures/testfile.txt') @@ -41,10 +39,10 @@ describe('.files (the MFS API part)', function () { after(() => f.clean()) it('.add file for testing', async () => { - const res = await ipfs.add(testfile) + const res = await all(ipfs.add(testfile)) expect(res).to.have.length(1) - expect(res[0].hash).to.equal(expectedMultihash) + expect(res[0].cid.toString()).to.equal(expectedMultihash) expect(res[0].path).to.equal(expectedMultihash) }) @@ -54,10 +52,10 @@ describe('.files (the MFS API part)', function () { const expectedBufferMultihash = 'QmWfVY9y3xjsixTgbd9AorQxH7VtMpzfx2HaWtsoUYecaX' const file = Buffer.from('hello') - const res = await ipfs.add(file) + const res = await all(ipfs.add(file)) expect(res).to.have.length(1) - expect(res[0].hash).to.equal(expectedBufferMultihash) + expect(res[0].cid.toString()).to.equal(expectedBufferMultihash) expect(res[0].path).to.equal(expectedBufferMultihash) }) @@ -65,10 +63,10 @@ describe('.files (the MFS API part)', function () { const expectedHash = 'QmWfVY9y3xjsixTgbd9AorQxH7VtMpzfx2HaWtsoUYecaX' const content = Buffer.from('hello') - const res = await ipfs.add([{ path: '', content }]) + const res = await all(ipfs.add([{ path: '', content }])) expect(res).to.have.length(1) - expect(res[0].hash).to.equal(expectedHash) + expect(res[0].cid.toString()).to.equal(expectedHash) expect(res[0].path).to.equal(expectedHash) }) @@ -76,39 +74,40 @@ describe('.files (the MFS API part)', function () { const expectedCid = 'bafybeifogzovjqrcxvgt7g36y7g63hvwvoakledwk4b2fr2dl4wzawpnny' const options = { cidVersion: 1, rawLeaves: false } - const res = await ipfs.add(testfile, options) + const res = await all(ipfs.add(testfile, options)) expect(res).to.have.length(1) - expect(res[0].hash).to.equal(expectedCid) + expect(res[0].cid.toString()).to.equal(expectedCid) expect(res[0].path).to.equal(expectedCid) }) it('.add with only-hash=true', async () => { const content = String(Math.random() + Date.now()) - const files = await ipfs.add(Buffer.from(content), { onlyHash: true }) + const files = await all(ipfs.add(Buffer.from(content), { onlyHash: true })) expect(files).to.have.length(1) // 'ipfs.object.get()' should timeout because content wasn't actually added - await expectTimeout(ipfs.object.get(files[0].hash), 4000) + return expect(ipfs.object.get(files[0].cid, { timeout: 2000 })) + .to.be.rejectedWith(TimeoutError) }) it('.add with options', async () => { - const res = await ipfs.add(testfile, { pin: false }) + const res = await all(ipfs.add(testfile, { pin: false })) expect(res).to.have.length(1) - expect(res[0].hash).to.equal(expectedMultihash) + expect(res[0].cid.toString()).to.equal(expectedMultihash) expect(res[0].path).to.equal(expectedMultihash) }) it('.add pins by default', async () => { const newContent = Buffer.from(String(Math.random())) - const initialPins = await ipfs.pin.ls() + const initialPins = await all(ipfs.pin.ls()) - await ipfs.add(newContent) + await all(ipfs.add(newContent)) - const pinsAfterAdd = await ipfs.pin.ls() + const pinsAfterAdd = await all(ipfs.pin.ls()) expect(pinsAfterAdd.length).to.eql(initialPins.length + 1) }) @@ -116,11 +115,11 @@ describe('.files (the MFS API part)', function () { it('.add with pin=false', async () => { const newContent = Buffer.from(String(Math.random())) - const initialPins = await ipfs.pin.ls() + const initialPins = await all(ipfs.pin.ls()) - await ipfs.add(newContent, { pin: false }) + await all(ipfs.add(newContent, { pin: false })) - const pinsAfterAdd = await ipfs.pin.ls() + const pinsAfterAdd = await all(ipfs.pin.ls()) expect(pinsAfterAdd.length).to.eql(initialPins.length) }) @@ -134,10 +133,10 @@ describe('.files (the MFS API part)', function () { } const options = { hashAlg: name, rawLeaves: false } - const res = await ipfs.add([file], options) + const res = await all(ipfs.add([file], options)) expect(res).to.have.length(1) - const cid = new CID(res[0].hash) + const { cid } = res[0] expect(mh.decode(cid.multihash).name).to.equal(name) }) }) @@ -151,7 +150,7 @@ describe('.files (the MFS API part)', function () { progress = p } - const res = await ipfs.add(testfile, { progress: progressHandler }) + const res = await all(ipfs.add(testfile, { progress: progressHandler })) expect(res).to.have.length(1) expect(progress).to.be.equal(testfile.byteLength) @@ -168,7 +167,7 @@ describe('.files (the MFS API part)', function () { } // TODO: needs to be using a big file - const res = await ipfs.add(testfile, { progress: progressHandler }) + const res = await all(ipfs.add(testfile, { progress: progressHandler })) expect(res).to.have.length(1) expect(progress).to.be.equal(testfile.byteLength) @@ -185,7 +184,7 @@ describe('.files (the MFS API part)', function () { } // TODO: needs to be using a directory - const res = await ipfs.add(testfile, { progress: progressHandler }) + const res = await all(ipfs.add(testfile, { progress: progressHandler })) expect(res).to.have.length(1) expect(progress).to.be.equal(testfile.byteLength) @@ -193,7 +192,7 @@ describe('.files (the MFS API part)', function () { }) it('.add without progress options', async () => { - const res = await ipfs.add(testfile) + const res = await all(ipfs.add(testfile)) expect(res).to.have.length(1) }) @@ -207,44 +206,35 @@ describe('.files (the MFS API part)', function () { } const options = { hashAlg: name, rawLeaves: false } - const res = await ipfs.add([file], options) + const res = await all(ipfs.add([file], options)) expect(res).to.have.length(1) - const cid = new CID(res[0].hash) + const { cid } = res[0] expect(mh.decode(cid.multihash).name).to.equal(name) }) }) - it('.addPullStream with object chunks and pull stream content', (done) => { + it('.add with object chunks and iterable content', async () => { const expectedCid = 'QmRf22bZar3WKmojipms22PkXH1MZGmvsqzQtuSvQE3uhm' - pull( - values([{ content: values([Buffer.from('test')]) }]), - ipfs.addPullStream(), - collect((err, res) => { - expect(err).to.not.exist() - - expect(res).to.have.length(1) - expect(res[0]).to.deep.equal({ path: expectedCid, hash: expectedCid, size: 12 }) - done() - }) + const res = await pipe( + [{ content: [Buffer.from('test')] }], + ipfs.add, + all ) - }) - - it('.add with pull stream', async () => { - const expectedCid = 'QmRf22bZar3WKmojipms22PkXH1MZGmvsqzQtuSvQE3uhm' - const res = await ipfs.add(values([Buffer.from('test')])) expect(res).to.have.length(1) - expect(res[0]).to.deep.equal({ path: expectedCid, hash: expectedCid, size: 12 }) + res[0].cid = res[0].cid.toString() + expect(res[0]).to.deep.equal({ path: expectedCid, cid: expectedCid, size: 12 }) }) - it('.add with array of objects with pull stream content', async () => { + it('.add with iterable', async () => { const expectedCid = 'QmRf22bZar3WKmojipms22PkXH1MZGmvsqzQtuSvQE3uhm' - const res = await ipfs.add([{ content: values([Buffer.from('test')]) }]) + const res = await all(ipfs.add([Buffer.from('test')])) expect(res).to.have.length(1) - expect(res[0]).to.eql({ path: expectedCid, hash: expectedCid, size: 12 }) + res[0].cid = res[0].cid.toString() + expect(res[0]).to.deep.equal({ path: expectedCid, cid: expectedCid, size: 12 }) }) it('files.mkdir', async () => { @@ -315,7 +305,7 @@ describe('.files (the MFS API part)', function () { await ipfs.files.write(file, Buffer.from('Hello, world'), { create: true }) - const files = await ipfs.files.ls(folder) + const files = await all(ipfs.files.ls(folder)) expect(files.length).to.equal(1) }) @@ -324,7 +314,7 @@ describe('.files (the MFS API part)', function () { const folder = `test-folder-${Math.random()}` await ipfs.files.mkdir(`/${folder}`) - const files = await ipfs.files.ls() + const files = await all(ipfs.files.ls()) expect(files.find(file => file.name === folder)).to.be.ok() }) @@ -334,7 +324,7 @@ describe('.files (the MFS API part)', function () { create: true }) - const buf = await ipfs.files.read('/test-folder/test-file-2.txt') + const buf = Buffer.concat(await all(ipfs.files.read('/test-folder/test-file-2.txt'))) expect(buf.toString()).to.be.equal('hello world') }) @@ -342,7 +332,7 @@ describe('.files (the MFS API part)', function () { it('files.write without options', async () => { await ipfs.files.write('/test-folder/test-file-2.txt', Buffer.from('hello world')) - const buf = await ipfs.files.read('/test-folder/test-file-2.txt') + const buf = Buffer.concat(await all(ipfs.files.read('/test-folder/test-file-2.txt'))) expect(buf.toString()).to.be.equal('hello world') }) @@ -357,9 +347,10 @@ describe('.files (the MFS API part)', function () { }) const stats = await ipfs.files.stat(file) + stats.cid = stats.cid.toString() expect(stats).to.deep.equal({ - hash: 'QmQhouoDPAnzhVM148yCa9CbUXK65wSEAZBtgrLGHtmdmP', + cid: 'QmQhouoDPAnzhVM148yCa9CbUXK65wSEAZBtgrLGHtmdmP', size: 12, cumulativeSize: 70, blocks: 1, @@ -383,7 +374,7 @@ describe('.files (the MFS API part)', function () { await ipfs.files.write(file, testfile, { create: true }) - const buf = await ipfs.files.read(file) + const buf = Buffer.concat(await all(ipfs.files.read(file))) expect(Buffer.from(buf)).to.deep.equal(testfile) }) diff --git a/test/get.spec.js b/test/get.spec.js index a6fb3aaa4..c303179c8 100644 --- a/test/get.spec.js +++ b/test/get.spec.js @@ -5,6 +5,8 @@ const { expect } = require('interface-ipfs-core/src/utils/mocha') const loadFixture = require('aegir/fixtures') +const all = require('it-all') +const concat = require('it-concat') const f = require('./utils/factory') @@ -24,35 +26,37 @@ describe('.get (specific go-ipfs features)', function () { before(async () => { ipfs = (await f.spawn()).api - await ipfs.add(smallFile.data) + await all(ipfs.add(smallFile.data)) }) after(() => f.clean()) it('no compression args', async () => { - const files = await ipfs.get(smallFile.cid) + const files = await all(ipfs.get(smallFile.cid)) expect(files).to.be.length(1) - expect(files[0].content.toString()).to.contain(smallFile.data.toString()) + const content = await concat(files[0].content) + expect(content.toString()).to.contain(smallFile.data.toString()) }) it('archive true', async () => { - const files = await ipfs.get(smallFile.cid, { archive: true }) + const files = await all(ipfs.get(smallFile.cid, { archive: true })) expect(files).to.be.length(1) - expect(files[0].content.toString()).to.contain(smallFile.data.toString()) + const content = await concat(files[0].content) + expect(content.toString()).to.contain(smallFile.data.toString()) }) it('err with out of range compression level', async () => { - await expect(ipfs.get(smallFile.cid, { + await expect(all(ipfs.get(smallFile.cid, { compress: true, compressionLevel: 10 - })).to.be.rejectedWith('compression level must be between 1 and 9') + }))).to.be.rejectedWith('compression level must be between 1 and 9') }) // TODO Understand why this test started failing it.skip('with compression level', async () => { - await ipfs.get(smallFile.cid, { compress: true, 'compression-level': 1 }) + await all(ipfs.get(smallFile.cid, { compress: true, 'compression-level': 1 })) }) it('add path containing "+"s (for testing get)', async () => { @@ -60,17 +64,17 @@ describe('.get (specific go-ipfs features)', function () { const subdir = 'tmp/c++files' const expectedCid = 'QmPkmARcqjo5fqK1V1o8cFsuaXxWYsnwCNLJUYS4KeZyff' const path = `${subdir}/${filename}` - const files = await ipfs.add([{ + const files = await all(ipfs.add([{ path, content: Buffer.from(path) - }]) + }])) - expect(files[2].hash).to.equal(expectedCid) + expect(files[2].cid.toString()).to.equal(expectedCid) }) it('get path containing "+"s', async () => { const cid = 'QmPkmARcqjo5fqK1V1o8cFsuaXxWYsnwCNLJUYS4KeZyff' - const files = await ipfs.get(cid) + const files = await all(ipfs.get(cid)) expect(files).to.be.an('array').with.lengthOf(3) expect(files[0]).to.have.property('path', cid) diff --git a/test/interface.spec.js b/test/interface.spec.js index 796c1ae86..ebec1b0e9 100644 --- a/test/interface.spec.js +++ b/test/interface.spec.js @@ -3,7 +3,6 @@ const tests = require('interface-ipfs-core') const merge = require('merge-options') -const { isNode } = require('ipfs-utils/src/env') const { createFactory } = require('ipfsd-ctl') const { findBin } = require('ipfsd-ctl/src/utils') const isWindows = process.platform && process.platform === 'win32' @@ -25,6 +24,43 @@ describe('interface-ipfs-core tests', () => { } const commonFactory = createFactory(commonOptions) + tests.root(commonFactory, { + skip: [ + { + name: 'should add with mode as string', + reason: 'TODO not implemented in go-ipfs yet' + }, + { + name: 'should add with mode as number', + reason: 'TODO not implemented in go-ipfs yet' + }, + { + name: 'should add with mtime as Date', + reason: 'TODO not implemented in go-ipfs yet' + }, + { + name: 'should add with mtime as { nsecs, secs }', + reason: 'TODO not implemented in go-ipfs yet' + }, + { + name: 'should add with mtime as timespec', + reason: 'TODO not implemented in go-ipfs yet' + }, + { + name: 'should add with mtime as hrtime', + reason: 'TODO not implemented in go-ipfs yet' + }, + { + name: 'should export a chunk of a file', + reason: 'TODO not implemented in go-ipfs yet' + }, + { + name: 'should ls with metadata', + reason: 'TODO not implemented in go-ipfs yet' + } + ] + }) + tests.bitswap(commonFactory) tests.block(commonFactory, { @@ -34,7 +70,18 @@ describe('interface-ipfs-core tests', () => { }] }) - tests.bootstrap(commonFactory) + tests.bootstrap(commonFactory, { + skip: [{ + name: 'should return a list containing the bootstrap peer when called with a valid arg (ip4)', + reason: 'TODO unskip when go-ipfs switches to p2p for libp2p keys' + }, { + name: 'should prevent duplicate inserts of bootstrap peers', + reason: 'TODO unskip when go-ipfs switches to p2p for libp2p keys' + }, { + name: 'should return a list containing the peer removed when called with a valid arg (ip4)', + reason: 'TODO unskip when go-ipfs switches to p2p for libp2p keys' + }] + }) tests.config(commonFactory, { skip: [ @@ -81,31 +128,21 @@ describe('interface-ipfs-core tests', () => { ] }) - tests.dht(commonFactory, { + tests.dht(commonFactory) + + tests.files(commonFactory, { skip: [ - // dht.findpeer { - name: 'should fail to find other peer if peer does not exist', - reason: 'FIXME checking what is exactly go-ipfs returning https://github.com/ipfs/go-ipfs/issues/3862#issuecomment-294168090' + name: 'should ls directory', + reason: 'TODO unskip when go-ipfs supports --long https://github.com/ipfs/go-ipfs/pull/6528' }, - // dht.findprovs { - name: 'should take options to override timeout config', - reason: 'FIXME go-ipfs does not support a timeout option' + name: 'should list a file directly', + reason: 'TODO unskip when go-ipfs supports --long https://github.com/ipfs/go-ipfs/pull/6528' }, - // dht.get - { - name: 'should get a value after it was put on another node', - reason: 'FIXME go-ipfs errors with Error: key was not found (type 6) https://github.com/ipfs/go-ipfs/issues/3862' - } - ] - }) - - tests.filesMFS(commonFactory, { - skip: [ { - name: 'should ls directory with long option', - reason: 'TODO unskip when go-ipfs supports --long https://github.com/ipfs/go-ipfs/pull/6528' + name: 'should ls directory and include metadata', + reason: 'TODO not implemented in go-ipfs yet' }, { name: 'should read from outside of mfs', @@ -167,10 +204,6 @@ describe('interface-ipfs-core tests', () => { name: 'should respect metadata when copying from outside of mfs', reason: 'TODO not implemented in go-ipfs yet' }, - { - name: 'ls directory with long option should include metadata', - reason: 'TODO not implemented in go-ipfs yet' - }, { name: 'should have default mtime', reason: 'TODO not implemented in go-ipfs yet' @@ -270,57 +303,6 @@ describe('interface-ipfs-core tests', () => { ] }) - tests.filesRegular(commonFactory, { - skip: [ - // .addFromFs - isNode ? null : { - name: 'addFromFs', - reason: 'Not designed to run in the browser' - }, - { - name: 'should add with mode as string', - reason: 'TODO not implemented in go-ipfs yet' - }, - { - name: 'should add with mode as number', - reason: 'TODO not implemented in go-ipfs yet' - }, - { - name: 'should add with mtime as Date', - reason: 'TODO not implemented in go-ipfs yet' - }, - { - name: 'should add with mtime as { nsecs, secs }', - reason: 'TODO not implemented in go-ipfs yet' - }, - { - name: 'should add with mtime as timespec', - reason: 'TODO not implemented in go-ipfs yet' - }, - { - name: 'should add with mtime as hrtime', - reason: 'TODO not implemented in go-ipfs yet' - }, - // .catPullStream - { - name: 'should export a chunk of a file', - reason: 'TODO not implemented in go-ipfs yet' - }, - { - name: 'should export a chunk of a file in a Pull Stream', - reason: 'TODO not implemented in go-ipfs yet' - }, - { - name: 'should export a chunk of a file in a Readable Stream', - reason: 'TODO not implemented in go-ipfs yet' - }, - { - name: 'should ls with metadata', - reason: 'TODO not implemented in go-ipfs yet' - } - ] - }) - tests.key(commonFactory, { skip: [ // key.export @@ -346,7 +328,6 @@ describe('interface-ipfs-core tests', () => { } )), { skip: [ - // stop { name: 'should resolve a record from peerid as cidv1 in base32', reason: 'TODO not implemented in go-ipfs yet: https://github.com/ipfs/go-ipfs/issues/5287' @@ -383,14 +364,6 @@ describe('interface-ipfs-core tests', () => { tests.ping(commonFactory, { skip: [ - { - name: 'should fail when pinging an unknown peer over pull stream', - reason: 'FIXME go-ipfs return success with text: Looking up peer ' - }, - { - name: 'should fail when pinging peer that is not available over readable stream', - reason: 'FIXME go-ipfs return success with text: Looking up peer ' - }, { name: 'should fail when pinging a peer that is not available', reason: 'FIXME go-ipfs return success with text: Looking up peer ' diff --git a/test/lib.stream-to-iterable.spec.js b/test/lib.stream-to-iterable.spec.js deleted file mode 100644 index 3ad326480..000000000 --- a/test/lib.stream-to-iterable.spec.js +++ /dev/null @@ -1,40 +0,0 @@ -/* eslint-env mocha */ -'use strict' - -const { expect } = require('interface-ipfs-core/src/utils/mocha') -const toIterable = require('../src/lib/stream-to-iterable') - -describe('lib/stream-to-iterable', () => { - it('should return input if already async iterable', () => { - const input = { [Symbol.asyncIterator] () { return this } } - expect(toIterable(input)).to.equal(input) - }) - - it('should convert reader to async iterable', async () => { - const inputData = [2, 31, 3, 4] - const input = { - getReader () { - let i = 0 - return { - read () { - return i === inputData.length - ? { done: true } - : { value: inputData[i++] } - }, - releaseLock () {} - } - } - } - - const chunks = [] - for await (const chunk of toIterable(input)) { - chunks.push(chunk) - } - - expect(chunks).to.eql(inputData) - }) - - it('should throw on unknown stream', () => { - expect(() => toIterable({})).to.throw('unknown stream') - }) -}) diff --git a/test/log.spec.js b/test/log.spec.js index 1a885028d..c56660d07 100644 --- a/test/log.spec.js +++ b/test/log.spec.js @@ -3,6 +3,7 @@ 'use strict' const { expect } = require('interface-ipfs-core/src/utils/mocha') +const all = require('it-all') const f = require('./utils/factory') describe('.log', function () { @@ -19,7 +20,7 @@ describe('.log', function () { it('.log.tail', async () => { const i = setInterval(async () => { try { - await ipfs.add(Buffer.from('just adding some data to generate logs')) + await all(ipfs.add(Buffer.from('just adding some data to generate logs'))) } catch (_) { // this can error if the test has finished and we're shutting down the node } diff --git a/test/node/swarm.js b/test/node/swarm.js index 9e0252a2c..89315f2fe 100644 --- a/test/node/swarm.js +++ b/test/node/swarm.js @@ -25,7 +25,7 @@ describe('.swarm.peers', function () { expect(res.length).to.equal(1) expect(res[0].error).to.not.exist() expect(res[0].addr.toString()).to.equal(response.Peers[0].Addr) - expect(res[0].peer.toB58String()).to.equal(response.Peers[0].Peer) + expect(res[0].peer.toString()).to.equal(response.Peers[0].Peer) expect(scope.isDone()).to.equal(true) }) @@ -43,7 +43,7 @@ describe('.swarm.peers', function () { expect(res.length).to.equal(1) expect(res[0].error).to.not.exist() expect(res[0].addr.toString()).to.equal(response.Peers[0].Addr) - expect(res[0].peer.toB58String()).to.equal(response.Peers[0].Peer) + expect(res[0].peer.toString()).to.equal(response.Peers[0].Peer) expect(scope.isDone()).to.equal(true) }) diff --git a/test/ping.spec.js b/test/ping.spec.js index 01636ed60..7076f208b 100644 --- a/test/ping.spec.js +++ b/test/ping.spec.js @@ -2,8 +2,7 @@ 'use strict' const { expect } = require('interface-ipfs-core/src/utils/mocha') -const pull = require('pull-stream/pull') -const collect = require('pull-stream/sinks/collect') +const all = require('it-all') const f = require('./utils/factory') @@ -34,7 +33,7 @@ describe('.ping', function () { after(() => f.clean()) it('.ping with default count', async () => { - const res = await ipfs.ping(otherId) + const res = await all(ipfs.ping(otherId)) expect(res).to.be.an('array') expect(res.filter(isPong)).to.have.lengthOf(10) res.forEach(packet => { @@ -46,7 +45,7 @@ describe('.ping', function () { }) it('.ping with count = 2', async () => { - const res = await ipfs.ping(otherId, { count: 2 }) + const res = await all(ipfs.ping(otherId, { count: 2 })) expect(res).to.be.an('array') expect(res.filter(isPong)).to.have.lengthOf(2) res.forEach(packet => { @@ -56,39 +55,4 @@ describe('.ping', function () { const resultMsg = res.find(packet => packet.text.includes('Average latency')) expect(resultMsg).to.exist() }) - - it('.pingPullStream', (done) => { - pull( - ipfs.pingPullStream(otherId, { count: 2 }), - collect((err, data) => { - expect(err).to.not.exist() - expect(data).to.be.an('array') - expect(data.filter(isPong)).to.have.lengthOf(2) - data.forEach(packet => { - expect(packet).to.have.keys('success', 'time', 'text') - expect(packet.time).to.be.a('number') - }) - const resultMsg = data.find(packet => packet.text.includes('Average latency')) - expect(resultMsg).to.exist() - done() - }) - ) - }) - - it('.pingReadableStream', (done) => { - let packetNum = 0 - ipfs.pingReadableStream(otherId, { count: 2 }) - .on('data', data => { - expect(data).to.be.an('object') - expect(data).to.have.keys('success', 'time', 'text') - if (isPong(data)) packetNum++ - }) - .on('error', err => { - expect(err).not.to.exist() - }) - .on('end', () => { - expect(packetNum).to.equal(2) - done() - }) - }) }) diff --git a/test/request-api.spec.js b/test/request-api.spec.js index c213193bb..1767b5914 100644 --- a/test/request-api.spec.js +++ b/test/request-api.spec.js @@ -2,16 +2,12 @@ 'use strict' const { expect } = require('interface-ipfs-core/src/utils/mocha') -const isNode = require('detect-node') +const { isNode } = require('ipfs-utils/src/env') const ipfsClient = require('../src/index.js') -const ndjson = require('ndjson') -const pump = require('pump') describe('\'deal with HTTP weirdness\' tests', () => { - it('does not crash if no content-type header is provided', (done) => { - if (!isNode) { - return done() - } + it('does not crash if no content-type header is provided', async function () { + if (!isNode) return this.skip() // go-ipfs always (currently) adds a content-type header, even if no content is present, // the standard behaviour for an http-api is to omit this header if no content is present @@ -24,12 +20,10 @@ describe('\'deal with HTTP weirdness\' tests', () => { }) }) - server.listen(6001, () => { - ipfsClient('/ip4/127.0.0.1/tcp/6001').config.replace('test/fixtures/r-config.json', (err) => { - expect(err).to.not.exist() - server.close(done) - }) - }) + await new Promise(resolve => server.listen(6001, resolve)) + await ipfsClient('/ip4/127.0.0.1/tcp/6001').config.replace('test/fixtures/r-config.json') + + server.close() }) }) @@ -39,12 +33,11 @@ describe('trailer headers', () => { if (!isNode) { return done() } const server = require('http').createServer((req, res) => { - const resStream = pump(res, ndjson.stringify()) res.setHeader('x-chunked-output', '1') res.setHeader('content-type', 'application/json') res.setHeader('Trailer', 'X-Stream-Error') res.addTrailers({ 'X-Stream-Error': JSON.stringify({ Message: 'ups, something went wrong', Code: 500 }) }) - resStream.write({ Bytes: 1 }) + res.write(JSON.stringify({ Bytes: 1 })) res.end() }) @@ -64,7 +57,7 @@ describe('trailer headers', () => { }) describe('error handling', () => { - it('should handle plain text error response', function (done) { + it('should handle plain text error response', async function () { if (!isNode) return this.skip() const server = require('http').createServer((req, res) => { @@ -78,17 +71,16 @@ describe('error handling', () => { }) }) - server.listen(6001, () => { - ipfsClient('/ip4/127.0.0.1/tcp/6001').config.replace('test/fixtures/r-config.json', (err) => { - expect(err).to.exist() - expect(err.response.status).to.equal(403) - expect(err.message).to.equal('ipfs method not allowed') - server.close(done) - }) - }) + await new Promise(resolve => server.listen(6001, resolve)) + + await expect(ipfsClient('/ip4/127.0.0.1/tcp/6001').config.replace('test/fixtures/r-config.json')) + .to.eventually.be.rejectedWith('ipfs method not allowed') + .and.to.have.nested.property('response.status').that.equals(403) + + server.close() }) - it('should handle JSON error response', function (done) { + it('should handle JSON error response', async function () { if (!isNode) return this.skip() const server = require('http').createServer((req, res) => { @@ -102,17 +94,16 @@ describe('error handling', () => { }) }) - server.listen(6001, () => { - ipfsClient('/ip4/127.0.0.1/tcp/6001').config.replace('test/fixtures/r-config.json', (err) => { - expect(err).to.exist() - expect(err.response.status).to.equal(400) - expect(err.message).to.equal('client error') - server.close(done) - }) - }) + await new Promise(resolve => server.listen(6001, resolve)) + + await expect(ipfsClient('/ip4/127.0.0.1/tcp/6001').config.replace('test/fixtures/r-config.json')) + .to.eventually.be.rejectedWith('client error') + .and.to.have.nested.property('response.status').that.equals(400) + + server.close() }) - it('should handle JSON error response with invalid JSON', function (done) { + it('should handle JSON error response with invalid JSON', async function () { if (!isNode) return this.skip() const server = require('http').createServer((req, res) => { @@ -126,12 +117,12 @@ describe('error handling', () => { }) }) - server.listen(6001, () => { - ipfsClient('/ip4/127.0.0.1/tcp/6001').config.replace('test/fixtures/r-config.json', (err) => { - expect(err).to.exist() - expect(err.message).to.include('Unexpected token M in JSON at position 2') - server.close(done) - }) - }) + await new Promise(resolve => server.listen(6001, resolve)) + + await expect(ipfsClient('/ip4/127.0.0.1/tcp/6001').config.replace('test/fixtures/r-config.json')) + .to.eventually.be.rejected() + .and.to.have.property('message').that.includes('Unexpected token M in JSON at position 2') + + server.close() }) }) diff --git a/test/stats.spec.js b/test/stats.spec.js index d60aaa330..1e5d7da25 100644 --- a/test/stats.spec.js +++ b/test/stats.spec.js @@ -2,6 +2,7 @@ 'use strict' const { expect } = require('interface-ipfs-core/src/utils/mocha') +const all = require('it-all') const f = require('./utils/factory') describe('stats', function () { @@ -31,7 +32,7 @@ describe('stats', function () { }) it('.stats.bw', async () => { - const res = await ipfs.stats.bw() + const res = (await all(ipfs.stats.bw()))[0] expect(res).to.exist() expect(res).to.have.a.property('totalIn') diff --git a/test/sub-modules.spec.js b/test/sub-modules.spec.js index ee8f6d93b..a5db456df 100644 --- a/test/sub-modules.spec.js +++ b/test/sub-modules.spec.js @@ -64,12 +64,8 @@ describe('submodules', () => { it('ping', () => { const ping = require('../src')().ping - const pingPullStream = require('../src')().pingPullStream - const pingReadableStream = require('../src')().pingReadableStream expect(ping).to.be.a('function') - expect(pingPullStream).to.be.a('function') - expect(pingReadableStream).to.be.a('function') }) it('log', () => { @@ -164,26 +160,11 @@ describe('submodules', () => { const filesRegular = require('../src')() expect(filesRegular.add).to.be.a('function') - expect(filesRegular.addReadableStream).to.be.a('function') - expect(filesRegular.addPullStream).to.be.a('function') - expect(filesRegular.addFromStream).to.be.a('function') - expect(filesRegular.addFromFs).to.be.a('function') - expect(filesRegular.addFromURL).to.be.a('function') expect(filesRegular.get).to.be.a('function') - expect(filesRegular.getReadableStream).to.be.a('function') - expect(filesRegular.getPullStream).to.be.a('function') expect(filesRegular.cat).to.be.a('function') - expect(filesRegular.catReadableStream).to.be.a('function') - expect(filesRegular.catPullStream).to.be.a('function') expect(filesRegular.ls).to.be.a('function') - expect(filesRegular.lsReadableStream).to.be.a('function') - expect(filesRegular.lsPullStream).to.be.a('function') expect(filesRegular.refs).to.be.a('function') - expect(filesRegular.refsReadableStream).to.be.a('function') - expect(filesRegular.refsPullStream).to.be.a('function') expect(filesRegular.refs.local).to.be.a('function') - expect(filesRegular.refs.localReadableStream).to.be.a('function') - expect(filesRegular.refs.localPullStream).to.be.a('function') }) it('files MFS API', () => { diff --git a/test/utils/expect-timeout.js b/test/utils/expect-timeout.js deleted file mode 100644 index 51c733075..000000000 --- a/test/utils/expect-timeout.js +++ /dev/null @@ -1,16 +0,0 @@ -'use strict' - -/** - * Resolve if @param promise hangs for at least @param ms, throw otherwise - * @param {Promise} promise promise that you expect to hang - * @param {Number} ms millis to wait - * @return {Promise} - */ -module.exports = (promise, ms) => { - return Promise.race([ - promise.then((out) => { - throw new Error('Expected Promise to timeout but it was successful.') - }), - new Promise((resolve, reject) => setTimeout(resolve, ms)) - ]) -}