diff --git a/CHANGELOG.md b/CHANGELOG.md index 671f9572..2639184f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,23 @@ + +# [0.68.0](https://github.com/ipfs/interface-ipfs-core/compare/v0.67.0...v0.68.0) (2018-06-18) + + +### Bug Fixes + +* improve bitswap wantlist and unwant docs ([7737546](https://github.com/ipfs/interface-ipfs-core/commit/7737546)) +* linting errors ([fcc834c](https://github.com/ipfs/interface-ipfs-core/commit/fcc834c)) +* removes duplicated TOC for pubsub ([a358cf7](https://github.com/ipfs/interface-ipfs-core/commit/a358cf7)) + + +### Features + +* add bitswap.unwant javascript spec ([df4e677](https://github.com/ipfs/interface-ipfs-core/commit/df4e677)) +* add bitswap.unwant javascript spec ([d75a361](https://github.com/ipfs/interface-ipfs-core/commit/d75a361)) +* add bitswap.unwant javascript spec ([c291ca9](https://github.com/ipfs/interface-ipfs-core/commit/c291ca9)) +* add peerId param to bitswap.wantlist ([9f81bcb](https://github.com/ipfs/interface-ipfs-core/commit/9f81bcb)) + + + # [0.67.0](https://github.com/ipfs/interface-ipfs-core/compare/v0.66.4...v0.67.0) (2018-06-04) diff --git a/SPEC/BITSWAP.md b/SPEC/BITSWAP.md index 00bc5fc1..28949c00 100644 --- a/SPEC/BITSWAP.md +++ b/SPEC/BITSWAP.md @@ -4,13 +4,58 @@ * [bitswap.unwant](#bitswapunwant) * [bitswap.stat](#bitswapstat) -#### `bitswap.wantlist` +#### `bitswap.unwant` -(not spec'ed yet) +> Removes a given block from your wantlist -#### `bitswap.unwant` +##### `Go` **WIP** + +##### `JavaScript` - ipfs.bitswap.unwant(cid, [callback]) + +`cid` is a [cid][cid] which can be passed as: + +- CID, a CID instance +- String, the base58 encoded version of the multihash + +`callback` must follow `function (err) {}` signature, where `err` is an error if the operation was not successful. + + **Example:** + + ```JavaScript + ipfs.bitswap.unwant('QmSoLSafTMBsPKadTEgaXctDQVcqN88CNLHXMkTNwMKPnu', (err) => { + if (err) throw err + console.log('Done') + }) + ``` + +##### `Go` **WIP** + +### `bitswap.wantlist` + +> Returns the wantlist, optionally filtered by peer ID -(not spec'ed yet) +#### `Go` **WIP** + +#### `JavaScript` - ipfs.bitswap.wantlist([peerId], [callback]) + +`callback` must follow `function (err, list) {}` signature, where `err` is an error if the operation was not successful. `list` is an Object containing the following keys: + +- `Keys` An array of objects containing the following keys: + - `/` A string multihash + +If no `callback` is passed, a promise is returned. + +**Example:** + +```JavaScript +ipfs.bitswap.wantlist((err, list) => console.log(list)) + +// { Keys: [{ '/': 'QmHash' }] } + +ipfs.bitswap.wantlist(peerId, (err, list) => console.log(list)) + +// { Keys: [{ '/': 'QmHash' }] } +``` #### `bitswap.stat` diff --git a/SPEC/FILES.md b/SPEC/FILES.md index c1308df2..7427701d 100644 --- a/SPEC/FILES.md +++ b/SPEC/FILES.md @@ -56,6 +56,7 @@ If no `content` is passed, then the path is treated as an empty directory - hashAlg || hash (string): multihash hashing algorithm to use. - wrapWithDirectory (boolean): adds a wrapping node around the content. - onlyHash (boolean): doesn't actually add the file to IPFS, but rather calculates its hash. +- pin (boolean, default true): pin this object when adding. `callback` must follow `function (err, res) {}` signature, where `err` is an error if the operation was not successful. `res` will be an array of: @@ -109,6 +110,7 @@ Returns a Readable Stream of class Duplex, where objects can be written of the f - progress (function): a function that will be called with the byte length of chunks as a file is added to ipfs. - hashAlg || hash (string): multihash hashing algorithm to use - wrapWithDirectory (boolean): adds a wrapping node around the content +- pin (boolean, default true): pin this object when adding. **Example:** @@ -158,6 +160,7 @@ Returns a Pull Stream, where objects can be written of the forms - progress (function): a function that will be called with the byte length of chunks as a file is added to ipfs. - hashAlg || hash (string): multihash hashing algorithm to use - wrapWithDirectory (boolean): adds a wrapping node around the content +- pin (boolean, default true): pin this object when adding. **Example:** @@ -590,28 +593,56 @@ A great source of [examples][] can be found in the tests for this API. The Mutable File System (MFS) is a virtual file system on top of IPFS that exposes a Unix like API over a virtual directory. It enables users to write and read from paths without having to worry about updating the graph. It enables things like [ipfs-blob-store](https://github.com/ipfs/ipfs-blob-store) to exist. - #### `files.cp` > Copy files. ##### `Go` **WIP** -##### `JavaScript` - ipfs.files.cp([from, to], [callback]) +##### `JavaScript` - ipfs.files.cp(...from, to, [options], [callback]) Where: -- `from` is the path of the source file to copy. -- `to` is the path of the destination file to copy to. +- `from` is the path(s) of the source to copy. It might be: + - An existing MFS path to a file or a directory (e.g. `/my-dir/my-file.txt`) + - An IPFS path (e.g. `/ipfs/QmWGeRAEgtsHW3ec7U4qW2CyVy7eA2mFRVbk1nb24jFyks`) +- `to` is the path of the destination to copy to +- `options` is an optional Object that might contain the following keys: + - `parents` is a Boolean value to decide whether or not to make the parent directories if they don't exist (default: false) + - `format` is what type of nodes to write any newly created directories as (default: `dag-pb`) + - `hashAlg` is which algorithm to use when creating CIDs for newly created directories (default: `sha2-256`) + - `flush` is a Boolean value to decide whether or not to immediately flush MFS changes to disk (default: true) +- `callback` is an optional function with the signature `function (error) {}`, where `error` may be an Error that occured if the operation was not successful + +If `from` has multiple values then `to` must be a directory. -`callback` must follow the `function (err) {}` signature, where `err` is an Error if the operation was not successful. +If `from` has a single value and `to` exists and is a directory, `from` will be copied into `to`. + +If `from` has a single value and `to` exists and is a file, `from` must be a file and the contents of `to` will be replaced with the contents of `from` otherwise an error will be returned. + +If `from` is an IPFS path, and an MFS path exists with the same name, the IPFS path will be chosen. If no `callback` is passed, a promise is returned. **Example:** ```JavaScript -ipfs.files.cp(['/src-file', '/dst-file'], (err) => { +// To copy a file +ipfs.files.cp('/src-file', '/dst-file', (err) => { + if (err) { + console.error(err) + } +}) + +// To copy a directory +ipfs.files.cp('/src-dir', '/dst-dir', (err) => { + if (err) { + console.error(err) + } +}) + +// To copy multiple files to a directory +ipfs.files.cp('/src-file1', '/src-file2', '/dst-dir', (err) => { if (err) { console.error(err) } @@ -624,15 +655,17 @@ ipfs.files.cp(['/src-file', '/dst-file'], (err) => { ##### `Go` **WIP** -##### `JavaScript` - ipfs.files.mkdir(path, [options, callback]) +##### `JavaScript` - ipfs.files.mkdir(path, [options], [callback]) Where: -- `path` is the path to the directory to make. +- `path` is the path to the directory to make - `options` is an optional Object that might contain the following keys: - - `parents` is a Boolean value to decide whether or not to make the parent directories if they don't exist. - -`callback` must follow the `function (err) {}` signature, where `err` is an Error if the operation was not successful. + - `parents` is a Boolean value to decide whether or not to make the parent directories if they don't exist (default: false) + - `format` is what type of nodes to write any newly created directories as (default: `dag-pb`) + - `hashAlg` is which algorithm to use when creating CIDs for newly created directories (default: `sha2-256`) + - `flush` is a Boolean value to decide whether or not to immediately flush MFS changes to disk (default: true) +- `callback` is an optional function with the signature `function (error) {}`, where `error` may be an Error that occured if the operation was not successful If no `callback` is passed, a promise is returned. @@ -652,27 +685,25 @@ ipfs.files.mkdir('/my/beautiful/directory', (err) => { ##### `Go` **WIP** -##### `JavaScript` - ipfs.files.stat(path, [options, callback]) +##### `JavaScript` - ipfs.files.stat(path, [options], [callback]) Where: -- `path` is the path to the directory to stat. +- `path` is the path to the file or directory to stat - `options` is an optional Object that might contain the following keys: - - `hash` is a Boolean value to return only the hash. - - `size` is a Boolean value to return only the size. - - `withLocal` is a Boolean value to compute the amount of the dag that is local, and if possible the total size. - -`callback` must follow the `function (err, stat) {}` signature, where `err` is an Error if the operation was not successful and `stat` is an Object with the following keys: - -- `hash` is a string with the hash. -- `size` is an integer with the size in Bytes. -- `cumulativeSize` is an integer with the cumulative size in Bytes. -- `blocks` is an integer indicating the number of blocks. -- `type` is a string that can be either `directory` or `file`. -- `withLocality` is a boolean to indicate if locality information are present. -- `local` is a boolean to indicate if the queried dag is fully present locally. -- `sizeLocal` is an integer indicating the cumulative size of the data present locally. - + - `hash` is a Boolean value to return only the hash (default: false) + - `size` is a Boolean value to return only the size (default: false) + - `withLocal` is a Boolean value to compute the amount of the dag that is local, and if possible the total size (default: false) +- `callback` is an optional function with the signature `function (error, stats) {}`, where `error` may be an Error that occured if the operation was not successful and `stats` is an Object with the following keys: + +- `hash` is a string with the hash +- `size` is an integer with the file size in Bytes +- `cumulativeSize` is an integer with the size of the DAGNodes making up the file in Bytes +- `type` is a string that can be either `directory` or `file` +- `blocks` if `type` is `directory`, this is the number of files in the directory. If it is `file` it is the number of blocks that make up the file +- `withLocality` is a boolean to indicate if locality information are present +- `local` is a boolean to indicate if the queried dag is fully present locally +- `sizeLocal` is an integer indicating the cumulative size of the data present locally If no `callback` is passed, a promise is returned. @@ -698,15 +729,14 @@ ipfs.files.stat('/file.txt', (err, stats) => { ##### `Go` **WIP** -##### `JavaScript` - ipfs.files.rm(path, [options, callback]) +##### `JavaScript` - ipfs.files.rm(...paths, [options], [callback]) Where: -- `path` is the path of the file to remove. +- `paths` are one or more paths to remove - `options` is an optional Object that might contain the following keys: - - `recursive` is a Boolean value to decide whether or not to remove directories recursively. - -`callback` must follow the `function (err) {}` signature, where `err` is an Error if the operation was not successful. + - `recursive` is a Boolean value to decide whether or not to remove directories recursively (default: false) +- `callback` is an optional function with the signature `function (error) {}`, where `error` may be an Error that occured if the operation was not successful If no `callback` is passed, a promise is returned. @@ -720,6 +750,13 @@ ipfs.files.rm('/my/beautiful/file.txt', (err) => { } }) +// To remove multiple files +ipfs.files.rm('/my/beautiful/file.txt', '/my/other/file.txt', (err) => { + if (err) { + console.error(err) + } +}) + // To remove a directory ipfs.files.rm('/my/beautiful/directory', { recursive: true }, (err) => { if (err) { @@ -738,19 +775,20 @@ ipfs.files.rm('/my/beautiful/directory', { recursive: true }, (err) => { Where: -- `path` is the path of the file to read. +- `path` is the path of the file to read and must point to a file (and not a directory) - `options` is an optional Object that might contain the following keys: - - `offset` is an Integer with the byte offset to begin reading from. - - `count` is an Integer with the maximum number of bytes to read. - -`callback` must follow the `function (err, buf) {}` signature, where `err` is an Error if the operation was not successful and `buf` is a [`Buffer`][b] with the contents of `path`. + - `offset` is an Integer with the byte offset to begin reading from (default: 0) + - `length` is an Integer with the maximum number of bytes to read (default: Read to end of stream) +- `callback` is an optional function with the signature `function (error, buffer) {}`, where `error` may be an Error that occured if the operation was not successful and `buffer` is a [`Buffer`][b] with the contents of `path` If no `callback` is passed, a promise is returned. +N.b. this method is likely to result in high memory usage, you should use [files.readReadableStream](#filesreadreadablestream) or [files.readPullStream](#filesreadpullstream) instead where possible. + **Example:** ```JavaScript -ipfs.files.read('/hello-world', (err, buf) => { +ipfs.files.read('/hello-world', (error, buf) => { console.log(buf.toString('utf8')) }) @@ -767,10 +805,10 @@ ipfs.files.read('/hello-world', (err, buf) => { Where: -- `path` is the path of the file to read. +- `path` is the path of the file to read and must point to a file (and not a directory) - `options` is an optional Object that might contain the following keys: - - `offset` is an Integer with the byte offset to begin reading from. - - `count` is an Integer with the maximum number of bytes to read. + - `offset` is an Integer with the byte offset to begin reading from (default: 0) + - `length` is an Integer with the maximum number of bytes to read (default: Read to end of stream) Returns a [`ReadableStream`][rs] with the contents of `path`. @@ -793,10 +831,10 @@ stream.on('data', (buf) => console.log(buf.toString('utf8'))) Where: -- `path` is the path of the file to read. +- `path` is the path of the file to read and must point to a file (and not a directory) - `options` is an optional Object that might contain the following keys: - - `offset` is an Integer with the byte offset to begin reading from. - - `count` is an Integer with the maximum number of bytes to read. + - `offset` is an Integer with the byte offset to begin reading from (default: 0) + - `length` is an Integer with the maximum number of bytes to read (default: Read to end of stream) Returns a [`PullStream`][ps] with the contents of `path`. @@ -818,11 +856,11 @@ pull( ##### `Go` **WIP** -##### `JavaScript` - ipfs.files.write(path, content, [options, callback]) +##### `JavaScript` - ipfs.files.write(path, content, [options], [callback]) Where: -- `path` is the path of the file to write. +- `path` is the path of the file to write - `content` can be: - a [`Buffer`][b] - a [`PullStream`][ps] @@ -830,12 +868,11 @@ Where: - a [`Blob`][blob] (caveat: will only work in the browser) - a string path to a file (caveat: will only work in Node.js) - `options` is an optional Object that might contain the following keys: - - `offset` is an Integer with the byte offset to begin writing at. - - `create` is a Boolean to indicate to create the file if it doesn't exist. - - `truncate` is a Boolean to indicate if the file should be truncated to size 0 before writing. - - `count` is an Integer with the maximum number of bytes to read. - -`callback` must follow the `function (err) {}` signature, where `err` is an Error if the operation was not successful. + - `offset` is an Integer with the byte offset to begin writing at (default: 0) + - `create` is a Boolean to indicate to create the file if it doesn't exist (default: false) + - `truncate` is a Boolean to indicate if the file should be truncated after writing all the bytes from `content` (default: false) + - `length` is an Integer with the maximum number of bytes to read (default: Read all bytes from `content`) +- `callback` is an optional function with the signature `function (error) {}`, where `error` may be an Error that occured if the operation was not successful If no `callback` is passed, a promise is returned. @@ -853,21 +890,47 @@ ipfs.files.write('/hello-world', Buffer.from('Hello, world!'), (err) => { ##### `Go` **WIP** -##### `JavaScript` - ipfs.files.mv([from, to], [callback]) +##### `JavaScript` - ipfs.files.mv(...from, to, [options], [callback]) Where: -- `from` is the path of the source file to move. -- `to` is the path of the destination file to move to. +- `from` is the path(s) of the source to move +- `to` is the path of the destination to move to +- `options` is an optional Object that might contain the following keys: + - `parents` is a Boolean value to decide whether or not to make the parent directories if they don't exist (default: false) + - `format` is what type of nodes to write any newly created directories as (default: `dag-pb`) + - `hashAlg` is which algorithm to use when creating CIDs for newly created directories (default: `sha2-256`) + - `flush` is a Boolean value to decide whether or not to immediately flush MFS changes to disk (default: true) +- `callback` is an optional function with the signature `function (error) {}`, where `error` may be an Error that occured if the operation was not successful + +If `from` has multiple values then `to` must be a directory. + +If `from` has a single value and `to` exists and is a directory, `from` will be moved into `to`. + +If `from` has a single value and `to` exists and is a file, `from` must be a file and the contents of `to` will be replaced with the contents of `from` otherwise an error will be returned. -`callback` must follow the `function (err) {}` signature, where `err` is an Error if the operation was not successful. +If `from` is an IPFS path, and an MFS path exists with the same name, the IPFS path will be chosen. + +All values of `from` will be removed after the operation is complete, unless they are an IPFS path. If no `callback` is passed, a promise is returned. **Example:** ```JavaScript -ipfs.files.mv(['/src-file', '/dst-file'], (err) => { +ipfs.files.mv('/src-file', '/dst-file', (err) => { + if (err) { + console.error(err) + } +}) + +ipfs.files.mv('/src-dir', '/dst-dir', (err) => { + if (err) { + console.error(err) + } +}) + +ipfs.files.mv('/src-file1', '/src-file2', '/dst-dir', (err) => { if (err) { console.error(err) } @@ -880,13 +943,12 @@ ipfs.files.mv(['/src-file', '/dst-file'], (err) => { ##### `Go` **WIP** -##### `JavaScript` - ipfs.files.flush([path, callback]) +##### `JavaScript` - ipfs.files.flush([...paths], [callback]) Where: -- `path` is the path to flush. Default is `/`. - -`callback` must follow the `function (err) {}` signature, where `err` is an Error if the operation was not successful. +- `paths` are an optional string paths to flush (default: `/`) +- `callback` is an optional function with the signature `function (error) {}`, where `error` may be an Error that occured if the operation was not successful If no `callback` is passed, a promise is returned. @@ -906,20 +968,17 @@ ipfs.files.flush('/', (err) => { ##### `Go` **WIP** -##### `JavaScript` - ipfs.files.ls([path, options, callback]) +##### `JavaScript` - ipfs.files.ls([path], [callback]) Where: -- `path` is the path to show listing for. Defaults to `/`. -- `options` is an optional Object that might contain the following keys: - - `l` is a Boolean value o use long listing format. - -`callback` must follow `function (err, files) {}` signature, where `err` is an error if the operation was not successful. `files` is an array containing Objects that contain the following keys: +- `path` is an optional string to show listing for (default: `/`) +- `callback` is an optional function with the signature `function (error, files) {}`, where `error` may be an Error that occured if the operation was not successful and `files` is an array containing Objects that contain the following keys: -- `name` which is the file's name. -- `type` which i the object's type (`directory` or `file`). -- `size` the size of the file in bytes. -- `hash` the hash of the file. +- `name` which is the file's name +- `type` which i the object's type (`directory` or `file`) +- `size` the size of the file in bytes +- `hash` the hash of the file If no `callback` is passed, a promise is returned. diff --git a/SPEC/PIN.md b/SPEC/PIN.md index bc0aeeb1..1f27b140 100644 --- a/SPEC/PIN.md +++ b/SPEC/PIN.md @@ -16,7 +16,7 @@ Where: - `hash` is an IPFS multihash. - `options` is an object that can contain the following keys - - 'recursive' - Recursively pin the object linked. Type: bool. Default: `false` + - 'recursive' - Recursively pin the object linked. Type: bool. Default: `true` `callback` must follow `function (err, res) {}` signature, where `err` is an error if the operation was not successful. `res` is an array of objects that represent the files that were pinned. Example: @@ -76,7 +76,7 @@ A great source of [examples][] can be found in the tests for this API. Where: - `hash` is a multihash. - `options` is an object that can contain the following keys - - 'recursive' - Recursively unpin the object linked. Type: bool. Default: `false` + - 'recursive' - Recursively unpin the object linked. Type: bool. Default: `true` `callback` must follow `function (err) {}` signature, where `err` is an error if the operation was not successful. diff --git a/SPEC/PUBSUB.md b/SPEC/PUBSUB.md index 5e20cd97..5fd8e9c2 100644 --- a/SPEC/PUBSUB.md +++ b/SPEC/PUBSUB.md @@ -6,12 +6,6 @@ * [pubsub.ls](#pubsubls) * [pubsub.peers](#pubsubpeers) -* [pubsub.subscribe](#pubsubsubscribe) -* [pubsub.unsubscribe](#pubsubunsubscribe) -* [pubsub.publish](#pubsubpublish) -* [pubsub.ls](#pubsubls) -* [pubsub.peers](#pubsubpeers) - #### `pubsub.subscribe` > Subscribe to a pubsub topic. @@ -108,7 +102,7 @@ If no `callback` is passed, a promise is returned. ```JavaScript const topic = 'fruit-of-the-day' -const msg = new Buffer('banana') +const msg = Buffer.from('banana') ipfs.pubsub.publish(topic, msg, (err) => { if (err) { diff --git a/js/src/bitswap.js b/js/src/bitswap.js new file mode 100644 index 00000000..0999e9da --- /dev/null +++ b/js/src/bitswap.js @@ -0,0 +1,159 @@ +/* eslint-env mocha */ +'use strict' + +const chai = require('chai') +const dirtyChai = require('dirty-chai') +const series = require('async/series') +const expect = chai.expect +const statsTests = require('./utils/stats') +const spawn = require('./utils/spawn') +chai.use(dirtyChai) +const CID = require('cids') + +module.exports = (common) => { + describe('.bitswap online', () => { + let ipfsA + let ipfsB + let withGo + let ipfsBId + const key = 'QmUBdnXXPyoDFXj3Hj39dNJ5VkN3QFRskXxcGaYFBB8CNR' + + before(function (done) { + // CI takes longer to instantiate the daemon, so we need to increase the + // timeout for the before step + this.timeout(60 * 250) + + common.setup((err, factory) => { + expect(err).to.not.exist() + series([ + (cb) => spawn.spawnNodeWithId(factory, (err, node) => { + expect(err).to.not.exist() + ipfsA = node + withGo = node.peerId.agentVersion.startsWith('go-ipfs') + cb() + }), + (cb) => spawn.spawnNodeWithId(factory, (err, node) => { + expect(err).to.not.exist() + ipfsB = node + ipfsBId = node.peerId + ipfsB.block.get(new CID(key)) + .then(() => {}) + .catch(() => {}) + ipfsA.swarm.connect(ipfsBId.addresses[0], (err) => { + expect(err).to.not.exist() + setTimeout(cb, 350) + }) + }) + ], done) + }) + }) + + after((done) => common.teardown(done)) + + it('.stat', (done) => { + ipfsB.bitswap.stat((err, stats) => { + expect(err).to.not.exist() + statsTests.expectIsBitswap(err, stats) + done() + }) + }) + + it('.wantlist', (done) => { + ipfsB.bitswap.wantlist((err, list) => { + expect(err).to.not.exist() + expect(list.Keys).to.have.length(1) + expect(list.Keys[0]['/']).to.equal(key) + done() + }) + }) + + it('.wantlist peerid', (done) => { + ipfsA.bitswap.wantlist(ipfsBId.id, (err, list) => { + expect(err).to.not.exist() + expect(list.Keys[0]['/']).to.equal(key) + done() + }) + }) + + it('.unwant', function (done) { + if (withGo) { + this.skip() + } + ipfsB.bitswap.unwant(key, (err) => { + expect(err).to.not.exist() + ipfsB.bitswap.wantlist((err, list) => { + expect(err).to.not.exist() + expect(list.Keys).to.be.empty() + done() + }) + }) + }) + }) + + describe('.bitswap offline', () => { + let ipfs + + before(function (done) { + // CI takes longer to instantiate the daemon, so we need to increase the + // timeout for the before step + this.timeout(60 * 1000) + + common.setup((err, factory) => { + expect(err).to.not.exist() + factory.spawnNode((err, node) => { + expect(err).to.not.exist() + ipfs = node + ipfs.id((err, id) => { + expect(err).to.not.exist() + ipfs.stop((err) => { + // TODO: go-ipfs returns an error, https://github.com/ipfs/go-ipfs/issues/4078 + if (!id.agentVersion.startsWith('go-ipfs')) { + expect(err).to.not.exist() + } + done() + }) + }) + }) + }) + }) + + it('.stat gives error while offline', (done) => { + ipfs.bitswap.stat((err, stats) => { + expect(err).to.exist() + // When run against core we get our expected error, when run + // as part of the http tests we get a connection refused + if (err.code !== 'ECONNREFUSED') { + expect(err).to.match(/online mode/) + } + expect(stats).to.not.exist() + done() + }) + }) + + it('.wantlist gives error if offline', (done) => { + ipfs.bitswap.wantlist((err, list) => { + expect(err).to.exist() + // When run against core we get our expected error, when run + // as part of the http tests we get a connection refused + if (err.code !== 'ECONNREFUSED') { + expect(err).to.match(/online mode/) + } + expect(list).to.not.exist() + done() + }) + }) + + it('.unwant gives error if offline', (done) => { + const key = 'QmUBdnXXPyoDFXj3Hj39dNJ5VkN3QFRskXxcGaYFBB8CNR' + ipfs.bitswap.unwant(key, (err) => { + expect(err).to.exist() + // When run against core we get our expected error, when run + // as part of the http tests we get a connection refused + if (err.code !== 'ECONNREFUSED') { + expect(err).to.match(/online mode/) + } + done() + }) + }) + }) +} diff --git a/js/src/index.js b/js/src/index.js index dd2012e9..07904c43 100644 --- a/js/src/index.js +++ b/js/src/index.js @@ -19,3 +19,4 @@ exports.repo = require('./repo') exports.bootstrap = require('./bootstrap') exports.types = require('./types') exports.util = require('./util') +exports.bitswap = require('./bitswap') diff --git a/package.json b/package.json index 1aca264b..ddd94073 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "interface-ipfs-core", - "version": "0.67.0", + "version": "0.68.0", "description": "A test suite and interface you can use to implement a IPFS core interface.", "leadMaintainer": "Alan Shaw ", "main": "js/src/index.js", @@ -65,9 +65,12 @@ "Haad ", "Henrique Dias ", "Jacob Heun ", + "Jacob Karlsson ", "Jason Papakostas ", "Joel Gustafson ", + "Jonathan ", "Kevin Simper ", + "Maciej Krüger ", "Marius Darila ", "Matt Zumwalt ", "Michael Garvin ",