diff --git a/CHANGELOG.md b/CHANGELOG.md
index 13b6e5294..f0a01abc2 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,19 @@
+
+## [0.65.9](https://github.com/ipfs/interface-ipfs-core/compare/v0.65.8...v0.65.9) (2018-05-16)
+
+
+### Bug Fixes
+
+* add "files." to read* headers ([8b39b12](https://github.com/ipfs/interface-ipfs-core/commit/8b39b12))
+* linting warnings ([aae31b0](https://github.com/ipfs/interface-ipfs-core/commit/aae31b0))
+
+
+### Features
+
+* add utils to spawn multiple nodes and get their ID ([e77a2f6](https://github.com/ipfs/interface-ipfs-core/commit/e77a2f6))
+
+
+
## [0.65.8](https://github.com/ipfs/interface-ipfs-core/compare/v0.65.7...v0.65.8) (2018-05-15)
diff --git a/SPEC/FILES.md b/SPEC/FILES.md
index bd97ba3d5..b339d806f 100644
--- a/SPEC/FILES.md
+++ b/SPEC/FILES.md
@@ -19,6 +19,8 @@
* [files.stat](#filesmkdir)
* [files.rm](#filesrm)
* [files.read](#filesread)
+* [files.readReadableStream](#filesreadreadablestream)
+* [files.readPullStream](#filesreadpullstream)
* [files.write](#fileswrite)
* [files.mv](#filesmv)
* [files.flush](#filesflush)
@@ -599,8 +601,8 @@ The Mutable File System (MFS) is a virtual file system on top of IPFS that expos
Where:
-- `from` is the path of the source object to copy.
-- `to` is the path of the destination object to copy to.
+- `from` is the path of the source file to copy.
+- `to` is the path of the destination file to copy to.
`callback` must follow the `function (err) {}` signature, where `err` is an Error if the operation was not successful.
@@ -700,7 +702,7 @@ ipfs.files.stat('/file.txt', (err, stats) => {
Where:
-- `path` is the path of the object to remove.
+- `path` is the path of the file 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.
@@ -728,20 +730,20 @@ ipfs.files.rm('/my/beautiful/directory', { recursive: true }, (err) => {
#### `files.read`
-> Read a file.
+> Read a file into a [`Buffer`][b].
##### `Go` **WIP**
-##### `JavaScript` - ipfs.files.read(path, [options, callback])
+##### `JavaScript` - ipfs.files.read(path, [options], [callback])
Where:
-- `path` is the path of the object to read.
+- `path` is the path of the file to read.
- `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 with the contents of `path`.
+`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`.
If no `callback` is passed, a promise is returned.
@@ -749,12 +751,67 @@ If no `callback` is passed, a promise is returned.
```JavaScript
ipfs.files.read('/hello-world', (err, buf) => {
- console.log(buf.toString())
+ console.log(buf.toString('utf8'))
})
// Hello, World!
```
+#### `files.readReadableStream`
+
+> Read a file into a [`ReadableStream`][rs].
+
+##### `Go` **WIP**
+
+##### `JavaScript` - ipfs.files.readReadableStream(path, [options])
+
+Where:
+
+- `path` is the path of the file to read.
+- `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.
+
+Returns a [`ReadableStream`][rs] with the contents of `path`.
+
+**Example:**
+
+```JavaScript
+const stream = ipfs.files.readReadableStream('/hello-world')
+stream.on('data', (buf) => console.log(buf.toString('utf8')))
+
+// Hello, World!
+```
+
+#### `files.readPullStream`
+
+> Read a file into a [`PullStream`][ps].
+
+##### `Go` **WIP**
+
+##### `JavaScript` - ipfs.files.readPullStream(path, [options])
+
+Where:
+
+- `path` is the path of the file to read.
+- `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.
+
+Returns a [`PullStream`][ps] with the contents of `path`.
+
+**Example:**
+
+```JavaScript
+pull(
+ ipfs.files.readPullStream('/hello-world'),
+ through(buf => console.log(buf.toString('utf8'))),
+ collect(err => {})
+)
+
+// Hello, World!
+```
+
#### `files.write`
> Write to a file.
@@ -765,10 +822,13 @@ ipfs.files.read('/hello-world', (err, buf) => {
Where:
-- `path` is the path of the object to write.
+- `path` is the path of the file to write.
- `content` can be:
- - a Buffer instance.
- - a Path (caveat: will only work in Node.js).
+ - a [`Buffer`][b]
+ - a [`PullStream`][ps]
+ - a [`ReadableStream`][rs]
+ - 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.
@@ -797,8 +857,8 @@ ipfs.files.write('/hello-world', Buffer.from('Hello, world!'), (err) => {
Where:
-- `from` is the path of the source object to move.
-- `to` is the path of the destination object to move to.
+- `from` is the path of the source file to move.
+- `to` is the path of the destination file to move to.
`callback` must follow the `function (err) {}` signature, where `err` is an Error if the operation was not successful.
@@ -881,3 +941,4 @@ ipfs.files.ls('/screenshots', function (err, files) {
[rs]: https://www.npmjs.com/package/readable-stream
[ps]: https://www.npmjs.com/package/pull-stream
[cid]: https://www.npmjs.com/package/cids
+[blob]: https://developer.mozilla.org/en-US/docs/Web/API/Blob
diff --git a/js/src/dag.js b/js/src/dag.js
index de74c1728..d337bd045 100644
--- a/js/src/dag.js
+++ b/js/src/dag.js
@@ -13,6 +13,7 @@ const dagPB = require('ipld-dag-pb')
const DAGNode = dagPB.DAGNode
const dagCBOR = require('ipld-dag-cbor')
const CID = require('cids')
+const { spawnNodeWithId } = require('./utils/spawn')
module.exports = (common) => {
describe('.dag', () => {
@@ -26,14 +27,12 @@ module.exports = (common) => {
common.setup((err, factory) => {
expect(err).to.not.exist()
- factory.spawnNode((err, node) => {
+
+ spawnNodeWithId(factory, (err, node) => {
expect(err).to.not.exist()
ipfs = node
- ipfs.id((err, id) => {
- expect(err).to.not.exist()
- withGo = id.agentVersion.startsWith('go-ipfs')
- done()
- })
+ withGo = node.peerId.agentVersion.startsWith('go-ipfs')
+ done()
})
})
})
diff --git a/js/src/dht.js b/js/src/dht.js
index d32595c6a..333d2a424 100644
--- a/js/src/dht.js
+++ b/js/src/dht.js
@@ -6,22 +6,9 @@ const dirtyChai = require('dirty-chai')
const expect = chai.expect
chai.use(dirtyChai)
const waterfall = require('async/waterfall')
-const series = require('async/series')
const parallel = require('async/parallel')
const CID = require('cids')
-
-function spawnWithId (factory, callback) {
- waterfall([
- (cb) => factory.spawnNode(cb),
- (node, cb) => node.id((err, peerId) => {
- if (err) {
- return cb(err)
- }
- node.peerId = peerId
- cb(null, node)
- })
- ], callback)
-}
+const { spawnNodesWithId } = require('./utils/spawn')
module.exports = (common) => {
describe('.dht', function () {
@@ -40,13 +27,8 @@ module.exports = (common) => {
common.setup((err, factory) => {
expect(err).to.not.exist()
- series([
- (cb) => spawnWithId(factory, cb),
- (cb) => spawnWithId(factory, cb),
- (cb) => spawnWithId(factory, cb),
- (cb) => spawnWithId(factory, cb),
- (cb) => spawnWithId(factory, cb)
- ], (err, nodes) => {
+
+ spawnNodesWithId(5, factory, (err, nodes) => {
expect(err).to.not.exist()
nodeA = nodes[0]
diff --git a/js/src/files-mfs.js b/js/src/files-mfs.js
index 948c5fc5e..2d8a07225 100644
--- a/js/src/files-mfs.js
+++ b/js/src/files-mfs.js
@@ -5,6 +5,7 @@
const chai = require('chai')
const dirtyChai = require('dirty-chai')
+const loadFixture = require('aegir/fixtures')
const expect = chai.expect
chai.use(dirtyChai)
@@ -477,8 +478,13 @@ module.exports = (common) => {
})
})
- // TODO (achingbrain) - Not yet supported in js-ipfs or go-ipfs yet')
+ // TODO: (achingbrain) - Not yet supported in js-ipfs or go-ipfs yet')
describe.skip('.stat', () => {
+ const smallFile = {
+ cid: 'Qma4hjFTnCasJ8PVp3mZbZK5g2vGDT4LByLJ7m8ciyRFZP',
+ data: loadFixture('js/test/fixtures/testfile.txt', 'interface-ipfs-core')
+ }
+
before((done) => ipfs.files.add(smallFile.data, done))
it.skip('stat outside of mfs', function (done) {
diff --git a/js/src/files.js b/js/src/files.js
index 884726132..ff8f3a961 100644
--- a/js/src/files.js
+++ b/js/src/files.js
@@ -32,11 +32,6 @@ module.exports = (common) => {
return loadFixture(path, 'interface-ipfs-core')
}
- const wrapDirectory = {
- path: 'wrapper/',
- cid: 'QmbzKtHxQXJnWG9VR66TscUfcoK3CV4nceRsCdyAEsEj9A'
- }
-
const smallFile = {
cid: 'Qma4hjFTnCasJ8PVp3mZbZK5g2vGDT4LByLJ7m8ciyRFZP',
data: fixture('js/test/fixtures/testfile.txt')
@@ -339,11 +334,11 @@ module.exports = (common) => {
it('files.add with only-hash=true', () => {
this.slow(10 * 1000)
const content = String(Math.random() + Date.now())
-
+
return ipfs.files.add(Buffer.from(content), { onlyHash: true })
.then(files => {
expect(files).to.have.length(1)
-
+
// 'ipfs.object.get()' should timeout because content wasn't actually added
return expectTimeout(ipfs.object.get(files[0].hash), 4000)
})
diff --git a/js/src/index.js b/js/src/index.js
index 881e50145..7db37eb54 100644
--- a/js/src/index.js
+++ b/js/src/index.js
@@ -17,3 +17,4 @@ exports.stats = require('./stats')
exports.repo = require('./repo')
exports.bootstrap = require('./bootstrap')
exports.types = require('./types')
+exports.util = require('./util')
diff --git a/js/src/key.js b/js/src/key.js
index 96109570b..11c11993e 100644
--- a/js/src/key.js
+++ b/js/src/key.js
@@ -8,6 +8,7 @@ const dirtyChai = require('dirty-chai')
const expect = chai.expect
chai.use(dirtyChai)
const hat = require('hat')
+const { spawnNodeWithId } = require('./utils/spawn')
module.exports = (common) => {
describe('.key', () => {
@@ -25,14 +26,11 @@ module.exports = (common) => {
common.setup((err, factory) => {
expect(err).to.not.exist()
- factory.spawnNode((err, node) => {
+ spawnNodeWithId(factory, (err, node) => {
expect(err).to.not.exist()
ipfs = node
- ipfs.id((err, id) => {
- expect(err).to.not.exist()
- withGo = id.agentVersion.startsWith('go-ipfs')
- done()
- })
+ withGo = node.peerId.agentVersion.startsWith('go-ipfs')
+ done()
})
})
})
diff --git a/js/src/miscellaneous.js b/js/src/miscellaneous.js
index abe804b59..7c3030435 100644
--- a/js/src/miscellaneous.js
+++ b/js/src/miscellaneous.js
@@ -7,6 +7,7 @@ const chai = require('chai')
const dirtyChai = require('dirty-chai')
const expect = chai.expect
chai.use(dirtyChai)
+const { spawnNodeWithId } = require('./utils/spawn')
module.exports = (common) => {
describe('.miscellaneous', () => {
@@ -20,14 +21,11 @@ module.exports = (common) => {
common.setup((err, factory) => {
expect(err).to.not.exist()
- factory.spawnNode((err, node) => {
+ spawnNodeWithId(factory, (err, node) => {
expect(err).to.not.exist()
ipfs = node
- ipfs.id((err, id) => {
- expect(err).to.not.exist()
- withGo = id.agentVersion.startsWith('go-ipfs')
- done()
- })
+ withGo = node.peerId.agentVersion.startsWith('go-ipfs')
+ done()
})
})
})
diff --git a/js/src/pubsub.js b/js/src/pubsub.js
index b4c40c551..a877073e5 100644
--- a/js/src/pubsub.js
+++ b/js/src/pubsub.js
@@ -8,10 +8,10 @@ const expect = chai.expect
chai.use(dirtyChai)
const series = require('async/series')
const each = require('async/each')
-const waterfall = require('async/waterfall')
const parallel = require('async/parallel')
const whilst = require('async/whilst')
const hat = require('hat')
+const { spawnNodesWithId } = require('./utils/spawn')
// On Browsers it will be false, but the tests currently aren't run
// there anyway
@@ -36,19 +36,6 @@ function waitForPeers (ipfs, topic, peersToWait, callback) {
}, 500)
}
-function spawnWithId (factory, callback) {
- waterfall([
- (cb) => factory.spawnNode(cb),
- (node, cb) => node.id((err, res) => {
- if (err) {
- return cb(err)
- }
- node.peerId = res
- cb(null, node)
- })
- ], callback)
-}
-
function makeCheck (n, done) {
let i = 0
return (err) => {
@@ -83,11 +70,7 @@ module.exports = (common) => {
return done(err)
}
- series([
- (cb) => spawnWithId(factory, cb),
- (cb) => spawnWithId(factory, cb),
- (cb) => spawnWithId(factory, cb)
- ], (err, nodes) => {
+ spawnNodesWithId(3, factory, (err, nodes) => {
if (err) {
return done(err)
}
diff --git a/js/src/stats.js b/js/src/stats.js
index df9cf1e72..83441e024 100644
--- a/js/src/stats.js
+++ b/js/src/stats.js
@@ -13,7 +13,6 @@ chai.use(dirtyChai)
module.exports = (common) => {
describe('.stats', () => {
let ipfs
- let withGo
before(function (done) {
// CI takes longer to instantiate the daemon, so we need to increase the
@@ -25,11 +24,7 @@ module.exports = (common) => {
factory.spawnNode((err, node) => {
expect(err).to.not.exist()
ipfs = node
- node.id((err, id) => {
- expect(err).to.not.exist()
- withGo = id.agentVersion.startsWith('go-ipfs')
- done()
- })
+ done()
})
})
})
diff --git a/js/src/swarm.js b/js/src/swarm.js
index 45284b448..5905412c3 100644
--- a/js/src/swarm.js
+++ b/js/src/swarm.js
@@ -13,6 +13,7 @@ const PeerId = require('peer-id')
const os = require('os')
const path = require('path')
const hat = require('hat')
+const { spawnNodes } = require('./utils/spawn')
module.exports = (common) => {
describe('.swarm', function () {
@@ -30,18 +31,13 @@ module.exports = (common) => {
common.setup((err, factory) => {
expect(err).to.not.exist()
factoryInstance = factory
- series([
- (cb) => factory.spawnNode((err, node) => {
- expect(err).to.not.exist()
- ipfsA = node
- cb()
- }),
- (cb) => factory.spawnNode((err, node) => {
- expect(err).to.not.exist()
- ipfsB = node
- cb()
- })
- ], done)
+
+ spawnNodes(2, factory, (err, nodes) => {
+ expect(err).to.not.exist()
+ ipfsA = nodes[0]
+ ipfsB = nodes[1]
+ done()
+ })
})
})
diff --git a/js/src/util.js b/js/src/util.js
index 7e884d711..b64ef2b3c 100644
--- a/js/src/util.js
+++ b/js/src/util.js
@@ -3,38 +3,39 @@
const crypto = require('libp2p-crypto')
const isIPFS = require('is-ipfs')
-
const chai = require('chai')
const dirtyChai = require('dirty-chai')
const expect = chai.expect
chai.use(dirtyChai)
-describe('.types', function () {
- let ipfs
+module.exports = (common) => {
+ describe('.util', function () {
+ 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)
+ 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) => {
+ common.setup((err, factory) => {
expect(err).to.not.exist()
- ipfs = node
- done()
+ factory.spawnNode((err, node) => {
+ expect(err).to.not.exist()
+ ipfs = node
+ done()
+ })
})
})
- })
- after((done) => {
- common.teardown(done)
- })
+ after((done) => {
+ common.teardown(done)
+ })
- it('util object', () => {
- expect(ipfs.util).to.be.deep.equal({
- crypto: crypto,
- isIPFS: isIPFS
+ it('util object', () => {
+ expect(ipfs.util).to.be.deep.equal({
+ crypto: crypto,
+ isIPFS: isIPFS
+ })
})
})
-})
+}
diff --git a/js/src/utils/spawn.js b/js/src/utils/spawn.js
new file mode 100644
index 000000000..877011ebb
--- /dev/null
+++ b/js/src/utils/spawn.js
@@ -0,0 +1,30 @@
+const waterfall = require('async/waterfall')
+const times = require('async/times')
+
+// Spawn a node, get it's id and set it as `peerId` on the node
+function spawnNodeWithId (factory, callback) {
+ waterfall([
+ (cb) => factory.spawnNode(cb),
+ (node, cb) => node.id((err, id) => {
+ if (err) return cb(err)
+ node.peerId = id
+ cb(null, node)
+ })
+ ], callback)
+}
+
+exports.spawnNodeWithId = spawnNodeWithId
+
+// Spawn n nodes
+function spawnNodes (n, factory, callback) {
+ times(n, (_, cb) => factory.spawnNode(cb), callback)
+}
+
+exports.spawnNodes = spawnNodes
+
+// Spawn n nodes, getting their id's and setting them as `peerId` on the nodes
+function spawnNodesWithId (n, factory, callback) {
+ times(n, (_, cb) => spawnNodeWithId(factory, cb), callback)
+}
+
+exports.spawnNodesWithId = spawnNodesWithId
diff --git a/js/src/utils/stats.js b/js/src/utils/stats.js
index 24440a71b..d9c56f07c 100644
--- a/js/src/utils/stats.js
+++ b/js/src/utils/stats.js
@@ -3,7 +3,6 @@
'use strict'
-const Big = require('big.js')
const { expect } = require('chai')
const isBigInt = (n) => {
diff --git a/package.json b/package.json
index 351c93bb2..bd4ec908c 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "interface-ipfs-core",
- "version": "0.65.8",
+ "version": "0.65.9",
"description": "A test suite and interface you can use to implement a IPFS core interface.",
"leadMaintainer": "Alan Shaw ",
"main": "js/src/index.js",
@@ -57,7 +57,6 @@
"devDependencies": {},
"contributors": [
"Alan Shaw ",
- "Alex Potsides ",
"David Dias ",
"Dmitriy Ryajov ",
"Enrico Marino ",
@@ -83,6 +82,7 @@
"Thiago Delgado ",
"Vasco Santos ",
"Volker Mische ",
+ "achingbrain ",
"greenkeeperio-bot ",
"haad ",
"kumavis ",