diff --git a/.travis.yml b/.travis.yml index d86ec626d..c2e95ab4f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,7 +11,7 @@ before_install: script: - npm run lint - - npm test + - npm run test:node - npm run coverage addons: diff --git a/API.md b/API.md deleted file mode 100644 index b700119ee..000000000 --- a/API.md +++ /dev/null @@ -1,204 +0,0 @@ - - -**Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)* - -- [API Reference](#api-reference) - - [Core](#core) - - [`version([callback])`](#versioncallback) - - [`id([callback])`](#idcallback) - - [`block`](#block) - - [`block.put(buffer, [callback])`](#blockputbuffer-callback) - - [`block.get(hash, [callback])`](#blockgethash-callback) - - [`block.stat(hash, [callback])`](#blockstathash-callback) - - [`object`](#object) - - [`object.put(buffer, encoding, [callback])`](#objectputbuffer-encoding-callback) - - [`object.get(hash, [callback])`](#objectgethash-callback) - - [`object.data(hash, [callback])`](#objectdatahash-callback) - - [`object.stat(hash, [callback])`](#objectstathash-callback) - - [`object.links(hash, [callback])`](#objectlinkshash-callback) - - [`object.new(hash, [callback])`](#objectnewhash-callback) - - [`object.patch`](#objectpatch) - - [`object.patch.addLink(hash, name, ref, [callback])`](#objectpatchaddlinkhash-name-ref-callback) - - [`object.patch.rmLink(hash, name, [callback])`](#objectpatchrmlinkhash-name-callback) - - [`object.patch.setData(hash, data, [callback])`](#objectpatchsetdatahash-data-callback) - - [`object.patch.appendData(hash, data, ref, [callback])`](#objectpatchappenddatahash-data-ref-callback) - - [`refs(hash, options, [callback])`](#refshash-options-callback) - - [`refs.local(hash, [callback])`](#refslocalhash-callback) - - [`pin`](#pin) - - [`pin.add(hash, options, [callback])`](#pinaddhash-options-callback) - - [`pin.remove(hash, options, [callback])`](#pinremovehash-options-callback) - - [`pin.list(hash, options, [callback])`](#pinlisthash-options-callback) - - [`log`](#log) - - [`log.tail([callback])`](#logtailcallback) - - [Extensions](#extensions) - - [`add(arrayOrBufferOrStream, [callback])`](#addarrayorbufferorstream-callback) - - [`name`](#name) - - [`name.publish(hash, [callback])`](#namepublishhash-callback) - - [`name.resolve(hash, [callback])`](#nameresolvehash-callback) - - [`files`](#files) - - [`files.cp(src, target, [callback])`](#filescpsrc-target-callback) - - [`files.ls(folder, [callback])`](#fileslsfolder-callback) - - [`files.mkdir(folder, [options, callback])`](#filesmkdirfolder-options-callback) - - [`files.stat(fileOrFolder, [callback])`](#filesstatfileorfolder-callback) - - [`files.rm(fileOrFolder, [options, callback])`](#filesrmfileorfolder-options-callback) - - [`files.read(fileOrFolder, [callback])`](#filesreadfileorfolder-callback) - - [`files.write(file, bufferOrArray, [options, callback])`](#fileswritefile-bufferorarray-options-callback) - - [`files.mv(src, target, [callback])`](#filesmvsrc-target-callback) - - [`mount(ipfs, ipns, [callback])`](#mountipfs-ipns-callback) - - [Tooling](#tooling) - - [`commands([callback])`](#commandscallback) - - [`update`](#update) - - [`update.apply([callback])`](#updateapplycallback) - - [`update.check([callback])`](#updatecheckcallback) - - [`update.log([callback])`](#updatelogcallback) - - [`diag`](#diag) - - [`diag.net([callback])`](#diagnetcallback) - - [`diag.sys([callback])`](#diagsyscallback) - - [`diag.cmds([callback])`](#diagcmdscallback) - - [Network](#network) - - [`ping(id, [callback])`](#pingid-callback) - - [`dht`](#dht) - - [`dht.findprovs([callback])`](#dhtfindprovscallback) - - [`dht.get(key, [options, callback])`](#dhtgetkey-options-callback) - - [`dht.put(key, value, [options, callback])`](#dhtputkey-value-options-callback) - - [`swarm`](#swarm) - - [`swarm.peers([callback])`](#swarmpeerscallback) - - [`swarm.connect(address, [callback])`](#swarmconnectaddress-callback) - - - -# API Reference - -We classify the API calls by 'core', 'extensions', 'tooling', and 'network', following the same API spec organization available at [ipfs/specs](https://github.com/ipfs/specs/tree/master/api). - -The tests folder also contains great examples that can be used to understand how this client library interacts with the HTTP-API. You can find the [tests here](test/api). - -## Core - -#### `version([callback])` - -- [tests](test/api/version.spec.js) - -#### `id([callback])` - -- [tests](test/api/id.spec.js) - -#### `block` - -- [tests](test/api/block.spec.js) - -##### `block.put(buffer, [callback])` -##### `block.get(hash, [callback])` -##### `block.stat(hash, [callback])` - -#### `object` - -- [tests](test/api/object.spec.js) - -##### `object.put(buffer, encoding, [callback])` -##### `object.get(hash, [callback])` -##### `object.data(hash, [callback])` -##### `object.stat(hash, [callback])` -##### `object.links(hash, [callback])` -##### `object.new(hash, [callback])` - -##### `object.patch` - -###### `object.patch.addLink(hash, name, ref, [callback])` -###### `object.patch.rmLink(hash, name, [callback])` -###### `object.patch.setData(hash, data, [callback])` -###### `object.patch.appendData(hash, data, ref, [callback])` - -#### `refs(hash, options, [callback])` - -- [tests](test/api/refs.spec.js) - -##### `refs.local(hash, [callback])` - - -#### `pin` - -- [tests](test/api/pin.spec.js) - -##### `pin.add(hash, options, [callback])` -##### `pin.remove(hash, options, [callback])` -##### `pin.list(hash, options, [callback])` - -#### `log` - -- [tests](test/api/log.spec.js) - -##### `log.tail([callback])` - -## Extensions - -#### `add(arrayOrBufferOrStream, [callback])` - -- [tests](test/api/add.spec.js) - -#### `name` - -- [tests](test/api/name.spec.js) - -##### `name.publish(hash, [callback])` -##### `name.resolve(hash, [callback])` - -#### `files` - -- [tests](test/api/files.spec.js) - -##### `files.cp(src, target, [callback])` -##### `files.ls(folder, [callback])` -##### `files.mkdir(folder, [options, callback])` -##### `files.stat(fileOrFolder, [callback])` -##### `files.rm(fileOrFolder, [options, callback])` -##### `files.read(fileOrFolder, [callback])` -##### `files.write(file, bufferOrArray, [options, callback])` -##### `files.mv(src, target, [callback])` - -#### `mount(ipfs, ipns, [callback])` - -- [tests](test/api/mount.spec.js) - -## Tooling - -#### `commands([callback])` - -- [tests](test/api/commands.spec.js) - -#### `update` - -- [tests](test/api/update.spec.js) - -##### `update.apply([callback])` -##### `update.check([callback])` -##### `update.log([callback])` - -#### `diag` - -- [tests](test/api/diag.spec.js) - -##### `diag.net([callback])` -##### `diag.sys([callback])` -##### `diag.cmds([callback])` - -## Network - -#### `ping(id, [callback])` - -- [tests](test/api/ping.spec.js) - -#### `dht` - -- [tests](test/api/dht.spec.js) - -##### `dht.findprovs([callback])` -##### `dht.get(key, [options, callback])` -##### `dht.put(key, value, [options, callback])` - -#### `swarm` - -- [tests](test/api/swarm.spec.js) - -##### `swarm.peers([callback])` -##### `swarm.connect(address, [callback])` diff --git a/README.md b/README.md index 3100b4310..cba5bde23 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ -# js-ipfs-api +ipfs-api +======== [![](https://img.shields.io/badge/made%20by-Protocol%20Labs-blue.svg?style=flat-square)](http://ipn.io) [![](https://img.shields.io/badge/project-IPFS-blue.svg?style=flat-square)](http://ipfs.io/) @@ -9,7 +10,9 @@ [![Travis CI](https://travis-ci.org/ipfs/js-ipfs-api.svg?branch=master)](https://travis-ci.org/ipfs/js-ipfs-api) [![Circle CI](https://circleci.com/gh/ipfs/js-ipfs-api.svg?style=svg)](https://circleci.com/gh/ipfs/js-ipfs-api) -> A client library for the IPFS HTTP API, implemented in JavaScript. +> A client library for the IPFS HTTP API, implemented in JavaScript. This client library implements the [interface-ipfs-core](https://github.com/ipfs/interface-ipfs-core) enabling applications to change between a embebed js-ipfs node and any remote IPFS node without having to change the code. In addition, this client library implements a set of utility functions. + +![](https://github.com/ipfs/interface-ipfs-core/raw/master/img/badge.png) ## Table of Contents @@ -102,16 +105,71 @@ $ ipfs config --json API.HTTPHeaders.Access-Control-Allow-Origin "[\"http://exam ### API -> `WIP` - -`js-ipfs-api` follows the spec defined by [`interface-ipfs-core`](https://github.com/ipfs/interface-ipfs-core), which concerns the interface to expect from IPFS implementations. This interface is a currently active endeavor - expect it to be complete in the next few weeks (August 2016). You can use it today to consult the methods available. +> `js-ipfs-api` follows the spec defined by [`interface-ipfs-core`](https://github.com/ipfs/interface-ipfs-core), which concerns the interface to expect from IPFS implementations. This interface is a currently active endeavor - expect it to be complete in the next few weeks (August 2016). You can use it today to consult the methods available. -### Extra API methods +### Utility functions -Adding to the methods defined by [`interface-ipfs-core`](https://github.com/ipfs/interface-ipfs-core), `js-ipfs-api` exposes a set of extra utility methods. +Adding to the methods defined by [`interface-ipfs-core`](https://github.com/ipfs/interface-ipfs-core), `js-ipfs-api` exposes a set of extra utility methods. These utility functions are scoped behind the `ipfs.util`. Complete documentation for these methods is coming with: https://github.com/ipfs/js-ipfs-api/pull/305 + +#### Add files or entire directories from the FileSystem to IPFS + +> `ipfs.util.addFromFs(path, option, callback)` + +Reads a file from `path` on the filesystem and adds it to IPFS. If `path` is a directory, use option `{ recursive: true }` to add the directory and all its sub-directories. + +```JavaScript +ipfs.util.addFromFs('path/to/a/file', { recursive: true }, (err, result) => { + if (err) { + throw err + } + console.log(result) +}) +``` + +`result` is an array of objects describing the files that were added, such as: + +``` +[{ + path: 'test-folder', + hash: 'QmRNjDeKStKGTQXnJ2NFqeQ9oW23WcpbmvCVrpDHgDg3T6', + size: 2278 +}, +// ... +] +``` + +#### Add a file from a URL to IPFS + +> `ipfs.util.addFromURL(url, callback)` + +```JavaScript +ipfs.util.addFromURL('http://example.com/', (err, result) => { + if (err) { + throw err + } + console.log(result) +}) + +``` + +#### Add a file from a stream to IPFS + +> `ipfs.util.addFromStream(stream, callback)` + +This is very similar to `ipfs.files.add({path:'', content: stream})`. It is like the reverse of cat + +```JavaScript +ipfs.util.addFromStream(, (err, result) => { + if (err) { + throw err + } + console.log(result) +}) +``` + ### Callbacks and promises If you do not pass in a callback all API functions will return a `Promise`. For example: @@ -135,9 +193,11 @@ yet available you need to bring your own polyfill. We run tests by executing `npm test` in a terminal window. This will run both Node.js and Browser tests, both in Chrome and PhantomJS. To ensure that the module conforms with the [`interface-ipfs-core`](https://github.com/ipfs/interface-ipfs-core) spec, we run the batch of tests provided by the interface module, which can be found [here](https://github.com/ipfs/interface-ipfs-core/tree/master/src). + + ## Contribute -The js-ipfs API is a work in progress. As such, there's a few things you can do right now to help out: +The js-ipfs-api is a work in progress. As such, there's a few things you can do right now to help out: * **[Check out the existing issues](https://github.com/ipfs/js-ipfs-api/issues)**! * **Perform code reviews**. More eyes will help a) speed the project along b) ensure quality and c) reduce possible future bugs. @@ -148,6 +208,10 @@ The js-ipfs API is a work in progress. As such, there's a few things you can do [![](https://cdn.rawgit.com/jbenet/contribute-ipfs-gif/master/img/contribute.gif)](https://github.com/ipfs/community/blob/master/contributing.md) +## Historical context + +This module started as a direct mapping from the go-ipfs cli to a JavaScript implementation, although this was useful and familiar to a lot of developers that were coming to IPFS for the first time, it also created some confusion on how to operate the core of IPFS and have access to the full capacity of the protocol. After much consideration, we decided to create `interface-ipfs-core` with the goal of standardizing the interface of a core implementation of IPFS, and keep the utility functions the IPFS community learned to use and love, such as reading files from disk and storing them directly to IPFS. + ## License [MIT](LICENSE) diff --git a/package.json b/package.json index b92a6397b..115151912 100644 --- a/package.json +++ b/package.json @@ -1,9 +1,21 @@ { "name": "ipfs-api", "version": "6.0.3", - "description": "A client library for the IPFS API", + "description": "A client library for the IPFS HTTP API. Follows interface-ipfs-core spec", "main": "lib/index.js", "jsnext:main": "src/index.js", + "scripts": { + "test": "node --max_old_space_size=4096 node_modules/.bin/gulp test:node", + "test:node": "gulp test:node", + "test:browser": "node --max_old_space_size=4096 node_modules/.bin/gulp test:browser", + "lint": "aegir-lint", + "build": "gulp build", + "release": "node --max_old_space_size=4096 node_modules/.bin/gulp release", + "release-minor": "node --max_old_space_size=4096 node_modules/.bin/gulp release --type minor", + "release-major": "node --max_old_space_size=4096 node_modules/.bin/gulp release --type major", + "coverage": "gulp coverage", + "coverage-publish": "aegir-coverage publish" + }, "dependencies": { "async": "^2.0.1", "babel-runtime": "^6.11.6", @@ -20,6 +32,7 @@ "ndjson": "^1.4.3", "promisify-es6": "^1.0.1", "qs": "^6.2.1", + "tar-stream": "^1.5.2", "wreck": "^9.0.0" }, "engines": { @@ -30,13 +43,12 @@ "url": "https://github.com/ipfs/js-ipfs-api" }, "devDependencies": { - "aegir": "^6.0.0", + "aegir": "^6.0.1", "chai": "^3.5.0", "gulp": "^3.9.1", "hapi": "^14.1.0", - "interface-ipfs-core": "^0.8.0", + "interface-ipfs-core": "^0.13.0", "ipfsd-ctl": "^0.14.0", - "passthrough-counter": "^1.0.0", "pre-commit": "^1.1.3", "socket.io": "^1.4.8", "socket.io-client": "^1.4.8", @@ -44,18 +56,6 @@ "stream-http": "^2.3.1", "streamifier": "^0.1.1" }, - "scripts": { - "test": "gulp test", - "test:node": "gulp test:node", - "test:browser": "gulp test:browser", - "lint": "aegir-lint", - "build": "gulp build", - "release": "gulp release", - "release-minor": "gulp release --type minor", - "release-major": "gulp release --type major", - "coverage": "gulp coverage", - "coverage-publish": "aegir-coverage publish" - }, "pre-commit": [ "lint", "test" diff --git a/src/api/add-files.js b/src/api/add-files.js deleted file mode 100644 index 26f71097d..000000000 --- a/src/api/add-files.js +++ /dev/null @@ -1,25 +0,0 @@ -'use strict' - -const isNode = require('detect-node') -const addToDagNodesTransform = require('../add-to-dagnode-transform') - -module.exports = (send) => { - return function add (path, opts, cb) { - if (typeof (opts) === 'function' && cb === undefined) { - cb = opts - opts = {} - } - - if (!isNode) { - return cb(new Error('Recursive uploads are not supported in the browser')) - } - - if (typeof (path) !== 'string') { - return cb(new Error('"path" must be a string')) - } - - var sendWithTransform = send.withTransform(addToDagNodesTransform) - - return sendWithTransform('add', null, opts, path, cb) - } -} diff --git a/src/api/add-url.js b/src/api/add-url.js deleted file mode 100644 index fccb96e75..000000000 --- a/src/api/add-url.js +++ /dev/null @@ -1,25 +0,0 @@ -'use strict' - -const Wreck = require('wreck') -const addToDagNodesTransform = require('../add-to-dagnode-transform') - -module.exports = (send) => { - return function add (url, opts, cb) { - if (typeof (opts) === 'function' && cb === undefined) { - cb = opts - opts = {} - } - - if (typeof url !== 'string' || !url.startsWith('http')) { - return cb(new Error('"url" param must be an http(s) url')) - } - - var sendWithTransform = send.withTransform(addToDagNodesTransform) - - Wreck.request('GET', url, null, (err, res) => { - if (err) return cb(err) - - sendWithTransform('add', null, opts, res, cb) - }) - } -} diff --git a/src/api/add.js b/src/api/add.js index 2dfea23b9..1379a4296 100644 --- a/src/api/add.js +++ b/src/api/add.js @@ -16,6 +16,9 @@ module.exports = (send) => { const sendWithTransform = send.withTransform(addToDagNodesTransform) - sendWithTransform('add', null, {}, files, callback) + return sendWithTransform({ + path: 'add', + files: files + }, callback) }) } diff --git a/src/api/bitswap.js b/src/api/bitswap.js index c2f9749b4..98704caca 100644 --- a/src/api/bitswap.js +++ b/src/api/bitswap.js @@ -1,15 +1,29 @@ 'use strict' -const argCommand = require('../cmd-helpers').argCommand +const promisify = require('promisify-es6') module.exports = (send) => { return { - wantlist (cb) { - return send('bitswap/wantlist', {}, null, null, cb) - }, - stat (cb) { - return send('bitswap/stat', {}, null, null, cb) - }, - unwant: argCommand(send, 'bitswap/unwant') + wantlist: promisify((callback) => { + send({ + path: 'bitswap/wantlist' + }, callback) + }), + stat: promisify((callback) => { + send({ + path: 'bitswap/stat' + }, callback) + }), + unwant: promisify((args, opts, callback) => { + if (typeof (opts) === 'function') { + callback = opts + opts = {} + } + send({ + path: 'bitswap/unwant', + args: args, + qs: opts + }, callback) + }) } } diff --git a/src/api/block.js b/src/api/block.js index 8a6ec4529..563a7bc6a 100644 --- a/src/api/block.js +++ b/src/api/block.js @@ -1,20 +1,41 @@ 'use strict' -const argCommand = require('../cmd-helpers').argCommand +const promisify = require('promisify-es6') module.exports = (send) => { return { - get: argCommand(send, 'block/get'), - stat: argCommand(send, 'block/stat'), - put (file, cb) { + get: promisify((args, opts, callback) => { + if (typeof (opts) === 'function') { + callback = opts + opts = {} + } + return send({ + path: 'block/get', + args: args, + qs: opts + }, callback) + }), + stat: promisify((args, opts, callback) => { + if (typeof (opts) === 'function') { + callback = opts + opts = {} + } + return send({ + path: 'block/stat', + args: args, + qs: opts + }, callback) + }), + put: promisify((file, callback) => { if (Array.isArray(file)) { - let err = new Error('block.put() only accepts 1 file') - if (typeof cb !== 'function' && typeof Promise !== 'undefined') { - return new Promise((resolve, reject) => reject(err)) - } - return cb(err) + const err = new Error('block.put() only accepts 1 file') + return callback(err) } - return send('block/put', null, null, file, cb) - } + + return send({ + path: 'block/put', + files: file + }, callback) + }) } } diff --git a/src/api/bootstrap.js b/src/api/bootstrap.js index 1c8ee0d59..89f67a0aa 100644 --- a/src/api/bootstrap.js +++ b/src/api/bootstrap.js @@ -1,23 +1,70 @@ 'use strict' -const command = require('../cmd-helpers').command +const promisify = require('promisify-es6') module.exports = (send) => { return { - add: (arg, opts, cb) => { - if (typeof opts === 'function' && cb === undefined) { - cb = opts + add: promisify((args, opts, callback) => { + if (typeof opts === 'function' && + !callback) { + callback = opts opts = {} } - return send('bootstrap/add', arg, opts, null, cb) - }, - rm: (arg, opts, cb) => { - if (typeof opts === 'function' && cb === undefined) { - cb = opts + + // opts is the real callback -- + // 'callback' is being injected by promisify + if (typeof opts === 'function' && + typeof callback === 'function') { + callback = opts + opts = {} + } + + if (args && typeof args === 'object') { + opts = args + args = undefined + } + + send({ + path: 'bootstrap/add', + args: args, + qs: opts + }, callback) + }), + rm: promisify((args, opts, callback) => { + if (typeof opts === 'function' && + !callback) { + callback = opts + opts = {} + } + + // opts is the real callback -- + // 'callback' is being injected by promisify + if (typeof opts === 'function' && + typeof callback === 'function') { + callback = opts + opts = {} + } + + if (args && typeof args === 'object') { + opts = args + args = undefined + } + + send({ + path: 'bootstrap/rm', + args: args, + qs: opts + }, callback) + }), + list: promisify((opts, callback) => { + if (typeof (opts) === 'function') { + callback = opts opts = {} } - return send('bootstrap/rm', arg, opts, null, cb) - }, - list: command(send, 'bootstrap/list') + send({ + path: 'bootstrap/list', + qs: opts + }, callback) + }) } } diff --git a/src/api/cat.js b/src/api/cat.js index 06e9bac90..62adfb73b 100644 --- a/src/api/cat.js +++ b/src/api/cat.js @@ -4,13 +4,16 @@ const promisify = require('promisify-es6') const cleanMultihash = require('../clean-multihash') module.exports = (send) => { - const cat = promisify((multihash, callback) => { + return promisify((hash, callback) => { try { - multihash = cleanMultihash(multihash) + hash = cleanMultihash(hash) } catch (err) { return callback(err) } - send('cat', multihash, null, null, callback) + + send({ + path: 'cat', + args: hash + }, callback) }) - return cat } diff --git a/src/api/commands.js b/src/api/commands.js index 18eaee4d5..b0b4490b8 100644 --- a/src/api/commands.js +++ b/src/api/commands.js @@ -1,7 +1,11 @@ 'use strict' -const command = require('../cmd-helpers').command +const promisify = require('promisify-es6') module.exports = (send) => { - return command(send, 'commands') + return promisify((callback) => { + send({ + path: 'commands' + }, callback) + }) } diff --git a/src/api/config.js b/src/api/config.js index 582362bb6..33aaa03cd 100644 --- a/src/api/config.js +++ b/src/api/config.js @@ -1,31 +1,78 @@ 'use strict' -const argCommand = require('../cmd-helpers').argCommand +const streamifier = require('streamifier') +const promisify = require('promisify-es6') module.exports = (send) => { return { - get: argCommand(send, 'config'), - set (key, value, opts, cb) { - if (typeof (opts) === 'function') { - cb = opts + get: promisify((key, callback) => { + if (typeof key === 'function') { + callback = key + key = undefined + } + + if (!key) { + send({ + path: 'config/show', + buffer: true + }, callback) + return + } + + send({ + path: 'config', + args: key, + buffer: true + }, (err, response) => { + if (err) { + return callback(err) + } + callback(null, response.Value) + }) + }), + set: promisify((key, value, opts, callback) => { + if (typeof opts === 'function') { + callback = opts opts = {} } + if (typeof key !== 'string') { + return callback(new Error('Invalid key type')) + } - if (typeof (value) === 'object') { + if (typeof value !== 'object' && + typeof value !== 'boolean' && + typeof value !== 'string') { + return callback(new Error('Invalid value type')) + } + + if (typeof value === 'object') { value = JSON.stringify(value) opts = { json: true } - } else if (typeof (value) === 'boolean') { + } + + if (typeof value === 'boolean') { value = value.toString() opts = { bool: true } } - return send('config', [key, value], opts, null, cb) - }, - show (cb) { - return send('config/show', null, null, null, true, cb) - }, - replace (file, cb) { - return send('config/replace', null, null, file, cb) - } + send({ + path: 'config', + args: [key, value], + qs: opts, + files: undefined, + buffer: true + }, callback) + }), + replace: promisify((config, callback) => { + if (typeof config === 'object') { + config = streamifier.createReadStream(new Buffer(JSON.stringify(config))) + } + + send({ + path: 'config/replace', + files: config, + buffer: true + }, callback) + }) } } diff --git a/src/api/add-stream.js b/src/api/create-add-stream.js similarity index 91% rename from src/api/add-stream.js rename to src/api/create-add-stream.js index ab7954016..8c40dd1cc 100644 --- a/src/api/add-stream.js +++ b/src/api/create-add-stream.js @@ -7,7 +7,7 @@ const promisify = require('promisify-es6') module.exports = (send) => { const add = addCmd(send) - return promisify(function createAddStream (callback) { + return promisify((callback) => { const tuples = [] const ds = new Duplex({ objectMode: true }) diff --git a/src/api/dht.js b/src/api/dht.js index aa02da5ce..fe42146ec 100644 --- a/src/api/dht.js +++ b/src/api/dht.js @@ -1,20 +1,55 @@ 'use strict' -const argCommand = require('../cmd-helpers').argCommand +const promisify = require('promisify-es6') module.exports = (send) => { return { - findprovs: argCommand(send, 'dht/findprovs'), - get (key, opts, cb) { - if (typeof (opts) === 'function' && !cb) { - cb = opts - opts = null + findprovs: promisify((args, opts, callback) => { + if (typeof opts === 'function' && + !callback) { + callback = opts + opts = {} + } + + // opts is the real callback -- + // 'callback' is being injected by promisify + if (typeof opts === 'function' && + typeof callback === 'function') { + callback = opts + opts = {} + } + + send({ + path: 'dht/findprovs', + args: args, + qs: opts + }, callback) + }), + get: promisify((key, opts, callback) => { + if (typeof opts === 'function' && + !callback) { + callback = opts + opts = {} + } + + // opts is the real callback -- + // 'callback' is being injected by promisify + if (typeof opts === 'function' && + typeof callback === 'function') { + callback = opts + opts = {} } const handleResult = (done, err, res) => { - if (err) return done(err) - if (!res) return done(new Error('empty response')) - if (res.length === 0) return done(new Error('no value returned for key')) + if (err) { + return done(err) + } + if (!res) { + return done(new Error('empty response')) + } + if (res.length === 0) { + return done(new Error('no value returned for key')) + } // Inconsistent return values in the browser vs node if (Array.isArray(res)) { @@ -29,28 +64,32 @@ module.exports = (send) => { } } - if (typeof cb !== 'function' && typeof Promise !== 'undefined') { - const done = (err, res) => { - if (err) throw err - return res - } - - return send('dht/get', key, opts) - .then( - (res) => handleResult(done, null, res), - (err) => handleResult(done, err) - ) + send({ + path: 'dht/get', + args: key, + qs: opts + }, handleResult.bind(null, callback)) + }), + put: promisify((key, value, opts, callback) => { + if (typeof opts === 'function' && + !callback) { + callback = opts + opts = {} } - return send('dht/get', key, opts, null, handleResult.bind(null, cb)) - }, - put (key, value, opts, cb) { - if (typeof (opts) === 'function' && !cb) { - cb = opts - opts = null + // opts is the real callback -- + // 'callback' is being injected by promisify + if (typeof opts === 'function' && + typeof callback === 'function') { + callback = opts + opts = {} } - return send('dht/put', [key, value], opts, null, cb) - } + send({ + path: 'dht/put', + args: [key, value], + qs: opts + }, callback) + }) } } diff --git a/src/api/diag.js b/src/api/diag.js index 438817446..15ae62301 100644 --- a/src/api/diag.js +++ b/src/api/diag.js @@ -1,11 +1,41 @@ 'use strict' -const command = require('../cmd-helpers').command +const promisify = require('promisify-es6') module.exports = (send) => { return { - net: command(send, 'diag/net'), - sys: command(send, 'diag/sys'), - cmds: command(send, 'diag/sys') + net: promisify((opts, callback) => { + if (typeof (opts) === 'function') { + callback = opts + opts = {} + } + + send({ + path: 'diag/net', + qs: opts + }, callback) + }), + sys: promisify((opts, callback) => { + if (typeof (opts) === 'function') { + callback = opts + opts = {} + } + + send({ + path: 'diag/sys', + qs: opts + }, callback) + }), + cmds: promisify((opts, callback) => { + if (typeof (opts) === 'function') { + callback = opts + opts = {} + } + + send({ + path: 'diag/cmds', + qs: opts + }, callback) + }) } } diff --git a/src/api/files.js b/src/api/files.js index 2e848c39e..2fbf827eb 100644 --- a/src/api/files.js +++ b/src/api/files.js @@ -1,28 +1,118 @@ 'use strict' -const argCommand = require('../cmd-helpers').argCommand +const promisify = require('promisify-es6') module.exports = (send) => { return { - cp: argCommand(send, 'files/cp'), - ls: argCommand(send, 'files/ls'), - mkdir: argCommand(send, 'files/mkdir'), - stat: argCommand(send, 'files/stat'), - rm: function (path, opts, cb) { - if (typeof opts === 'function' && cb === undefined) { - cb = opts - opts = {} - } - return send('files/rm', path, opts, null, cb) - }, - read: argCommand(send, 'files/read'), - write: function (pathDst, files, opts, cb) { - if (typeof opts === 'function' && cb === undefined) { - cb = opts - opts = {} - } - return send('files/write', pathDst, opts, files, cb) - }, - mv: argCommand(send, 'files/mv') + cp: promisify((args, opts, callback) => { + if (typeof (opts) === 'function') { + callback = opts + opts = {} + } + send({ + path: 'files/cp', + args: args, + qs: opts + }, callback) + }), + ls: promisify((args, opts, callback) => { + if (typeof (opts) === 'function') { + callback = opts + opts = {} + } + return send({ + path: 'files/ls', + args: args, + qs: opts + }, callback) + }), + mkdir: promisify((args, opts, callback) => { + if (typeof (opts) === 'function') { + callback = opts + opts = {} + } + send({ + path: 'files/mkdir', + args: args, + qs: opts + }, callback) + }), + stat: promisify((args, opts, callback) => { + if (typeof (opts) === 'function') { + callback = opts + opts = {} + } + send({ + path: 'files/stat', + args: args, + qs: opts + }, callback) + }), + rm: promisify((path, opts, callback) => { + if (typeof opts === 'function' && + !callback) { + callback = opts + opts = {} + } + + // opts is the real callback -- + // 'callback' is being injected by promisify + if (typeof opts === 'function' && + typeof callback === 'function') { + callback = opts + opts = {} + } + + send({ + path: 'files/rm', + args: path, + qs: opts + }, callback) + }), + read: promisify((args, opts, callback) => { + if (typeof (opts) === 'function') { + callback = opts + opts = {} + } + send({ + path: 'files/read', + args: args, + qs: opts + }, callback) + }), + write: promisify((pathDst, files, opts, callback) => { + if (typeof opts === 'function' && + !callback) { + callback = opts + opts = {} + } + + // opts is the real callback -- + // 'callback' is being injected by promisify + if (typeof opts === 'function' && + typeof callback === 'function') { + callback = opts + opts = {} + } + + send({ + path: 'files/write', + args: pathDst, + qs: opts, + files: files + }, callback) + }), + mv: promisify((args, opts, callback) => { + if (typeof opts === 'function' && + callback === undefined) { + callback = opts + opts = {} + } + send({ + path: 'files/mv', + args: args, + qs: opts + }, callback) + }) } } diff --git a/src/api/get.js b/src/api/get.js index b1b833d9d..fa7ba1250 100644 --- a/src/api/get.js +++ b/src/api/get.js @@ -5,26 +5,33 @@ const cleanMultihash = require('../clean-multihash') const promisify = require('promisify-es6') module.exports = (send) => { - return promisify(function get (path, opts, cb) { - if (typeof opts === 'function' && !cb) { - cb = opts + return promisify(function get (path, opts, callback) { + if (typeof opts === 'function' && + !callback) { + callback = opts opts = {} } - // opts is the real callback -- 'cb' is being injected by promisify - if (typeof opts === 'function' && typeof cb === 'function') { - cb = opts + // opts is the real callback -- + // 'callback' is being injected by promisify + if (typeof opts === 'function' && + typeof callback === 'function') { + callback = opts opts = {} } try { path = cleanMultihash(path) } catch (err) { - return cb(err) + return callback(err) } var sendWithTransform = send.withTransform(tarStreamToObjects) - return sendWithTransform('get', path, opts, null, cb) + sendWithTransform({ + path: 'get', + args: path, + qs: opts + }, callback) }) } diff --git a/src/api/id.js b/src/api/id.js index ab4d44e8d..beb970f42 100644 --- a/src/api/id.js +++ b/src/api/id.js @@ -1,11 +1,28 @@ 'use strict' +const promisify = require('promisify-es6') + module.exports = (send) => { - return function id (idParam, cb) { - if (typeof idParam === 'function') { - cb = idParam - idParam = null + return promisify((opts, callback) => { + if (typeof opts === 'function') { + callback = opts + opts = undefined } - return send('id', idParam, null, null, cb) - } + send({ + path: 'id', + args: opts + }, (err, result) => { + if (err) { + return callback(err) + } + const identity = { + id: result.ID, + publicKey: result.PublicKey, + addresses: result.Addresses, + agentVersion: result.AgentVersion, + protocolVersion: result.ProtocolVersion + } + callback(null, identity) + }) + }) } diff --git a/src/api/log.js b/src/api/log.js index 1c85767d8..e4da33864 100644 --- a/src/api/log.js +++ b/src/api/log.js @@ -1,19 +1,19 @@ 'use strict' const ndjson = require('ndjson') +const promisify = require('promisify-es6') module.exports = (send) => { return { - tail (cb) { - if (typeof cb !== 'function' && typeof Promise !== 'undefined') { - return send('log/tail', null, {}, null, false) - .then((res) => res.pipe(ndjson.parse())) - } - - return send('log/tail', null, {}, null, false, (err, res) => { - if (err) return cb(err) - cb(null, res.pipe(ndjson.parse())) + tail: promisify((callback) => { + send({ + path: 'log/tail' + }, (err, response) => { + if (err) { + return callback(err) + } + callback(null, response.pipe(ndjson.parse())) }) - } + }) } } diff --git a/src/api/ls.js b/src/api/ls.js index 4f109b6fe..8098fdeb8 100644 --- a/src/api/ls.js +++ b/src/api/ls.js @@ -1,7 +1,17 @@ 'use strict' -const argCommand = require('../cmd-helpers').argCommand +const promisify = require('promisify-es6') module.exports = (send) => { - return argCommand(send, 'ls') + return promisify((args, opts, callback) => { + if (typeof (opts) === 'function') { + callback = opts + opts = {} + } + send({ + path: 'ls', + args: args, + qs: opts + }, callback) + }) } diff --git a/src/api/mount.js b/src/api/mount.js index 917fa0b90..a01c56825 100644 --- a/src/api/mount.js +++ b/src/api/mount.js @@ -1,17 +1,27 @@ 'use strict' +const promisify = require('promisify-es6') + module.exports = (send) => { - return function mount (ipfs, ipns, cb) { + return promisify((ipfs, ipns, callback) => { if (typeof ipfs === 'function') { - cb = ipfs + callback = ipfs ipfs = null } else if (typeof ipns === 'function') { - cb = ipns + callback = ipns ipns = null } const opts = {} - if (ipfs) opts.f = ipfs - if (ipns) opts.n = ipns - return send('mount', null, opts, null, cb) - } + if (ipfs) { + opts.f = ipfs + } + if (ipns) { + opts.n = ipns + } + + send({ + path: 'mount', + qs: opts + }, callback) + }) } diff --git a/src/api/name.js b/src/api/name.js index 70e7b72b9..77fd39fe0 100644 --- a/src/api/name.js +++ b/src/api/name.js @@ -1,10 +1,30 @@ 'use strict' -const argCommand = require('../cmd-helpers').argCommand +const promisify = require('promisify-es6') module.exports = (send) => { return { - publish: argCommand(send, 'name/publish'), - resolve: argCommand(send, 'name/resolve') + publish: promisify((args, opts, callback) => { + if (typeof (opts) === 'function') { + callback = opts + opts = {} + } + send({ + path: 'name/publish', + args: args, + qs: opts + }, callback) + }), + resolve: promisify((args, opts, callback) => { + if (typeof (opts) === 'function') { + callback = opts + opts = {} + } + send({ + path: 'name/resolve', + args: args, + qs: opts + }, callback) + }) } } diff --git a/src/api/object.js b/src/api/object.js index 0c6d2a05c..787b36276 100644 --- a/src/api/object.js +++ b/src/api/object.js @@ -5,6 +5,7 @@ const DAGLink = require('ipfs-merkle-dag').DAGLink const promisify = require('promisify-es6') const bs58 = require('bs58') const bl = require('bl') +const cleanMultihash = require('../clean-multihash') module.exports = (send) => { const api = { @@ -23,7 +24,10 @@ module.exports = (send) => { return callback(err) } - send('object/get', multihash, null, null, (err, result) => { + send({ + path: 'object/get', + args: multihash + }, (err, result) => { if (err) { return callback(err) } @@ -73,7 +77,11 @@ module.exports = (send) => { } const enc = options.enc || 'json' - send('object/put', null, {inputenc: enc}, buf, (err, result) => { + send({ + path: 'object/put', + qs: { inputenc: enc }, + files: buf + }, (err, result) => { if (err) { return callback(err) } @@ -117,7 +125,10 @@ module.exports = (send) => { return callback(err) } - send('object/data', multihash, null, null, (err, result) => { + send({ + path: 'object/data', + args: multihash + }, (err, result) => { if (err) { return callback(err) } @@ -144,7 +155,10 @@ module.exports = (send) => { return callback(err) } - send('object/links', multihash, null, null, (err, result) => { + send({ + path: 'object/links', + args: multihash + }, (err, result) => { if (err) { return callback(err) } @@ -159,25 +173,30 @@ module.exports = (send) => { callback(null, links) }) }), - stat: promisify((multihash, options, callback) => { - if (typeof options === 'function') { - callback = options - options = {} + stat: promisify((multihash, opts, callback) => { + if (typeof opts === 'function') { + callback = opts + opts = {} } - if (!options) { - options = {} + if (!opts) { + opts = {} } try { - multihash = cleanMultihash(multihash, options) + multihash = cleanMultihash(multihash, opts) } catch (err) { return callback(err) } - send('object/stat', multihash, null, null, callback) + send({ + path: 'object/stat', + args: multihash + }, callback) }), new: promisify((callback) => { - send('object/new', null, null, null, (err, result) => { + send({ + path: 'object/new' + }, (err, result) => { if (err) { return callback(err) } @@ -191,88 +210,102 @@ module.exports = (send) => { }) }), patch: { - addLink: promisify((multihash, dLink, options, callback) => { - if (typeof options === 'function') { - callback = options - options = {} + addLink: promisify((multihash, dLink, opts, callback) => { + if (typeof opts === 'function') { + callback = opts + opts = {} } - if (!options) { - options = {} + if (!opts) { + opts = {} } try { - multihash = cleanMultihash(multihash, options) + multihash = cleanMultihash(multihash, opts) } catch (err) { return callback(err) } - send('object/patch/add-link', [multihash, dLink.name, bs58.encode(dLink.hash).toString()], null, null, (err, result) => { + send({ + path: 'object/patch/add-link', + args: [multihash, dLink.name, bs58.encode(dLink.hash).toString()] + }, (err, result) => { if (err) { return callback(err) } api.get(result.Hash, { enc: 'base58' }, callback) }) }), - rmLink: promisify((multihash, dLink, options, callback) => { - if (typeof options === 'function') { - callback = options - options = {} + rmLink: promisify((multihash, dLink, opts, callback) => { + if (typeof opts === 'function') { + callback = opts + opts = {} } - if (!options) { - options = {} + if (!opts) { + opts = {} } try { - multihash = cleanMultihash(multihash, options) + multihash = cleanMultihash(multihash, opts) } catch (err) { return callback(err) } - send('object/patch/rm-link', [multihash, dLink.name], null, null, (err, result) => { + send({ + path: 'object/patch/rm-link', + args: [multihash, dLink.name] + }, (err, result) => { if (err) { return callback(err) } api.get(result.Hash, { enc: 'base58' }, callback) }) }), - setData: promisify((multihash, data, options, callback) => { - if (typeof options === 'function') { - callback = options - options = {} + setData: promisify((multihash, data, opts, callback) => { + if (typeof opts === 'function') { + callback = opts + opts = {} } - if (!options) { - options = {} + if (!opts) { + opts = {} } try { - multihash = cleanMultihash(multihash, options) + multihash = cleanMultihash(multihash, opts) } catch (err) { return callback(err) } - send('object/patch/set-data', [multihash], null, data, (err, result) => { + send({ + path: 'object/patch/set-data', + args: [multihash], + files: data + }, (err, result) => { if (err) { return callback(err) } api.get(result.Hash, { enc: 'base58' }, callback) }) }), - appendData: promisify((multihash, data, options, callback) => { - if (typeof options === 'function') { - callback = options - options = {} + appendData: promisify((multihash, data, opts, callback) => { + if (typeof opts === 'function') { + callback = opts + opts = {} } - if (!options) { - options = {} + if (!opts) { + opts = {} } try { - multihash = cleanMultihash(multihash, options) + multihash = cleanMultihash(multihash, opts) } catch (err) { return callback(err) } - send('object/patch/append-data', [multihash], null, data, (err, result) => { + send({ + path: 'object/patch/append-data', + args: [multihash], + files: data + }, (err, result) => { if (err) { return callback(err) } @@ -281,34 +314,6 @@ module.exports = (send) => { }) } } - return api -} -function cleanMultihash (multihash, options) { - if (Buffer.isBuffer(multihash)) { - if (options.enc) { - switch (options.enc) { - case 'base58': { - multihash = multihash.toString() - break - } - default: throw new Error('invalid multihash') - } - } else { - multihash = bs58.encode(multihash).toString() - } - } else if (typeof multihash === 'string') { - if (options.enc) { - // For the future, when we support more than one enc - // switch (options.enc) { - // case 'base58': // It is good - // } - } else { - throw new Error('not valid multihash') - } - } else if (!multihash) { - throw new Error('missing valid multihash') - } - - return multihash + return api } diff --git a/src/api/pin.js b/src/api/pin.js index e79e1623c..cbd96eee0 100644 --- a/src/api/pin.js +++ b/src/api/pin.js @@ -1,39 +1,68 @@ 'use strict' +const promisify = require('promisify-es6') + module.exports = (send) => { return { - add (hash, opts, cb) { + add: promisify((hash, opts, callback) => { if (typeof opts === 'function') { - cb = opts + callback = opts opts = null } - - return send('pin/add', hash, opts, null, cb) - }, - remove (hash, opts, cb) { + send({ + path: 'pin/add', + args: hash, + qs: opts + }, (err, res) => { + if (err) { + return callback(err) + } + callback(null, res.Pins) + }) + }), + rm: promisify((hash, opts, callback) => { if (typeof opts === 'function') { - cb = opts + callback = opts opts = null } + send({ + path: 'pin/rm', + args: hash, + qs: opts + }, (err, res) => { + if (err) { + return callback(err) + } + callback(null, res.Pins) + }) + }), + ls: promisify((hash, opts, callback) => { + if (typeof opts === 'function') { + callback = opts + opts = {} + } - return send('pin/rm', hash, opts, null, cb) - }, - list (type, cb) { - if (typeof type === 'function') { - cb = type - type = null + if (typeof hash === 'object') { + opts = hash + hash = undefined } - let opts = null - let hash = null - if (typeof type === 'string') { - opts = { type: type } - } else if (type && type.hash) { - hash = type.hash - type.hash = null - opts = type + + if (typeof hash === 'function') { + callback = hash + hash = undefined + opts = {} } - return send('pin/ls', hash, opts, null, cb) - } + send({ + path: 'pin/ls', + args: hash, + qs: opts + }, (err, res) => { + if (err) { + return callback(err) + } + callback(null, res.Keys) + }) + }) } } diff --git a/src/api/ping.js b/src/api/ping.js index f2853a675..5e7c74f6f 100644 --- a/src/api/ping.js +++ b/src/api/ping.js @@ -1,15 +1,18 @@ 'use strict' -module.exports = (send) => { - return function ping (id, cb) { - if (typeof cb !== 'function' && typeof Promise !== 'undefined') { - return send('ping', id, {n: 1}, null) - .then((res) => res[1]) - } +const promisify = require('promisify-es6') - return send('ping', id, { n: 1 }, null, function (err, res) { - if (err) return cb(err, null) - cb(null, res[1]) +module.exports = (send) => { + return promisify((id, callback) => { + send({ + path: 'ping', + args: id, + qs: { n: 1 } + }, function (err, res) { + if (err) { + return callback(err, null) + } + callback(null, res[1]) }) - } + }) } diff --git a/src/api/refs.js b/src/api/refs.js index 1788512f7..318ccb59f 100644 --- a/src/api/refs.js +++ b/src/api/refs.js @@ -1,10 +1,29 @@ 'use strict' -const cmds = require('../cmd-helpers') +const promisify = require('promisify-es6') module.exports = (send) => { - const refs = cmds.argCommand(send, 'refs') - refs.local = cmds.command(send, 'refs/local') + const refs = promisify((args, opts, callback) => { + if (typeof (opts) === 'function') { + callback = opts + opts = {} + } + return send({ + path: 'refs', + args: args, + qs: opts + }, callback) + }) + refs.local = promisify((opts, callback) => { + if (typeof (opts) === 'function') { + callback = opts + opts = {} + } + return send({ + path: 'refs', + qs: opts + }, callback) + }) return refs } diff --git a/src/api/repo.js b/src/api/repo.js index e6211c713..32cde20c8 100644 --- a/src/api/repo.js +++ b/src/api/repo.js @@ -1,10 +1,28 @@ 'use strict' -const cmds = require('../cmd-helpers') +const promisify = require('promisify-es6') module.exports = (send) => { return { - gc: cmds.command(send, 'repo/gc'), - stat: cmds.command(send, 'repo/stat') + gc: promisify((opts, callback) => { + if (typeof (opts) === 'function') { + callback = opts + opts = {} + } + send({ + path: 'repo/gc', + qs: opts + }, callback) + }), + stat: promisify((opts, callback) => { + if (typeof (opts) === 'function') { + callback = opts + opts = {} + } + send({ + path: 'repo/stat', + qs: opts + }, callback) + }) } } diff --git a/src/api/swarm.js b/src/api/swarm.js index 08b87c6f2..510b2d2a3 100644 --- a/src/api/swarm.js +++ b/src/api/swarm.js @@ -1,13 +1,84 @@ 'use strict' -const cmds = require('../cmd-helpers') +const promisify = require('promisify-es6') +const multiaddr = require('multiaddr') module.exports = (send) => { return { - peers: cmds.command(send, 'swarm/peers'), - connect: cmds.argCommand(send, 'swarm/connect'), - disconnect: cmds.argCommand(send, 'swarm/disconnect'), - addrs: cmds.command(send, 'swarm/addrs'), - localAddrs: cmds.command(send, 'swarm/addrs/local') + peers: promisify((opts, callback) => { + if (typeof (opts) === 'function') { + callback = opts + opts = {} + } + send({ + path: 'swarm/peers', + qs: opts + }, (err, result) => { + if (err) { + return callback(err) + } + callback(null, result.Strings.map((addr) => { + return multiaddr(addr) + })) + }) + }), + connect: promisify((args, opts, callback) => { + if (typeof (opts) === 'function') { + callback = opts + opts = {} + } + send({ + path: 'swarm/connect', + args: args, + qs: opts + }, callback) + }), + disconnect: promisify((args, opts, callback) => { + if (typeof (opts) === 'function') { + callback = opts + opts = {} + } + send({ + path: 'swarm/disconnect', + args: args, + qs: opts + }, callback) + }), + addrs: promisify((opts, callback) => { + if (typeof (opts) === 'function') { + callback = opts + opts = {} + } + send({ + path: 'swarm/addrs', + qs: opts + }, (err, result) => { + if (err) { + return callback(err) + } + callback(null, Object.keys(result.Addrs).map((id) => { + return result.Addrs[id].map((maStr) => { + return multiaddr(maStr).encapsulate('/ipfs/' + id) + }) + })[0]) + }) + }), + localAddrs: promisify((opts, callback) => { + if (typeof (opts) === 'function') { + callback = opts + opts = {} + } + send({ + path: 'swarm/addrs/local', + qs: opts + }, (err, result) => { + if (err) { + return callback(err) + } + callback(null, result.Strings.map((addr) => { + return multiaddr(addr) + })) + }) + }) } } diff --git a/src/api/update.js b/src/api/update.js index 5eca2c3ec..7d3e980a9 100644 --- a/src/api/update.js +++ b/src/api/update.js @@ -1,11 +1,38 @@ 'use strict' -const command = require('../cmd-helpers').command +const promisify = require('promisify-es6') module.exports = (send) => { return { - apply: command(send, 'update'), - check: command(send, 'update/check'), - log: command(send, 'update/log') + apply: promisify((opts, callback) => { + if (typeof (opts) === 'function') { + callback = opts + opts = {} + } + send({ + path: 'update', + qs: opts + }, callback) + }), + check: promisify((opts, callback) => { + if (typeof (opts) === 'function') { + callback = opts + opts = {} + } + send({ + path: 'update/check', + qs: opts + }, callback) + }), + log: promisify((opts, callback) => { + if (typeof (opts) === 'function') { + callback = opts + opts = {} + } + send({ + path: 'update/log', + qs: opts + }, callback) + }) } } diff --git a/src/api/util/fs-add.js b/src/api/util/fs-add.js new file mode 100644 index 000000000..c78dda13a --- /dev/null +++ b/src/api/util/fs-add.js @@ -0,0 +1,39 @@ +'use strict' + +const isNode = require('detect-node') +const addToDagNodesTransform = require('./../../add-to-dagnode-transform') +const promisify = require('promisify-es6') + +module.exports = (send) => { + return promisify((path, opts, callback) => { + if (typeof opts === 'function' && + callback === undefined) { + callback = opts + opts = {} + } + + // opts is the real callback -- + // 'callback' is being injected by promisify + if (typeof opts === 'function' && + typeof callback === 'function') { + callback = opts + opts = {} + } + + if (!isNode) { + return callback(new Error('fsAdd does not work in the browser')) + } + + if (typeof path !== 'string') { + return callback(new Error('"path" must be a string')) + } + + const sendWithTransform = send.withTransform(addToDagNodesTransform) + + sendWithTransform({ + path: 'add', + qs: opts, + files: path + }, callback) + }) +} diff --git a/src/api/util/url-add.js b/src/api/util/url-add.js new file mode 100644 index 000000000..f8707ca9d --- /dev/null +++ b/src/api/util/url-add.js @@ -0,0 +1,43 @@ +'use strict' + +const Wreck = require('wreck') +const addToDagNodesTransform = require('./../../add-to-dagnode-transform') + +const promisify = require('promisify-es6') + +module.exports = (send) => { + return promisify((url, opts, callback) => { + if (typeof (opts) === 'function' && + callback === undefined) { + callback = opts + opts = {} + } + + // opts is the real callback -- + // 'callback' is being injected by promisify + if (typeof opts === 'function' && + typeof callback === 'function') { + callback = opts + opts = {} + } + + if (typeof url !== 'string' || + !url.startsWith('http')) { + return callback(new Error('"url" param must be an http(s) url')) + } + + const sendWithTransform = send.withTransform(addToDagNodesTransform) + + Wreck.request('GET', url, null, (err, res) => { + if (err) { + return callback(err) + } + + sendWithTransform({ + path: 'add', + qs: opts, + files: res + }, callback) + }) + }) +} diff --git a/src/api/version.js b/src/api/version.js index 9221b6275..5548b63f3 100644 --- a/src/api/version.js +++ b/src/api/version.js @@ -1,7 +1,27 @@ 'use strict' -const command = require('../cmd-helpers').command +const promisify = require('promisify-es6') module.exports = (send) => { - return command(send, 'version') + return promisify((opts, callback) => { + if (typeof opts === 'function') { + callback = opts + opts = {} + } + + send({ + path: 'version', + qs: opts + }, (err, result) => { + if (err) { + return callback(err) + } + const version = { + version: result.Version, + commit: result.Commit, + repo: result.Repo + } + callback(null, version) + }) + }) } diff --git a/src/cmd-helpers.js b/src/cmd-helpers.js deleted file mode 100644 index 072c34825..000000000 --- a/src/cmd-helpers.js +++ /dev/null @@ -1,21 +0,0 @@ -'use strict' - -exports.command = function command (send, name) { - return (opts, cb) => { - if (typeof (opts) === 'function') { - cb = opts - opts = {} - } - return send(name, null, opts, null, cb) - } -} - -exports.argCommand = function argCommand (send, name) { - return (arg, opts, cb) => { - if (typeof (opts) === 'function') { - cb = opts - opts = {} - } - return send(name, arg, opts, null, cb) - } -} diff --git a/src/config.js b/src/default-config.js similarity index 100% rename from src/config.js rename to src/default-config.js diff --git a/src/get-dagnode.js b/src/get-dagnode.js index 3d60844c9..ce0afd674 100644 --- a/src/get-dagnode.js +++ b/src/get-dagnode.js @@ -4,38 +4,44 @@ const DAGNode = require('ipfs-merkle-dag').DAGNode const bl = require('bl') const async = require('async') -module.exports = function (send, hash, cb) { +module.exports = function (send, hash, callback) { // Retrieve the object and its data in parallel, then produce a DAGNode // instance using this information. async.parallel([ function get (done) { - send('object/get', hash, null, null, done) + send({ + path: 'object/get', + args: hash + }, done) }, function data (done) { // WORKAROUND: request the object's data separately, since raw bits in JSON // are interpreted as UTF-8 and corrupt the data. // See https://github.com/ipfs/go-ipfs/issues/1582 for more details. - send('object/data', hash, null, null, done) + send({ + path: 'object/data', + args: hash + }, done) }], function done (err, res) { if (err) { - return cb(err) + return callback(err) } var object = res[0] var stream = res[1] if (Buffer.isBuffer(stream)) { - cb(err, new DAGNode(stream, object.Links)) + callback(err, new DAGNode(stream, object.Links)) } else { stream.pipe(bl(function (err, data) { if (err) { - return cb(err) + return callback(err) } - cb(err, new DAGNode(data, object.Links)) + callback(err, new DAGNode(data, object.Links)) })) } }) diff --git a/src/get-files-stream.js b/src/get-files-stream.js index f723b34fd..485e06cce 100644 --- a/src/get-files-stream.js +++ b/src/get-files-stream.js @@ -93,7 +93,9 @@ function loadPaths (opts, file) { } function getFilesStream (files, opts) { - if (!files) return null + if (!files) { + return null + } const mp = new Multipart() diff --git a/src/index.js b/src/index.js index a150458d3..e5b4f3399 100644 --- a/src/index.js +++ b/src/index.js @@ -2,7 +2,7 @@ const multiaddr = require('multiaddr') const loadCommands = require('./load-commands') -const getConfig = require('./config') +const getConfig = require('./default-config') const getRequestAPI = require('./request-api') function IpfsAPI (hostOrMultiaddr, port, opts) { diff --git a/src/load-commands.js b/src/load-commands.js index ebd832de7..4b173cec8 100644 --- a/src/load-commands.js +++ b/src/load-commands.js @@ -2,8 +2,9 @@ function requireCommands () { const cmds = { - add: require('./api/add'), // add alias - createAddStream: require('./api/add-stream'), // add stream alias + // add and createAddStream alias + add: require('./api/add'), + createAddStream: require('./api/create-add-stream'), bitswap: require('./api/bitswap'), block: require('./api/block'), bootstrap: require('./api/bootstrap'), @@ -33,7 +34,7 @@ function requireCommands () { cmds.files = function (send) { const files = require('./api/files')(send) files.add = require('./api/add')(send) - files.createAddStream = require('./api/add-stream.js')(send) + files.createAddStream = require('./api/create-add-stream.js')(send) files.get = require('./api/get')(send) // aliases @@ -46,8 +47,9 @@ function requireCommands () { cmds.util = function (send) { const util = { - addFiles: require('./api/add-files')(send), - addUrl: require('./api/add-url')(send) + addFromFs: require('./api/util/fs-add')(send), + addFromStream: require('./api/add')(send), + addFromURL: require('./api/util/url-add')(send) } return util } diff --git a/src/request-api.js b/src/request-api.js index a5c01ea4c..2467a005b 100644 --- a/src/request-api.js +++ b/src/request-api.js @@ -4,7 +4,6 @@ const Wreck = require('wreck') const Qs = require('qs') const ndjson = require('ndjson') const getFilesStream = require('./get-files-stream') -const Counter = require('passthrough-counter') const isNode = require('detect-node') @@ -12,9 +11,7 @@ const isNode = require('detect-node') function parseChunkedJson (res, cb) { const parsed = [] - const c = new Counter() res - .pipe(c) .pipe(ndjson.parse()) .on('data', (obj) => { parsed.push(obj) @@ -32,7 +29,8 @@ function onRes (buffer, cb, uri) { const stream = Boolean(res.headers['x-stream-output']) const chunkedObjects = Boolean(res.headers['x-chunked-output']) - const isJson = res.headers['content-type'] && res.headers['content-type'].indexOf('application/json') === 0 + const isJson = res.headers['content-type'] && + res.headers['content-type'].indexOf('application/json') === 0 if (res.statusCode >= 400 || !res.statusCode) { const error = new Error(`Server responded with ${res.statusCode}`) @@ -65,39 +63,47 @@ function onRes (buffer, cb, uri) { } } -function requestAPI (config, path, args, qs, files, buffer, cb) { - qs = qs || {} +function requestAPI (config, options, callback) { + options.qs = options.qs || {} - if (Array.isArray(files)) { - qs.recursive = true + if (Array.isArray(options.files)) { + options.qs.recursive = true } - if (Array.isArray(path)) path = path.join('/') - if (args && !Array.isArray(args)) args = [args] - if (args) qs.arg = args - if (files && !Array.isArray(files)) files = [files] + if (Array.isArray(options.path)) { + options.path = options.path.join('/') + } + if (options.args && !Array.isArray(options.args)) { + options.args = [options.args] + } + if (options.args) { + options.qs.arg = options.args + } + if (options.files && !Array.isArray(options.files)) { + options.files = [options.files] + } - if (qs.r) { - qs.recursive = qs.r + if (options.qs.r) { + options.qs.recursive = options.qs.r // From IPFS 0.4.0, it throws an error when both r and recursive are passed - delete qs.r + delete options.qs.r } - qs['stream-channels'] = true + options.qs['stream-channels'] = true let stream - if (files) { - stream = getFilesStream(files, qs) + if (options.files) { + stream = getFilesStream(options.files, options.qs) } // this option is only used internally, not passed to daemon - delete qs.followSymlinks + delete options.qs.followSymlinks const port = config.port ? `:${config.port}` : '' const opts = { - method: files ? 'POST' : 'GET', - uri: `${config.protocol}://${config.host}${port}${config['api-path']}${path}?${Qs.stringify(qs, {arrayFormat: 'repeat'})}`, + method: 'POST', + uri: `${config.protocol}://${config.host}${port}${config['api-path']}${options.path}?${Qs.stringify(options.qs, {arrayFormat: 'repeat'})}`, headers: {} } @@ -106,72 +112,54 @@ function requestAPI (config, path, args, qs, files, buffer, cb) { opts.headers['User-Agent'] = config['user-agent'] } - if (files) { + if (options.files) { if (!stream.boundary) { - return cb(new Error('No boundary in multipart stream')) + return callback(new Error('No boundary in multipart stream')) } opts.headers['Content-Type'] = `multipart/form-data; boundary=${stream.boundary}` - opts.downstreamRes = stream opts.payload = stream } - return Wreck.request(opts.method, opts.uri, opts, onRes(buffer, cb, opts.uri)) + return Wreck.request(opts.method, opts.uri, opts, onRes(options.buffer, callback, opts.uri)) } -// -- Interface +// +// -- Module Interface exports = module.exports = function getRequestAPI (config) { - var send = function (path, args, qs, files, buffer, cb) { - if (typeof buffer === 'function') { - cb = buffer - buffer = false + /* + * options: { + * path: // API path (like /add or /config) - type: string + * args: // Arguments to the command - type: object + * qs: // Opts as query string opts to the command --something - type: object + * files: // files to be sent - type: string, buffer or array of strings or buffers + * buffer: // buffer the request before sending it - type: bool + * } + */ + const send = function (options, callback) { + if (typeof options !== 'object') { + return callback(new Error('no options were passed')) } - if (typeof cb !== 'function' && typeof Promise !== 'undefined') { - return new Promise(function (resolve, reject) { - requestAPI(config, path, args, qs, files, buffer, function (err, res) { - if (err) return reject(err) - resolve(res) - }) - }) - } - - return requestAPI(config, path, args, qs, files, buffer, cb) + return requestAPI(config, options, callback) } // Wraps the 'send' function such that an asynchronous // transform may be applied to its result before // passing it on to either its callback or promise. send.withTransform = function (transform) { - return function (path, args, qs, files, buffer, cb) { - if (typeof buffer === 'function') { - cb = buffer - buffer = false + return function (options, callback) { + if (typeof options !== 'object') { + return callback(new Error('no options were passed')) } - var p = send(path, args, qs, files, buffer, wrap(cb)) - - if (p instanceof Promise) { - return p.then((res) => { - return new Promise(function (resolve, reject) { - transform(null, res, send, function (err, res) { - if (err) { - reject(err) - } else { - resolve(res) - } - }) - }) - }) - } else { - return p - } + send(options, wrap(callback)) - function wrap (done) { - if (done) { + function wrap (func) { + if (func) { return function (err, res) { - transform(err, res, send, done) + transform(err, res, send, func) } } } diff --git a/test/interface-ipfs-core/block.spec.js b/test/interface-ipfs-core/block.spec.js index 5fedd8f0e..2254715a2 100644 --- a/test/interface-ipfs-core/block.spec.js +++ b/test/interface-ipfs-core/block.spec.js @@ -1,86 +1,20 @@ /* eslint-env mocha */ -/* eslint max-nested-callbacks: ["error", 8] */ -/* globals apiClients */ -'use strict' - -const expect = require('chai').expect - -describe('.block', () => { - const blorbKey = 'QmPv52ekjS75L4JmHpXVeuJ5uX2ecSfSZo88NSyxwA3rAQ' - const blorb = Buffer('blorb') - - it('returns an error when putting an array of files', () => { - return apiClients.a.block.put([blorb, blorb], (err) => { - expect(err).to.be.an.instanceof(Error) - }) - }) - it('block.put', (done) => { - apiClients.a.block.put(blorb, (err, res) => { - expect(err).to.not.exist - expect(res).to.have.a.property('Key', 'QmPv52ekjS75L4JmHpXVeuJ5uX2ecSfSZo88NSyxwA3rAQ') - done() - }) - }) - - it('block.get', (done) => { - apiClients.a.block.get(blorbKey, (err, res) => { - expect(err).to.not.exist - - let buf = '' - res - .on('data', function (data) { buf += data }) - .on('end', function () { - expect(buf).to.be.equal('blorb') - done() - }) - }) - }) - - it('block.stat', (done) => { - apiClients.a.block.stat(blorbKey, (err, res) => { - expect(err).to.not.exist - expect(res).to.have.property('Key') - expect(res).to.have.property('Size') - done() - }) - }) +'use strict' - describe('promise', () => { - it('returns an error when putting an array of files', () => { - return apiClients.a.block.put([blorb, blorb]) - .catch((err) => { - expect(err).to.be.an.instanceof(Error) - }) - }) +const test = require('interface-ipfs-core') +const FactoryClient = require('../factory/factory-client') - it('block.put', () => { - return apiClients.a.block.put(blorb) - .then((res) => { - expect(res).to.have.a.property('Key', 'QmPv52ekjS75L4JmHpXVeuJ5uX2ecSfSZo88NSyxwA3rAQ') - }) - }) +let fc - it('block.get', (done) => { - apiClients.a.block.get(blorbKey) - .then((res) => { - let buf = '' - res - .on('data', function (data) { buf += data }) - .on('end', function () { - expect(buf).to.be.equal('blorb') - done() - }) - }) - .catch(done) - }) +const common = { + setup: function (callback) { + fc = new FactoryClient() + callback(null, fc) + }, + teardown: function (callback) { + fc.dismantle(callback) + } +} - it('block.stat', () => { - return apiClients.a.block.stat(blorbKey) - .then((res) => { - expect(res).to.have.property('Key') - expect(res).to.have.property('Size') - }) - }) - }) -}) +test.block(common) diff --git a/test/interface-ipfs-core/bootstrap.spec.js b/test/interface-ipfs-core/bootstrap.spec.js index 8cecb7978..4b04f92ac 100644 --- a/test/interface-ipfs-core/bootstrap.spec.js +++ b/test/interface-ipfs-core/bootstrap.spec.js @@ -1,33 +1,43 @@ /* eslint-env mocha */ /* eslint max-nested-callbacks: ["error", 8] */ -/* globals apiClients */ 'use strict' const expect = require('chai').expect +const FactoryClient = require('../factory/factory-client') const invalidArg = 'this/Is/So/Invalid/' const validIp4 = '/ip4/104.236.176.52/tcp/4001/ipfs/QmSoLnSGccFuZQJzRadHn95W2CrSFmZuTdDWP8HXaHca9z' describe('.bootstrap', () => { + let ipfs + let fc + + before(function (done) { + this.timeout(20 * 1000) // slow CI + fc = new FactoryClient() + fc.spawnNode((err, node) => { + expect(err).to.not.exist + ipfs = node + done() + }) + }) + + after((done) => { + fc.dismantle(done) + }) + let peers describe('.add', () => { - it('returns an error when called without args or options', (done) => { - return apiClients.a.bootstrap.add(null, (err) => { - expect(err).to.be.an.instanceof(Error) - done() - }) - }) - it('returns an error when called with an invalid arg', (done) => { - return apiClients.a.bootstrap.add(invalidArg, (err) => { + ipfs.bootstrap.add(invalidArg, (err) => { expect(err).to.be.an.instanceof(Error) done() }) }) it('returns a list of containing the bootstrap peer when called with a valid arg (ip4)', (done) => { - return apiClients.a.bootstrap.add(validIp4, (err, res) => { + ipfs.bootstrap.add(validIp4, (err, res) => { expect(err).to.not.exist expect(res).to.be.eql({ Peers: [validIp4] }) peers = res.Peers @@ -38,7 +48,7 @@ describe('.bootstrap', () => { }) it('returns a list of bootstrap peers when called with the default option', (done) => { - return apiClients.a.bootstrap.add(null, { default: true }, (err, res) => { + ipfs.bootstrap.add({ default: true }, (err, res) => { expect(err).to.not.exist peers = res.Peers expect(peers).to.exist @@ -50,7 +60,7 @@ describe('.bootstrap', () => { describe('.list', () => { it('returns a list of peers', (done) => { - return apiClients.a.bootstrap.list((err, res) => { + ipfs.bootstrap.list((err, res) => { expect(err).to.not.exist peers = res.Peers expect(peers).to.exist @@ -61,14 +71,14 @@ describe('.bootstrap', () => { describe('.rm', () => { it('returns an error when called with an invalid arg', (done) => { - return apiClients.a.bootstrap.rm(invalidArg, (err) => { + ipfs.bootstrap.rm(invalidArg, (err) => { expect(err).to.be.an.instanceof(Error) done() }) }) it('returns empty list because no peers removed when called without an arg or options', (done) => { - return apiClients.a.bootstrap.rm(null, (err, res) => { + ipfs.bootstrap.rm(null, (err, res) => { expect(err).to.not.exist peers = res.Peers expect(peers).to.exist @@ -78,7 +88,7 @@ describe('.bootstrap', () => { }) it('returns list containing the peer removed when called with a valid arg (ip4)', (done) => { - return apiClients.a.bootstrap.rm(null, (err, res) => { + ipfs.bootstrap.rm(null, (err, res) => { expect(err).to.not.exist peers = res.Peers expect(peers).to.exist @@ -88,7 +98,7 @@ describe('.bootstrap', () => { }) it('returns list of all peers removed when all option is passed', (done) => { - return apiClients.a.bootstrap.rm(null, { all: true }, (err, res) => { + ipfs.bootstrap.rm(null, { all: true }, (err, res) => { expect(err).to.not.exist peers = res.Peers expect(peers).to.exist @@ -100,21 +110,21 @@ describe('.bootstrap', () => { describe('.promise', () => { describe('.add', () => { it('returns an error when called without args or options', () => { - return apiClients.a.bootstrap.add(null) + return ipfs.bootstrap.add(null) .catch((err) => { expect(err).to.be.an.instanceof(Error) }) }) it('returns an error when called with an invalid arg', () => { - return apiClients.a.bootstrap.add(invalidArg) + return ipfs.bootstrap.add(invalidArg) .catch((err) => { expect(err).to.be.an.instanceof(Error) }) }) it('returns a list of peers when called with a valid arg (ip4)', () => { - return apiClients.a.bootstrap.add(validIp4) + return ipfs.bootstrap.add(validIp4) .then((res) => { expect(res).to.be.eql({ Peers: [validIp4] }) peers = res.Peers @@ -124,7 +134,7 @@ describe('.bootstrap', () => { }) it('returns a list of default peers when called with the default option', () => { - return apiClients.a.bootstrap.add(null, { default: true }) + return ipfs.bootstrap.add(null, { default: true }) .then((res) => { peers = res.Peers expect(peers).to.exist @@ -135,7 +145,7 @@ describe('.bootstrap', () => { describe('.list', () => { it('returns a list of peers', () => { - return apiClients.a.bootstrap.list() + return ipfs.bootstrap.list() .then((res) => { peers = res.Peers expect(peers).to.exist @@ -145,14 +155,14 @@ describe('.bootstrap', () => { describe('.rm', () => { it('returns an error when called with an invalid arg', () => { - return apiClients.a.bootstrap.rm(invalidArg) + return ipfs.bootstrap.rm(invalidArg) .catch((err) => { expect(err).to.be.an.instanceof(Error) }) }) it('returns empty list when called without an arg or options', () => { - return apiClients.a.bootstrap.rm(null) + return ipfs.bootstrap.rm(null) .then((res) => { peers = res.Peers expect(peers).to.exist @@ -161,7 +171,7 @@ describe('.bootstrap', () => { }) it('returns list containing the peer removed when called with a valid arg (ip4)', () => { - return apiClients.a.bootstrap.rm(null) + return ipfs.bootstrap.rm(null) .then((res) => { peers = res.Peers expect(peers).to.exist @@ -170,7 +180,7 @@ describe('.bootstrap', () => { }) it('returns list of all peers removed when all option is passed', () => { - return apiClients.a.bootstrap.rm(null, { all: true }) + return ipfs.bootstrap.rm(null, { all: true }) .then((res) => { peers = res.Peers expect(peers).to.exist diff --git a/test/interface-ipfs-core/commands.spec.js b/test/interface-ipfs-core/commands.spec.js index a3fff5556..e18b0ca24 100644 --- a/test/interface-ipfs-core/commands.spec.js +++ b/test/interface-ipfs-core/commands.spec.js @@ -1,12 +1,29 @@ /* eslint-env mocha */ -/* globals apiClients */ 'use strict' const expect = require('chai').expect +const FactoryClient = require('../factory/factory-client') describe('.commands', () => { + let ipfs + let fc + + before(function (done) { + this.timeout(20 * 1000) // slow CI + fc = new FactoryClient() + fc.spawnNode((err, node) => { + expect(err).to.not.exist + ipfs = node + done() + }) + }) + + after((done) => { + fc.dismantle(done) + }) + it('lists commands', (done) => { - apiClients.a.commands((err, res) => { + ipfs.commands((err, res) => { expect(err).to.not.exist expect(res).to.exist done() @@ -15,7 +32,7 @@ describe('.commands', () => { describe('promise', () => { it('lists commands', () => { - return apiClients.a.commands() + return ipfs.commands() .then((res) => { expect(res).to.exist }) diff --git a/test/interface-ipfs-core/config.spec.js b/test/interface-ipfs-core/config.spec.js index ea0a9610c..794fd4678 100644 --- a/test/interface-ipfs-core/config.spec.js +++ b/test/interface-ipfs-core/config.spec.js @@ -1,135 +1,20 @@ /* eslint-env mocha */ /* eslint max-nested-callbacks: ["error", 8] */ -/* globals apiClients */ 'use strict' -const expect = require('chai').expect -const isNode = require('detect-node') -const path = require('path') +const test = require('interface-ipfs-core') +const FactoryClient = require('../factory/factory-client') -describe('.config', () => { - describe('.config.{set, get}', () => { - it('string', (done) => { - const confKey = 'arbitraryKey' - const confVal = 'arbitraryVal' +let fc - apiClients.a.config.set(confKey, confVal, (err, res) => { - expect(err).to.not.exist - apiClients.a.config.get(confKey, (err, res) => { - expect(err).to.not.exist - expect(res).to.have.a.property('Value', confVal) - done() - }) - }) - }) +const common = { + setup: function (callback) { + fc = new FactoryClient() + callback(null, fc) + }, + teardown: function (callback) { + fc.dismantle(callback) + } +} - it('bool', (done) => { - const confKey = 'otherKey' - const confVal = true - - apiClients.a.config.set(confKey, confVal, (err, res) => { - expect(err).to.not.exist - apiClients.a.config.get(confKey, (err, res) => { - expect(err).to.not.exist - expect(res.Value).to.deep.equal(confVal) - done() - }) - }) - }) - - it('json', (done) => { - const confKey = 'API.HTTPHeaders.Access-Control-Allow-Origin' - const confVal = ['http://example.io'] - - apiClients.a.config.set(confKey, confVal, (err, res) => { - expect(err).to.not.exist - apiClients.a.config.get(confKey, (err, res) => { - expect(err).to.not.exist - expect(res.Value).to.deep.equal(confVal) - done() - }) - }) - }) - }) - - it('.config.show', (done) => { - apiClients.c.config.show((err, res) => { - expect(err).to.not.exist - expect(res).to.exist - done() - }) - }) - - it('.config.replace', (done) => { - if (!isNode) { - return done() - } - - apiClients.c.config.replace(path.join(__dirname, '/../data/r-config.json'), (err, res) => { - expect(err).to.not.exist - expect(res).to.be.equal(null) - done() - }) - }) - - describe('promise', () => { - describe('.config.{set, get}', () => { - it('string', () => { - const confKey = 'arbitraryKey' - const confVal = 'arbitraryVal' - - return apiClients.a.config.set(confKey, confVal) - .then((res) => { - return apiClients.a.config.get(confKey) - }) - .then((res) => { - expect(res).to.have.a.property('Value', confVal) - }) - }) - - it('bool', () => { - const confKey = 'otherKey' - const confVal = true - - return apiClients.a.config.set(confKey, confVal) - .then((res) => { - return apiClients.a.config.get(confKey) - }) - .then((res) => { - expect(res.Value).to.deep.equal(confVal) - }) - }) - - it('json', () => { - const confKey = 'API.HTTPHeaders.Access-Control-Allow-Origin' - const confVal = ['http://example.com'] - - return apiClients.a.config.set(confKey, confVal) - .then((res) => { - return apiClients.a.config.get(confKey) - }) - .then((res) => { - expect(res.Value).to.deep.equal(confVal) - }) - }) - }) - - it('.config.show', () => { - return apiClients.c.config.show() - .then((res) => { - expect(res).to.exist - }) - }) - - it('.config.replace', () => { - if (!isNode) { - return - } - - return apiClients.c.config.replace(path.join(__dirname, '/../data/r-config.json')) - .then((res) => { - expect(res).to.be.equal(null) - }) - }) - }) -}) +test.config(common) diff --git a/test/interface-ipfs-core/diag.spec.js b/test/interface-ipfs-core/diag.spec.js index a7097f7e5..198248343 100644 --- a/test/interface-ipfs-core/diag.spec.js +++ b/test/interface-ipfs-core/diag.spec.js @@ -1,12 +1,29 @@ /* eslint-env mocha */ -/* globals apiClients */ 'use strict' +const FactoryClient = require('../factory/factory-client') const expect = require('chai').expect describe('.diag', () => { + let ipfs + let fc + + before(function (done) { + this.timeout(20 * 1000) // slow CI + fc = new FactoryClient() + fc.spawnNode((err, node) => { + expect(err).to.not.exist + ipfs = node + done() + }) + }) + + after((done) => { + fc.dismantle(done) + }) + it('.diag.net', (done) => { - apiClients.a.diag.net((err, res) => { + ipfs.diag.net((err, res) => { expect(err).to.not.exist expect(res).to.exist done() @@ -14,7 +31,7 @@ describe('.diag', () => { }) it('.diag.sys', (done) => { - apiClients.a.diag.sys((err, res) => { + ipfs.diag.sys((err, res) => { expect(err).to.not.exist expect(res).to.exist expect(res).to.have.a.property('memory') @@ -24,7 +41,7 @@ describe('.diag', () => { }) it('.diag.cmds', (done) => { - apiClients.a.diag.cmds((err, res) => { + ipfs.diag.cmds((err, res) => { expect(err).to.not.exist expect(res).to.exist done() @@ -33,14 +50,14 @@ describe('.diag', () => { describe('promise', () => { it('.diag.net', () => { - return apiClients.a.diag.net() + return ipfs.diag.net() .then((res) => { expect(res).to.exist }) }) it('.diag.sys', () => { - return apiClients.a.diag.sys() + return ipfs.diag.sys() .then((res) => { expect(res).to.exist expect(res).to.have.a.property('memory') @@ -49,7 +66,7 @@ describe('.diag', () => { }) it('.diag.cmds', () => { - return apiClients.a.diag.cmds() + return ipfs.diag.cmds() .then((res) => { expect(res).to.exist }) diff --git a/test/interface-ipfs-core/files.spec.js b/test/interface-ipfs-core/files.spec.js index d40187b6a..bed5c1506 100644 --- a/test/interface-ipfs-core/files.spec.js +++ b/test/interface-ipfs-core/files.spec.js @@ -1,6 +1,5 @@ /* eslint-env mocha */ /* eslint max-nested-callbacks: ["error", 8] */ -/* globals apiClients */ 'use strict' const expect = require('chai').expect @@ -28,10 +27,27 @@ test.files(common) // mfs tests describe('.files (pseudo mfs)', () => { + let ipfs + let fc + + before(function (done) { + this.timeout(20 * 1000) // slow CI + fc = new FactoryClient() + fc.spawnNode((err, node) => { + expect(err).to.not.exist + ipfs = node + done() + }) + }) + + after((done) => { + fc.dismantle(done) + }) + it('add file for testing', (done) => { const expectedMultihash = 'Qma4hjFTnCasJ8PVp3mZbZK5g2vGDT4LByLJ7m8ciyRFZP' - apiClients.a.files.add(testfile, (err, res) => { + ipfs.files.add(testfile, (err, res) => { expect(err).to.not.exist expect(res).to.have.length(1) @@ -42,14 +58,14 @@ describe('.files (pseudo mfs)', () => { }) it('files.mkdir', (done) => { - apiClients.a.files.mkdir('/test-folder', function (err) { + ipfs.files.mkdir('/test-folder', function (err) { expect(err).to.not.exist done() }) }) it('files.cp', (done) => { - apiClients.a.files + ipfs.files .cp(['/ipfs/Qma4hjFTnCasJ8PVp3mZbZK5g2vGDT4LByLJ7m8ciyRFZP', '/test-folder/test-file'], (err) => { expect(err).to.not.exist done() @@ -57,7 +73,7 @@ describe('.files (pseudo mfs)', () => { }) it('files.ls', (done) => { - apiClients.a.files.ls('/test-folder', (err, res) => { + ipfs.files.ls('/test-folder', (err, res) => { expect(err).to.not.exist expect(res.Entries.length).to.equal(1) done() @@ -65,11 +81,11 @@ describe('.files (pseudo mfs)', () => { }) it('files.write', (done) => { - apiClients.a.files + ipfs.files .write('/test-folder/test-file-2.txt', new Buffer('hello world'), {create: true}, (err) => { expect(err).to.not.exist - apiClients.a.files.read('/test-folder/test-file-2.txt', (err, stream) => { + ipfs.files.read('/test-folder/test-file-2.txt', (err, stream) => { expect(err).to.not.exist let buf = '' @@ -89,11 +105,11 @@ describe('.files (pseudo mfs)', () => { }) it('files.write without options', (done) => { - apiClients.a.files + ipfs.files .write('/test-folder/test-file-2.txt', new Buffer('hello world'), (err) => { expect(err).to.not.exist - apiClients.a.files.read('/test-folder/test-file-2.txt', (err, stream) => { + ipfs.files.read('/test-folder/test-file-2.txt', (err, stream) => { expect(err).to.not.exist let buf = '' @@ -113,7 +129,7 @@ describe('.files (pseudo mfs)', () => { }) it('files.stat', (done) => { - apiClients.a.files.stat('/test-folder/test-file', (err, res) => { + ipfs.files.stat('/test-folder/test-file', (err, res) => { expect(err).to.not.exist expect(res).to.deep.equal({ Hash: 'Qma4hjFTnCasJ8PVp3mZbZK5g2vGDT4LByLJ7m8ciyRFZP', @@ -128,7 +144,7 @@ describe('.files (pseudo mfs)', () => { }) it('files.stat file that does not exist', (done) => { - apiClients.a.files.stat('/test-folder/does-not-exist', (err, res) => { + ipfs.files.stat('/test-folder/does-not-exist', (err, res) => { expect(err).to.exist if (err.code === 0) { return done() @@ -142,7 +158,7 @@ describe('.files (pseudo mfs)', () => { return done() } - apiClients.a.files.read('/test-folder/test-file', (err, stream) => { + ipfs.files.read('/test-folder/test-file', (err, stream) => { expect(err).to.not.exist let buf = '' stream @@ -160,14 +176,14 @@ describe('.files (pseudo mfs)', () => { }) it('files.rm without options', (done) => { - apiClients.a.files.rm('/test-folder/test-file-2.txt', (err) => { + ipfs.files.rm('/test-folder/test-file-2.txt', (err) => { expect(err).to.not.exist done() }) }) it('files.rm', (done) => { - apiClients.a.files.rm('/test-folder', {recursive: true}, (err) => { + ipfs.files.rm('/test-folder', {recursive: true}, (err) => { expect(err).to.not.exist done() }) @@ -175,26 +191,26 @@ describe('.files (pseudo mfs)', () => { describe('promise', () => { it('files.mkdir', () => { - return apiClients.a.files.mkdir('/test-folder') + return ipfs.files.mkdir('/test-folder') }) it('files.cp', () => { - return apiClients.a.files + return ipfs.files .cp(['/ipfs/Qma4hjFTnCasJ8PVp3mZbZK5g2vGDT4LByLJ7m8ciyRFZP', '/test-folder/test-file']) }) it('files.ls', () => { - return apiClients.a.files.ls('/test-folder') + return ipfs.files.ls('/test-folder') .then((res) => { expect(res.Entries.length).to.equal(1) }) }) it('files.write', (done) => { - apiClients.a.files + ipfs.files .write('/test-folder/test-file-2.txt', new Buffer('hello world'), {create: true}) .then(() => { - return apiClients.a.files.read('/test-folder/test-file-2.txt') + return ipfs.files.read('/test-folder/test-file-2.txt') }) .then((stream) => { let buf = '' @@ -214,10 +230,10 @@ describe('.files (pseudo mfs)', () => { }) it('files.write without options', (done) => { - apiClients.a.files + ipfs.files .write('/test-folder/test-file-2.txt', new Buffer('hello world')) .then(() => { - return apiClients.a.files.read('/test-folder/test-file-2.txt') + return ipfs.files.read('/test-folder/test-file-2.txt') }) .then((stream) => { let buf = '' @@ -237,7 +253,7 @@ describe('.files (pseudo mfs)', () => { }) it('files.stat', () => { - return apiClients.a.files.stat('/test-folder/test-file') + return ipfs.files.stat('/test-folder/test-file') .then((res) => { expect(res).to.deep.equal({ Hash: 'Qma4hjFTnCasJ8PVp3mZbZK5g2vGDT4LByLJ7m8ciyRFZP', @@ -250,7 +266,7 @@ describe('.files (pseudo mfs)', () => { }) it('files.stat file that does not exist', () => { - return apiClients.a.files.stat('/test-folder/does-not-exist') + return ipfs.files.stat('/test-folder/does-not-exist') .catch((err) => { expect(err).to.exist expect(err.code).to.be.eql(0) @@ -262,7 +278,7 @@ describe('.files (pseudo mfs)', () => { return done() } - apiClients.a.files.read('/test-folder/test-file') + ipfs.files.read('/test-folder/test-file') .then((stream) => { let buf = '' stream @@ -280,11 +296,11 @@ describe('.files (pseudo mfs)', () => { }) it('files.rm without options', () => { - return apiClients.a.files.rm('/test-folder/test-file-2.txt') + return ipfs.files.rm('/test-folder/test-file-2.txt') }) it('files.rm', () => { - return apiClients.a.files.rm('/test-folder', {recursive: true}) + return ipfs.files.rm('/test-folder', {recursive: true}) }) }) }) diff --git a/test/interface-ipfs-core/generic.spec.js b/test/interface-ipfs-core/generic.spec.js new file mode 100644 index 000000000..6731ad9bb --- /dev/null +++ b/test/interface-ipfs-core/generic.spec.js @@ -0,0 +1,20 @@ +/* eslint-env mocha */ + +'use strict' + +const test = require('interface-ipfs-core') +const FactoryClient = require('../factory/factory-client') + +let fc + +const common = { + setup: function (callback) { + fc = new FactoryClient() + callback(null, fc) + }, + teardown: function (callback) { + fc.dismantle(callback) + } +} + +test.generic(common) diff --git a/test/interface-ipfs-core/get.spec.js b/test/interface-ipfs-core/get.spec.js index 2bf1f9f73..b989811c7 100644 --- a/test/interface-ipfs-core/get.spec.js +++ b/test/interface-ipfs-core/get.spec.js @@ -1,6 +1,5 @@ /* eslint-env mocha */ /* eslint max-nested-callbacks: ["error", 8] */ -/* globals apiClients */ 'use strict' @@ -11,6 +10,7 @@ const concat = require('concat-stream') const through = require('through2') const streamEqual = require('stream-equal') const path = require('path') +const FactoryClient = require('../factory/factory-client') const testfile = fs.readFileSync(path.join(__dirname, '/../data/testfile.txt')) @@ -22,8 +22,38 @@ if (isNode) { } describe('.get', () => { + let ipfs + let fc + + before(function (done) { + this.timeout(20 * 1000) // slow CI + fc = new FactoryClient() + fc.spawnNode((err, node) => { + expect(err).to.not.exist + ipfs = node + done() + }) + }) + + after((done) => { + fc.dismantle(done) + }) + + it('add file for testing', (done) => { + const expectedMultihash = 'Qma4hjFTnCasJ8PVp3mZbZK5g2vGDT4LByLJ7m8ciyRFZP' + + ipfs.files.add(testfile, (err, res) => { + expect(err).to.not.exist + + expect(res).to.have.length(1) + expect(res[0].hash).to.equal(expectedMultihash) + expect(res[0].path).to.equal(expectedMultihash) + done() + }) + }) + it('get with no compression args', (done) => { - apiClients.a + ipfs .get('Qma4hjFTnCasJ8PVp3mZbZK5g2vGDT4LByLJ7m8ciyRFZP', (err, res) => { expect(err).to.not.exist @@ -46,7 +76,7 @@ describe('.get', () => { }) it('get with archive true', (done) => { - apiClients.a + ipfs .get('Qma4hjFTnCasJ8PVp3mZbZK5g2vGDT4LByLJ7m8ciyRFZP', {archive: true}, (err, res) => { expect(err).to.not.exist @@ -69,7 +99,7 @@ describe('.get', () => { }) it('get err with out of range compression level', (done) => { - apiClients.a + ipfs .get('Qma4hjFTnCasJ8PVp3mZbZK5g2vGDT4LByLJ7m8ciyRFZP', {compress: true, 'compression-level': 10}, (err, res) => { expect(err).to.exist expect(err.toString()).to.equal('Error: Compression level must be between 1 and 9') @@ -78,7 +108,7 @@ describe('.get', () => { }) it('get with compression level', (done) => { - apiClients.a + ipfs .get('Qma4hjFTnCasJ8PVp3mZbZK5g2vGDT4LByLJ7m8ciyRFZP', {compress: true, 'compression-level': 1}, (err, res) => { expect(err).to.not.exist done() @@ -93,7 +123,7 @@ describe('.get', () => { const bigFile = fs.readFileSync(tfbPath) const expectedMultihash = 'Qme79tX2bViL26vNjPsF3DP1R9rMKMvnPYJiKTTKPrXJjq' - apiClients.a.files.add(bigFile, (err, res) => { + ipfs.files.add(bigFile, (err, res) => { expect(err).to.not.exist expect(res).to.have.length(1) @@ -108,7 +138,7 @@ describe('.get', () => { return done() } - apiClients.a.get('Qme79tX2bViL26vNjPsF3DP1R9rMKMvnPYJiKTTKPrXJjq', (err, files) => { + ipfs.get('Qme79tX2bViL26vNjPsF3DP1R9rMKMvnPYJiKTTKPrXJjq', (err, files) => { expect(err).to.not.exist files.on('data', (file) => { @@ -124,7 +154,7 @@ describe('.get', () => { describe('promise', () => { it('get', (done) => { - apiClients.a.get('Qma4hjFTnCasJ8PVp3mZbZK5g2vGDT4LByLJ7m8ciyRFZP') + ipfs.get('Qma4hjFTnCasJ8PVp3mZbZK5g2vGDT4LByLJ7m8ciyRFZP') .then((files) => { files.on('data', (file) => { let buf = '' diff --git a/test/interface-ipfs-core/id.spec.js b/test/interface-ipfs-core/id.spec.js deleted file mode 100644 index 26187e67c..000000000 --- a/test/interface-ipfs-core/id.spec.js +++ /dev/null @@ -1,26 +0,0 @@ -/* eslint-env mocha */ -/* globals apiClients */ -'use strict' - -const expect = require('chai').expect - -describe('.id', () => { - it('id', (done) => { - apiClients.a.id((err, res) => { - expect(err).to.not.exist - expect(res).to.have.a.property('ID') - expect(res).to.have.a.property('PublicKey') - done() - }) - }) - - describe('promise', () => { - it('id', () => { - return apiClients.a.id() - .then((res) => { - expect(res).to.have.a.property('ID') - expect(res).to.have.a.property('PublicKey') - }) - }) - }) -}) diff --git a/test/interface-ipfs-core/index.spec.js b/test/interface-ipfs-core/index.spec.js deleted file mode 100644 index a92b33245..000000000 --- a/test/interface-ipfs-core/index.spec.js +++ /dev/null @@ -1,12 +0,0 @@ -/* eslint-env mocha */ -/* globals apiClients */ -'use strict' - -const expect = require('chai').expect - -describe('API', () => { - it('has the api object', () => { - expect(apiClients.a).to.exist - expect(apiClients.a).to.have.a.property('id') - }) -}) diff --git a/test/interface-ipfs-core/log.spec.js b/test/interface-ipfs-core/log.spec.js index 65ac3c0ac..11710b780 100644 --- a/test/interface-ipfs-core/log.spec.js +++ b/test/interface-ipfs-core/log.spec.js @@ -1,42 +1,54 @@ /* eslint-env mocha */ /* eslint max-nested-callbacks: ["error", 8] */ -/* globals apiClients */ 'use strict' const expect = require('chai').expect const isNode = require('detect-node') +const FactoryClient = require('../factory/factory-client') // For some reason these tests time out in PhantomJS so we need to skip them const isPhantom = !isNode && typeof navigator !== 'undefined' && navigator.userAgent.match(/PhantomJS/) -describe('.log', () => { - it('.log.tail', (done) => { - if (isPhantom) { - return done() - } - const req = apiClients.a.log.tail((err, res) => { - expect(err).to.not.exist - expect(req).to.exist - - res.once('data', (obj) => { - expect(obj).to.be.an('object') +if (!isPhantom) { + describe('.log', () => { + let ipfs + let fc + + before(function (done) { + this.timeout(20 * 1000) // slow CI + fc = new FactoryClient() + fc.spawnNode((err, node) => { + expect(err).to.not.exist + ipfs = node done() }) }) - }) - describe('promise', () => { - it('.log.tail', () => { - if (isPhantom) { - return - } + after((done) => { + fc.dismantle(done) + }) - return apiClients.a.log.tail() - .then((res) => { - res.once('data', (obj) => { - expect(obj).to.be.an('object') - }) + it('.log.tail', (done) => { + const req = ipfs.log.tail((err, res) => { + expect(err).to.not.exist + expect(req).to.exist + + res.once('data', (obj) => { + expect(obj).to.be.an('object') + done() }) + }) + }) + + describe('promise', () => { + it('.log.tail', () => { + return ipfs.log.tail() + .then((res) => { + res.once('data', (obj) => { + expect(obj).to.be.an('object') + }) + }) + }) }) }) -}) +} diff --git a/test/interface-ipfs-core/ls.spec.js b/test/interface-ipfs-core/ls.spec.js index 2dbcd075a..43082cb66 100644 --- a/test/interface-ipfs-core/ls.spec.js +++ b/test/interface-ipfs-core/ls.spec.js @@ -1,15 +1,33 @@ /* eslint-env mocha */ -/* globals apiClients */ 'use strict' const expect = require('chai').expect const isNode = require('detect-node') - +const FactoryClient = require('../factory/factory-client') describe('ls', function () { + let ipfs + let fc + + before(function (done) { + this.timeout(20 * 1000) // slow CI + fc = new FactoryClient() + fc.spawnNode((err, node) => { + expect(err).to.not.exist + ipfs = node + done() + }) + }) + + after((done) => { + fc.dismantle(done) + }) + it('should correctly retrieve links', function (done) { - if (!isNode) return done() + if (!isNode) { + return done() + } - apiClients.a.ls('QmYwAPJzv5CZsnA625s3Xf2nemtYgPpHdWEz79ojWnPbdG', (err, res) => { + ipfs.ls('QmYwAPJzv5CZsnA625s3Xf2nemtYgPpHdWEz79ojWnPbdG', (err, res) => { expect(err).to.not.exist expect(res).to.have.a.property('Objects') @@ -20,7 +38,7 @@ describe('ls', function () { }) it('should correctly handle a nonexisting hash', function (done) { - apiClients.a.ls('surelynotavalidhashheh?', (err, res) => { + ipfs.ls('surelynotavalidhashheh?', (err, res) => { expect(err).to.exist expect(res).to.not.exist done() @@ -30,7 +48,7 @@ describe('ls', function () { it('should correctly handle a nonexisting path', function (done) { if (!isNode) return done() - apiClients.a.ls('QmRNjDeKStKGTQXnJ2NFqeQ9oW/folder_that_isnt_there', (err, res) => { + ipfs.ls('QmRNjDeKStKGTQXnJ2NFqeQ9oW/folder_that_isnt_there', (err, res) => { expect(err).to.exist expect(res).to.not.exist done() @@ -41,7 +59,7 @@ describe('ls', function () { it('should correctly retrieve links', () => { if (!isNode) return - return apiClients.a.ls('QmYwAPJzv5CZsnA625s3Xf2nemtYgPpHdWEz79ojWnPbdG') + return ipfs.ls('QmYwAPJzv5CZsnA625s3Xf2nemtYgPpHdWEz79ojWnPbdG') .then((res) => { expect(res).to.have.a.property('Objects') expect(res.Objects[0]).to.have.a.property('Links') @@ -50,7 +68,7 @@ describe('ls', function () { }) it('should correctly handle a nonexisting hash', () => { - return apiClients.a.ls('surelynotavalidhashheh?') + return ipfs.ls('surelynotavalidhashheh?') .catch((err) => { expect(err).to.exist }) @@ -59,7 +77,7 @@ describe('ls', function () { it('should correctly handle a nonexisting path', () => { if (!isNode) return - return apiClients.a.ls('QmRNjDeKStKGTQXnJ3NFqeQ9oW/folder_that_isnt_there') + return ipfs.ls('QmRNjDeKStKGTQXnJ3NFqeQ9oW/folder_that_isnt_there') .catch((err) => { expect(err).to.exist }) diff --git a/test/interface-ipfs-core/name.spec.js b/test/interface-ipfs-core/name.spec.js index 6cfd93788..4e3e9194f 100644 --- a/test/interface-ipfs-core/name.spec.js +++ b/test/interface-ipfs-core/name.spec.js @@ -3,10 +3,27 @@ 'use strict' const expect = require('chai').expect +const fs = require('fs') +const path = require('path') + +const testfile = fs.readFileSync(path.join(__dirname, '/../data/testfile.txt')) describe('.name', () => { let name + it('add file for testing', (done) => { + const expectedMultihash = 'Qma4hjFTnCasJ8PVp3mZbZK5g2vGDT4LByLJ7m8ciyRFZP' + + apiClients.a.files.add(testfile, (err, res) => { + expect(err).to.not.exist + + expect(res).to.have.length(1) + expect(res[0].hash).to.equal(expectedMultihash) + expect(res[0].path).to.equal(expectedMultihash) + done() + }) + }) + it('.name.publish', (done) => { apiClients.a.name.publish('Qma4hjFTnCasJ8PVp3mZbZK5g2vGDT4LByLJ7m8ciyRFZP', (err, res) => { expect(err).to.not.exist diff --git a/test/interface-ipfs-core/pin.spec.js b/test/interface-ipfs-core/pin.spec.js index 56be6bf2a..3d05068b8 100644 --- a/test/interface-ipfs-core/pin.spec.js +++ b/test/interface-ipfs-core/pin.spec.js @@ -1,83 +1,20 @@ /* eslint-env mocha */ -/* globals apiClients */ +/* eslint max-nested-callbacks: ["error", 8] */ 'use strict' -const expect = require('chai').expect +const test = require('interface-ipfs-core') +const FactoryClient = require('../factory/factory-client') -describe('.pin', () => { - it('.pin.add', (done) => { - apiClients.b.pin.add('Qma4hjFTnCasJ8PVp3mZbZK5g2vGDT4LByLJ7m8ciyRFZP', {recursive: false}, (err, res) => { - expect(err).to.not.exist - expect(res.Pins[0]).to.be.equal('Qma4hjFTnCasJ8PVp3mZbZK5g2vGDT4LByLJ7m8ciyRFZP') - done() - }) - }) +let fc - it('.pin.list', (done) => { - apiClients.b.pin.list((err, res) => { - expect(err).to.not.exist - expect(res).to.exist - done() - }) - }) +const common = { + setup: function (callback) { + fc = new FactoryClient() + callback(null, fc) + }, + teardown: function (callback) { + fc.dismantle(callback) + } +} - it('.pin.list hash', (done) => { - apiClients.b.pin.list({hash: 'Qma4hjFTnCasJ8PVp3mZbZK5g2vGDT4LByLJ7m8ciyRFZP'}, (err, res) => { - expect(err).to.not.exist - expect(res).to.exist - done() - }) - }) - - it('.pin.remove', (done) => { - apiClients.b.pin.remove('Qma4hjFTnCasJ8PVp3mZbZK5g2vGDT4LByLJ7m8ciyRFZP', {recursive: false}, (err, res) => { - expect(err).to.not.exist - expect(res).to.exist - apiClients.b.pin.list('direct', (err, res) => { - expect(err).to.not.exist - expect(res).to.exist - expect(res.Keys).to.be.empty - done() - }) - }) - }) - - describe('promise', () => { - it('.pin.add', () => { - return apiClients.b.pin - .add('Qma4hjFTnCasJ8PVp3mZbZK5g2vGDT4LByLJ7m8ciyRFZP', {recursive: false}) - .then((res) => { - expect(res.Pins[0]).to.be.equal('Qma4hjFTnCasJ8PVp3mZbZK5g2vGDT4LByLJ7m8ciyRFZP') - }) - }) - - it('.pin.list', () => { - return apiClients.b.pin.list() - .then((res) => { - expect(res).to.exist - }) - }) - - it('.pin.list hash', () => { - return apiClients.b.pin.list({ - hash: 'Qma4hjFTnCasJ8PVp3mZbZK5g2vGDT4LByLJ7m8ciyRFZP' - }) - .then((res) => { - expect(res).to.exist - }) - }) - - it('.pin.remove', () => { - return apiClients.b.pin - .remove('Qma4hjFTnCasJ8PVp3mZbZK5g2vGDT4LByLJ7m8ciyRFZP', {recursive: false}) - .then((res) => { - expect(res).to.exist - return apiClients.b.pin.list('direct') - }) - .then((res) => { - expect(res).to.exist - expect(res.Keys).to.be.empty - }) - }) - }) -}) +test.pin(common) diff --git a/test/interface-ipfs-core/ping.spec.js b/test/interface-ipfs-core/ping.spec.js index 47064360e..bf4e2e606 100644 --- a/test/interface-ipfs-core/ping.spec.js +++ b/test/interface-ipfs-core/ping.spec.js @@ -9,7 +9,7 @@ describe('.ping', () => { apiClients.b.id((err, id) => { expect(err).to.not.exist - apiClients.a.ping(id.ID, (err, res) => { + apiClients.a.ping(id.id, (err, res) => { expect(err).to.not.exist expect(res).to.have.a.property('Success') done() @@ -21,7 +21,7 @@ describe('.ping', () => { it('ping another peer', () => { return apiClients.b.id() .then((id) => { - return apiClients.a.ping(id.ID) + return apiClients.a.ping(id.id) }) .then((res) => { expect(res).to.have.a.property('Success') diff --git a/test/interface-ipfs-core/refs.spec.js b/test/interface-ipfs-core/refs.spec.js index d8dad1345..e687290e6 100644 --- a/test/interface-ipfs-core/refs.spec.js +++ b/test/interface-ipfs-core/refs.spec.js @@ -1,11 +1,28 @@ /* eslint-env mocha */ -/* globals apiClients */ 'use strict' const expect = require('chai').expect const isNode = require('detect-node') +const FactoryClient = require('../factory/factory-client') describe('.refs', () => { + let ipfs + let fc + + before(function (done) { + this.timeout(20 * 1000) // slow CI + fc = new FactoryClient() + fc.spawnNode((err, node) => { + expect(err).to.not.exist + ipfs = node + done() + }) + }) + + after((done) => { + fc.dismantle(done) + }) + const folder = 'QmYwAPJzv5CZsnA625s3Xf2nemtYgPpHdWEz79ojWnPbdG' const result = [{ Ref: 'QmYwAPJzv5CZsnA625s3Xf2nemtYgPpHdWEz79ojWnPbdG QmZTR5bcpQD7cFgTorqxZDYaew1Wqgfbd2ud9QqGPAkK2V about', @@ -32,7 +49,7 @@ describe('.refs', () => { return done() } - apiClients.a.refs(folder, {format: ' '}, (err, objs) => { + ipfs.refs(folder, {format: ' '}, (err, objs) => { expect(err).to.not.exist expect(objs).to.eql(result) @@ -42,9 +59,11 @@ describe('.refs', () => { describe('promise', () => { it('refs', () => { - if (!isNode) return + if (!isNode) { + return + } - return apiClients.a.refs(folder, {format: ' '}) + return ipfs.refs(folder, {format: ' '}) .then((objs) => { expect(objs).to.eql(result) }) diff --git a/test/interface-ipfs-core/repo.spec.js b/test/interface-ipfs-core/repo.spec.js index 6930bcc4f..778e06426 100644 --- a/test/interface-ipfs-core/repo.spec.js +++ b/test/interface-ipfs-core/repo.spec.js @@ -1,12 +1,29 @@ /* eslint-env mocha */ -/* globals apiClients */ 'use strict' +const FactoryClient = require('../factory/factory-client') const expect = require('chai').expect describe('.repo', () => { + let ipfs + let fc + + before(function (done) { + this.timeout(20 * 1000) // slow CI + fc = new FactoryClient() + fc.spawnNode((err, node) => { + expect(err).to.not.exist + ipfs = node + done() + }) + }) + + after((done) => { + fc.dismantle(done) + }) + it('.repo.gc', (done) => { - apiClients.a.repo.gc((err, res) => { + ipfs.repo.gc((err, res) => { expect(err).to.not.exist expect(res).to.exist done() @@ -14,7 +31,7 @@ describe('.repo', () => { }) it('.repo.stat', (done) => { - apiClients.a.repo.stat((err, res) => { + ipfs.repo.stat((err, res) => { expect(err).to.not.exist expect(res).to.exist expect(res).to.have.a.property('NumObjects') @@ -25,14 +42,14 @@ describe('.repo', () => { describe('promise', () => { it('.repo.gc', () => { - return apiClients.a.repo.gc() + return ipfs.repo.gc() .then((res) => { expect(res).to.exist }) }) it('.repo.stat', () => { - return apiClients.a.repo.stat() + return ipfs.repo.stat() .then((res) => { expect(res).to.exist expect(res).to.have.a.property('NumObjects') diff --git a/test/interface-ipfs-core/send.spec.js b/test/interface-ipfs-core/send.spec.js deleted file mode 100644 index 9714a72d3..000000000 --- a/test/interface-ipfs-core/send.spec.js +++ /dev/null @@ -1,6 +0,0 @@ -/* eslint-env mocha */ -'use strict' - -describe('.send', () => { - it('used by every command') -}) diff --git a/test/interface-ipfs-core/swarm.spec.js b/test/interface-ipfs-core/swarm.spec.js index 18f89115c..c01610d08 100644 --- a/test/interface-ipfs-core/swarm.spec.js +++ b/test/interface-ipfs-core/swarm.spec.js @@ -1,67 +1,20 @@ /* eslint-env mocha */ -/* globals apiClients */ +/* eslint max-nested-callbacks: ["error", 8] */ 'use strict' -const expect = require('chai').expect +const test = require('interface-ipfs-core') +const FactoryClient = require('../factory/factory-client') -describe('.swarm', () => { - it('.swarm.peers', (done) => { - apiClients.a.swarm.peers((err, res) => { - expect(err).to.not.exist +let fc - expect(res.Strings).to.have.length.above(1) - done() - }) - }) +const common = { + setup: function (callback) { + fc = new FactoryClient() + callback(null, fc) + }, + teardown: function (callback) { + fc.dismantle(callback) + } +} - it('.swarm.connect', (done) => { - // Done in the 'before' segment - done() - }) - - it('.swarm.disconnect', (done) => { - // Done in the 'after' segment - done() - }) - - it('.swarm.addrs', (done) => { - apiClients.a.swarm.addrs((err, res) => { - expect(err).to.not.exist - - expect(Object.keys(res.Addrs)).to.have.length.above(1) - done() - }) - }) - - it('.swarm.localAddrs', (done) => { - apiClients.a.swarm.localAddrs((err, res) => { - expect(err).to.not.exist - - expect(res.Strings).to.have.length.above(1) - done() - }) - }) - - describe('promise', () => { - it('.swarm.peers', () => { - return apiClients.a.swarm.peers() - .then((res) => { - expect(res.Strings).to.have.length.above(1) - }) - }) - - it('.swarm.addrs', () => { - return apiClients.a.swarm.addrs() - .then((res) => { - expect(Object.keys(res.Addrs)).to.have.length.above(1) - }) - }) - - it('.swarm.localAddrs', () => { - return apiClients.a.swarm.localAddrs() - .then((res) => { - expect(res.Strings).to.have.length.above(1) - }) - }) - }) -}) +test.swarm(common) diff --git a/test/interface-ipfs-core/version.spec.js b/test/interface-ipfs-core/version.spec.js deleted file mode 100644 index c7b9b0298..000000000 --- a/test/interface-ipfs-core/version.spec.js +++ /dev/null @@ -1,69 +0,0 @@ -/* eslint-env mocha */ -/* globals apiClients */ -'use strict' - -const expect = require('chai').expect - -describe('.version', () => { - // note, IPFS HTTP-API returns always the same object, the filtering - // happens on the CLI - it('checks the version', (done) => { - apiClients.a.version((err, res) => { - expect(err).to.not.exist - expect(res).to.have.a.property('Version') - expect(res).to.have.a.property('Commit') - expect(res).to.have.a.property('Repo') - done() - }) - }) - - it('with number option', (done) => { - apiClients.a.version({number: true}, (err, res) => { - expect(err).to.not.exist - expect(res).to.have.a.property('Version') - expect(res).to.have.a.property('Commit') - expect(res).to.have.a.property('Repo') - done() - }) - }) - - it('with commit option', (done) => { - apiClients.a.version({commit: true}, (err, res) => { - expect(err).to.not.exist - expect(res).to.have.a.property('Version') - expect(res).to.have.a.property('Commit') - expect(res).to.have.a.property('Repo') - done() - }) - }) - - it('with repo option', (done) => { - apiClients.a.version({commit: true}, (err, res) => { - expect(err).to.not.exist - expect(res).to.have.a.property('Version') - expect(res).to.have.a.property('Commit') - expect(res).to.have.a.property('Repo') - done() - }) - }) - - describe('promise', () => { - it('checks the version', () => { - return apiClients.a.version() - .then((res) => { - expect(res).to.have.a.property('Version') - expect(res).to.have.a.property('Commit') - expect(res).to.have.a.property('Repo') - }) - }) - - it('with number option', () => { - return apiClients.a.version({number: true}) - .then((res) => { - expect(res).to.have.a.property('Version') - expect(res).to.have.a.property('Commit') - expect(res).to.have.a.property('Repo') - }) - }) - }) -}) diff --git a/test/ipfs-api/constructor.spec.js b/test/ipfs-api/constructor.spec.js index ea6050f7f..f134af061 100644 --- a/test/ipfs-api/constructor.spec.js +++ b/test/ipfs-api/constructor.spec.js @@ -14,8 +14,8 @@ describe('ipfsAPI constructor tests', () => { client.id((err, id) => { expect(err).to.not.exist - expect(id).to.have.a.property('ID') - expect(id).to.have.a.property('PublicKey') + expect(id).to.have.a.property('id') + expect(id).to.have.a.property('publicKey') done() }) } diff --git a/test/ipfs-api/util.spec.js b/test/ipfs-api/util.spec.js new file mode 100644 index 000000000..b4453a5c8 --- /dev/null +++ b/test/ipfs-api/util.spec.js @@ -0,0 +1,71 @@ +/* eslint-env mocha */ +/* eslint max-nested-callbacks: ["error", 8] */ +'use strict' + +const expect = require('chai').expect +const isNode = require('detect-node') +const path = require('path') +const fs = require('fs') +const FactoryClient = require('../factory/factory-client') + +describe('.util', () => { + if (!isNode) { + return + } + + let ipfs + let fc + + before(function (done) { + this.timeout(20 * 1000) // slow CI + fc = new FactoryClient() + fc.spawnNode((err, node) => { + expect(err).to.not.exist + ipfs = node + done() + }) + }) + + after((done) => { + fc.dismantle(done) + }) + + it('.streamAdd', (done) => { + const tfpath = path.join(__dirname, '/../data/testfile.txt') + const rs = fs.createReadStream(tfpath) + rs.path = '' // clean the path for testing purposes + + ipfs.util.addFromStream(rs, (err, result) => { + expect(err).to.not.exist + expect(result.length).to.equal(1) + done() + }) + }) + + it('.fsAdd a directory', (done) => { + const filesPath = path.join(__dirname, '../data/test-folder') + ipfs.util.addFromFs(filesPath, { recursive: true }, (err, result) => { + expect(err).to.not.exist + expect(result.length).to.be.above(8) + done() + }) + }) + + it('.fsAdd a file', (done) => { + const filePath = path.join(__dirname, '../data/testfile.txt') + ipfs.util.addFromFs(filePath, (err, result) => { + expect(err).to.not.exist + expect(result.length).to.be.above(5) + + done() + }) + }) + + it('.urlAdd', (done) => { + ipfs.util.addFromURL('http://example.com/', (err, result) => { + expect(err).to.not.exist + expect(result.length).to.equal(1) + done() + }) + }) +}) diff --git a/test/setup/setup-ipfs-api-clients.js b/test/setup/setup-ipfs-api-clients.js index 33cc2ae17..eecb26787 100644 --- a/test/setup/setup-ipfs-api-clients.js +++ b/test/setup/setup-ipfs-api-clients.js @@ -18,7 +18,7 @@ function connectNodes (done) { throw err } // note to self: HTTP API port !== Node port - addrs[key] = id.Addresses[0] + addrs[key] = id.addresses[0] cb() }) } diff --git a/test/tmp-disposable-nodes-addrs.json b/test/tmp-disposable-nodes-addrs.json new file mode 100644 index 000000000..851a00021 --- /dev/null +++ b/test/tmp-disposable-nodes-addrs.json @@ -0,0 +1 @@ +{"c":"/ip4/127.0.0.1/tcp/56459","a":"/ip4/127.0.0.1/tcp/56466","b":"/ip4/127.0.0.1/tcp/56479"} \ No newline at end of file