diff --git a/.gitignore b/.gitignore index db6288ec0..a25f32043 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ test/setup/tmp-disposable-nodes-addrs.json dist coverage +docs \ No newline at end of file diff --git a/.npmignore b/.npmignore index 2f3481d98..66e1cefeb 100644 --- a/.npmignore +++ b/.npmignore @@ -3,3 +3,4 @@ node_modules coverage test +docs \ No newline at end of file diff --git a/README.md b/README.md index 6263151af..8fc3f8280 100644 --- a/README.md +++ b/README.md @@ -75,149 +75,9 @@ var ipfs = ipfsAPI('/ip4/127.0.0.1/tcp/5001') var ipfs = ipfsAPI({host: 'localhost', port: '5001', procotol: 'http'}) ``` -### In a web browser through Browserify - -Same as in Node.js, you just have to [browserify](http://browserify.org) the code before serving it. See the browserify repo for how to do that. - -See the example in the [examples folder](/examples/bundle-browserify) to get a boilerplate. - -### In a web browser through webpack - -See the example in the [examples folder](/examples/bundle-webpack) to get an idea on how to use js-ipfs-api with webpack - -### In a web browser from CDN - -Instead of a local installation (and browserification) you may request a remote copy of IPFS API from [unpkg CDN](https://unpkg.com/). - -To always request the latest version, use the following: - -```html - -``` - -For maximum security you may also decide to: - -* reference a specific version of IPFS API (to prevent unexpected breaking changes when a newer latest version is published) - -* [generate a SRI hash](https://www.srihash.org/) of that version and use it to ensure integrity - -* set the [CORS settings attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/CORS_settings_attributes) to make anonymous requests to CDN - -Example: - -```html - -``` - -CDN-based IPFS API provides the `IpfsApi` constructor as a method of the global `window` object. Example: - -``` -var ipfs = window.IpfsApi('localhost', '5001') -``` - -If you omit the host and port, the API will parse `window.host`, and use this information. This also works, and can be useful if you want to write apps that can be run from multiple different gateways: - -``` -var ipfs = window.IpfsApi() -``` - -### CORS - -In a web browser IPFS API (either browserified or CDN-based) might encounter an error saying that the origin is not allowed. This would be a CORS ("Cross Origin Resource Sharing") failure: IPFS servers are designed to reject requests from unknown domains by default. You can whitelist the domain that you are calling from by changing your ipfs config like this: - -```bash -$ ipfs config --json API.HTTPHeaders.Access-Control-Allow-Origin "[\"http://example.com\"]" -$ ipfs config --json API.HTTPHeaders.Access-Control-Allow-Credentials "[\"true\"]" -$ ipfs config --json API.HTTPHeaders.Access-Control-Allow-Methods "[\"PUT\", \"POST\", \"GET\"]" -``` - ## Usage -### API - -> `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. - -### 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. 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: - -```js -ipfs.id() - .then(function (id) { - console.log('my id is: ', id) - }) - .catch(function(err) { - console.log('Fail: ', err) - }) -``` - -This relies on a global `Promise` object. If you are in an environment where that is not -yet available you need to bring your own polyfill. +See https://ipfs.github.io/js-ipfs-api/ ## Development diff --git a/documentation.yml b/documentation.yml new file mode 100644 index 000000000..580d1f315 --- /dev/null +++ b/documentation.yml @@ -0,0 +1,3 @@ +toc: + - name: Intro + file: intro.md diff --git a/intro.md b/intro.md new file mode 100644 index 000000000..caebc2f99 --- /dev/null +++ b/intro.md @@ -0,0 +1,119 @@ +Installable via `npm install --save ipfs-api`, it can also be used directly in the browser. + +## Quick Example + +```js +const ipfsAPI = require('ipfs-api') + +// connect to ipfs daemon API server + +// leaving out the arguments will default to these values +const ipfs = ipfsAPI('localhost', '5001', {protocol: 'http'}) + +// or connect with multiaddr +const ipfs = ipfsAPI('/ip4/127.0.0.1/tcp/5001') + +// or using options +const ipfs = ipfsAPI({host: 'localhost', port: '5001', procotol: 'http'}) +``` + +There are more available, so take a look at the docs below for a full list. This documentation aims to be comprehensive, so if you feel anything is missing please create a GitHub issue for it. + +## Download + +The source is available for download from [GitHub](https://github.com/ipfs/js-ipfs-api). Alternatively, you can install using npm: + +```bash +$ npm install --save ipfs-api +``` + +You can then `require()` ${name} as normal: + +```js +const ipfsApi = require('ipfs-api') +``` + +## In the Browser + +Ipfs-api should work in any ES2015 environment out of the box. + +Usage: + +```html + +``` + +The portable versions of ipfs-api, including `index.js` and `index.min.js`, are included in the `/dist` folder. Ipfs-api can also be found on [unkpkg.com](https://unpkg.com) under + +- https://unpkg.com/ipfs-api/dist/index.min.js +- https://unpkg.com/ipfs-api/dist/index.js + +For maximum security you may also decide to: + +* reference a specific version of IPFS API (to prevent unexpected breaking changes when a newer latest version is published) +* [generate a SRI hash](https://www.srihash.org/) of that version and use it to ensure integrity +* set the [CORS settings attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/CORS_settings_attributes) to make anonymous requests to CDN + +Example: + +```html + +``` + +CDN-based IPFS API provides the `IpfsApi` constructor as a method of the global `window` object. Example: + +``` +const ipfs = window.IpfsApi('localhost', '5001') +``` + +If you omit the host and port, the API will parse `window.host`, and use this information. This also works, and can be useful if you want to write apps that can be run from multiple different gateways: + +``` +const ipfs = window.IpfsApi() +``` + +## Frequently Asked Questions + +### Running the daemon with the right port + +To interact with the API, you need to connect to a running ipfs daemon running. It needs to be available on the right port. `5001` is the default, and is used in the examples below, but it can be set to whatever you need. + +```sh +# Show the ipfs config API port to check it is correct +$ ipfs config Addresses.API +/ip4/127.0.0.1/tcp/5001 +# Set it if it does not match the above output +$ ipfs config Addresses.API /ip4/127.0.0.1/tcp/5001 +# Restart the daemon after changing the config + +# Run the daemon +$ ipfs daemon +``` + +### CORS + +In a web browser IPFS API (either browserified or CDN-based) might encounter an error saying that the origin is not allowed. This would be a CORS ("Cross Origin Resource Sharing") failure: IPFS servers are designed to reject requests from unknown domains by default. You can whitelist the domain that you are calling from by changing your ipfs config like this: + +```bash +$ ipfs config --json API.HTTPHeaders.Access-Control-Allow-Origin "[\"http://example.com\"]" +$ ipfs config --json API.HTTPHeaders.Access-Control-Allow-Credentials "[\"true\"]" +$ ipfs config --json API.HTTPHeaders.Access-Control-Allow-Methods "[\"PUT\", \"POST\", \"GET\"]" +``` + +### Callbacks and promises + +If you do not pass in a callback all API functions will return a `Promise`. For example: + +```js +ipfs.id() + .then(function (id) { + console.log('my id is: ', id) + }) + .catch(function(err) { + console.log('Fail: ', err) + }) +``` + +This relies on a global `Promise` object. If you are in an environment where none is available you need to bring your own polyfill. diff --git a/package.json b/package.json index a806019df..da08e382c 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,8 @@ "release-minor": "gulp release --type minor", "release-major": "gulp release --type major", "coverage": "gulp coverage", - "coverage-publish": "aegir-coverage publish" + "coverage-publish": "aegir-coverage publish", + "docs": "aegir-docs" }, "dependencies": { "async": "^2.1.4", diff --git a/src/api/add.js b/src/api/add.js index 1b41f7578..e93cb0ec6 100644 --- a/src/api/add.js +++ b/src/api/add.js @@ -5,6 +5,23 @@ const promisify = require('promisify-es6') const DAGNodeStream = require('../dagnode-stream') module.exports = (send) => { + /** + * Add content to IPFS. + * + * @alias add + * @method + * @param {(Buffer|Stream|Array)} files - The content to add. + * @param {function(Error, {hash: string})} [callback] + * @returns {Promise<{hash: string}>|undefined} + * + * @memberof IpfsApi# + * + * @example + * api.add(new Buffer('hello world')).then((res) => { + * console.log('saved with hash %s', res.hash) + * }) + * + */ return promisify((files, callback) => { const ok = Buffer.isBuffer(files) || isStream.isReadable(files) || diff --git a/src/api/bitswap.js b/src/api/bitswap.js index 98704caca..ff792e283 100644 --- a/src/api/bitswap.js +++ b/src/api/bitswap.js @@ -4,24 +4,60 @@ const promisify = require('promisify-es6') module.exports = (send) => { return { + /** + * Show blocks currently on the wantlist. + * + * Print out all blocks currently on the bitswap wantlist for the local peer. + * + * @alias bitswap.wantlist + * @method + * @param {function(Error, Array)} [callback] + * + * @returns {Promise>|undefined} + * @memberof IpfsApi# + */ wantlist: promisify((callback) => { send({ path: 'bitswap/wantlist' }, callback) }), + + /** + * Show some diagnostic information on the bitswap agent. + * + * @alias bitswap.stat + * @method + * @param {function(Error, Object)} [callback] + * + * @returns {Promise|undefined} + * @memberof IpfsApi# + */ stat: promisify((callback) => { send({ path: 'bitswap/stat' }, callback) }), - unwant: promisify((args, opts, callback) => { + + /** + * Remove a given block from your wantlist. + * + * @alias bitswap.unwant + * @method + * @param {string|Array} key - The `base58` encoded multihashes of the blocks to unwant. + * @param {Object} [opts={}] + * @param {function(Error)} [callback] + * + * @returns {Promise|undefined} + * @memberof IpfsApi# + */ + unwant: promisify((key, opts, callback) => { if (typeof (opts) === 'function') { callback = opts opts = {} } send({ path: 'bitswap/unwant', - args: args, + args: key, qs: opts }, callback) }) diff --git a/src/api/block.js b/src/api/block.js index 73d745063..b267ab6e8 100644 --- a/src/api/block.js +++ b/src/api/block.js @@ -8,6 +8,17 @@ const streamToValue = require('../stream-to-value') module.exports = (send) => { return { + /** + * Get a raw IPFS block + * + * @alias block.get + * @method + * @param {CID|string} args - the multihash or CID of the block. + * @param {Object} [opts={}] + * @param {function(Error, Block)} [callback] + * @returns {Promise|undefined} + * @memberof IpfsApi# + */ get: promisify((args, opts, callback) => { // TODO this needs to be adjusted with the new go-ipfs http-api if (CID.isCID(args)) { @@ -43,10 +54,22 @@ module.exports = (send) => { send.andTransform(request, transform, callback) }), - stat: promisify((args, opts, callback) => { + + /** + * Print information of a raw IPFS block. + * + * @alias block.stat + * @method + * @param {CID|string} key - the `base58` multihash or CID of the block. + * @param {Object} [opts={}] + * @param {function(Error, {key: string, size: string})} [callback] + * @returns {Promise<{key: string, size: string}>|undefined} + * @memberof IpfsApi# + */ + stat: promisify((key, opts, callback) => { // TODO this needs to be adjusted with the new go-ipfs http-api - if (args && CID.isCID(args)) { - args = multihash.toB58String(args.multihash) + if (key && CID.isCID(key)) { + key = multihash.toB58String(key.multihash) } if (typeof (opts) === 'function') { @@ -56,7 +79,7 @@ module.exports = (send) => { const request = { path: 'block/stat', - args: args, + args: key, qs: opts } @@ -70,6 +93,19 @@ module.exports = (send) => { send.andTransform(request, transform, callback) }), + + /** + * Store input as an IPFS block. + * + * @alias block.put + * @method + * @param {Object} block - The block to create. + * @param {Buffer} block.data - The data to be stored as an IPFS block. + * @param {CID} [cid] + * @param {function(Error, Block)} [callback] + * @returns {Promise|undefined} + * @memberof IpfsApi# + */ put: promisify((block, cid, callback) => { // TODO this needs to be adjusted with the new go-ipfs http-api if (typeof cid === 'function') { diff --git a/src/api/bootstrap.js b/src/api/bootstrap.js index 89f67a0aa..2aaa36108 100644 --- a/src/api/bootstrap.js +++ b/src/api/bootstrap.js @@ -4,7 +4,17 @@ const promisify = require('promisify-es6') module.exports = (send) => { return { - add: promisify((args, opts, callback) => { + /** + * Add peers to the bootstrap list. + * @alias bootstrap.add + * @method + * @param {string|Array} peers - A list of peers to add to the bootstrap list (in the format `'/'`) + * @param {Object} [opts={}] + * @param {function(Error)} [callback] + * @returns {Promise|undefined} + * @memberof IpfsApi# + */ + add: promisify((peers, opts, callback) => { if (typeof opts === 'function' && !callback) { callback = opts @@ -19,18 +29,30 @@ module.exports = (send) => { opts = {} } - if (args && typeof args === 'object') { - opts = args - args = undefined + if (peers && typeof peers === 'object') { + opts = peers + peers = undefined } send({ path: 'bootstrap/add', - args: args, + args: peers, qs: opts }, callback) }), - rm: promisify((args, opts, callback) => { + + /** + * Remove peers from the bootstrap list. + * + * @alias bootstrap.rm + * @method + * @param {string|Array} peers - The peers to remove from the bootstrap list + * @param {Object} [opts={}] + * @param {function(Error)} [callback] + * @returns {Promise|undefined} + * @memberof IpfsApi# + */ + rm: promisify((peers, opts, callback) => { if (typeof opts === 'function' && !callback) { callback = opts @@ -45,17 +67,28 @@ module.exports = (send) => { opts = {} } - if (args && typeof args === 'object') { - opts = args - args = undefined + if (peers && typeof peers === 'object') { + opts = peers + peers = undefined } send({ path: 'bootstrap/rm', - args: args, + args: peers, qs: opts }, callback) }), + + /** + * Show peers in the bootstrap list. + * + * @alias bootstrap.list + * @method + * @param {Object} [opts={}] + * @param {function(Error, Array)} [callback] + * @returns {Promise|undefined} + * @memberof IpfsApi# + */ list: promisify((opts, callback) => { if (typeof (opts) === 'function') { callback = opts diff --git a/src/api/cat.js b/src/api/cat.js index 762469a14..a5e3b29f6 100644 --- a/src/api/cat.js +++ b/src/api/cat.js @@ -4,6 +4,12 @@ const promisify = require('promisify-es6') const cleanMultihash = require('../clean-multihash') module.exports = (send) => { + /** + * @alias cat + * @method + * @returns {Promise|undefined} + * @memberof IpfsApi# + */ return promisify((hash, opts, callback) => { if (typeof opts === 'function') { callback = opts diff --git a/src/api/commands.js b/src/api/commands.js index b0b4490b8..c0ab3c7de 100644 --- a/src/api/commands.js +++ b/src/api/commands.js @@ -3,6 +3,12 @@ const promisify = require('promisify-es6') module.exports = (send) => { + /** + * @alias commands + * @method + * @returns {Promise|undefined} + * @memberof IpfsApi# + */ return promisify((callback) => { send({ path: 'commands' diff --git a/src/api/config.js b/src/api/config.js index 33aaa03cd..6b749e1fe 100644 --- a/src/api/config.js +++ b/src/api/config.js @@ -5,6 +5,12 @@ const promisify = require('promisify-es6') module.exports = (send) => { return { + /** + * @alias config.get + * @method + * @returns {Promise|undefined} + * @memberof IpfsApi# + */ get: promisify((key, callback) => { if (typeof key === 'function') { callback = key @@ -30,6 +36,12 @@ module.exports = (send) => { callback(null, response.Value) }) }), + /** + * @alias config.set + * @method + * @returns {Promise|undefined} + * @memberof IpfsApi# + */ set: promisify((key, value, opts, callback) => { if (typeof opts === 'function') { callback = opts @@ -63,6 +75,12 @@ module.exports = (send) => { buffer: true }, callback) }), + /** + * @alias config.replace + * @method + * @returns {Promise|undefined} + * @memberof IpfsApi# + */ replace: promisify((config, callback) => { if (typeof config === 'object') { config = streamifier.createReadStream(new Buffer(JSON.stringify(config))) diff --git a/src/api/create-add-stream.js b/src/api/create-add-stream.js index 8c40dd1cc..1937f21b8 100644 --- a/src/api/create-add-stream.js +++ b/src/api/create-add-stream.js @@ -7,6 +7,12 @@ const promisify = require('promisify-es6') module.exports = (send) => { const add = addCmd(send) + /** + * @alias createAddStream + * @method + * @returns {Promise|undefined} + * @memberof IpfsApi# + */ return promisify((callback) => { const tuples = [] diff --git a/src/api/dht.js b/src/api/dht.js index dd78e7e0e..7b26cc5c3 100644 --- a/src/api/dht.js +++ b/src/api/dht.js @@ -5,6 +5,12 @@ const streamToValue = require('../stream-to-value') module.exports = (send) => { return { + /** + * @alias dht.findprovs + * @method + * @returns {Promise|undefined} + * @memberof IpfsApi# + */ findprovs: promisify((args, opts, callback) => { if (typeof opts === 'function' && !callback) { @@ -28,6 +34,13 @@ module.exports = (send) => { send.andTransform(request, streamToValue, callback) }), + + /** + * @alias dht.get + * @method + * @returns {Promise|undefined} + * @memberof IpfsApi# + */ get: promisify((key, opts, callback) => { if (typeof opts === 'function' && !callback) { @@ -73,6 +86,13 @@ module.exports = (send) => { qs: opts }, handleResult.bind(null, callback)) }), + + /** + * @alias dht.put + * @method + * @returns {Promise|undefined} + * @memberof IpfsApi# + */ put: promisify((key, value, opts, callback) => { if (typeof opts === 'function' && !callback) { diff --git a/src/api/diag.js b/src/api/diag.js index 15ae62301..4d78d0e8f 100644 --- a/src/api/diag.js +++ b/src/api/diag.js @@ -4,6 +4,12 @@ const promisify = require('promisify-es6') module.exports = (send) => { return { + /** + * @alias diag.net + * @method + * @returns {Promise|undefined} + * @memberof IpfsApi# + */ net: promisify((opts, callback) => { if (typeof (opts) === 'function') { callback = opts @@ -15,6 +21,13 @@ module.exports = (send) => { qs: opts }, callback) }), + + /** + * @alias diag.sys + * @method + * @returns {Promise|undefined} + * @memberof IpfsApi# + */ sys: promisify((opts, callback) => { if (typeof (opts) === 'function') { callback = opts @@ -26,6 +39,13 @@ module.exports = (send) => { qs: opts }, callback) }), + + /** + * @alias diag.cmds + * @method + * @returns {Promise|undefined} + * @memberof IpfsApi# + */ cmds: promisify((opts, callback) => { if (typeof (opts) === 'function') { callback = opts diff --git a/src/api/files.js b/src/api/files.js index 2fbf827eb..ddc4d4b62 100644 --- a/src/api/files.js +++ b/src/api/files.js @@ -4,6 +4,12 @@ const promisify = require('promisify-es6') module.exports = (send) => { return { + /** + * @alias files.cp + * @method + * @returns {Promise|undefined} + * @memberof IpfsApi# + */ cp: promisify((args, opts, callback) => { if (typeof (opts) === 'function') { callback = opts @@ -15,6 +21,13 @@ module.exports = (send) => { qs: opts }, callback) }), + + /** + * @alias files.ls + * @method + * @returns {Promise|undefined} + * @memberof IpfsApi# + */ ls: promisify((args, opts, callback) => { if (typeof (opts) === 'function') { callback = opts @@ -26,6 +39,13 @@ module.exports = (send) => { qs: opts }, callback) }), + + /** + * @alias files.mkdir + * @method + * @returns {Promise|undefined} + * @memberof IpfsApi# + */ mkdir: promisify((args, opts, callback) => { if (typeof (opts) === 'function') { callback = opts @@ -37,6 +57,13 @@ module.exports = (send) => { qs: opts }, callback) }), + + /** + * @alias files.stat + * @method + * @returns {Promise|undefined} + * @memberof IpfsApi# + */ stat: promisify((args, opts, callback) => { if (typeof (opts) === 'function') { callback = opts @@ -48,6 +75,13 @@ module.exports = (send) => { qs: opts }, callback) }), + + /** + * @alias files.rm + * @method + * @returns {Promise|undefined} + * @memberof IpfsApi# + */ rm: promisify((path, opts, callback) => { if (typeof opts === 'function' && !callback) { @@ -69,6 +103,13 @@ module.exports = (send) => { qs: opts }, callback) }), + + /** + * @alias files.read + * @method + * @returns {Promise|undefined} + * @memberof IpfsApi# + */ read: promisify((args, opts, callback) => { if (typeof (opts) === 'function') { callback = opts @@ -80,6 +121,13 @@ module.exports = (send) => { qs: opts }, callback) }), + + /** + * @alias files.write + * @method + * @returns {Promise|undefined} + * @memberof IpfsApi# + */ write: promisify((pathDst, files, opts, callback) => { if (typeof opts === 'function' && !callback) { @@ -102,6 +150,13 @@ module.exports = (send) => { files: files }, callback) }), + + /** + * @alias files.mv + * @method + * @returns {Promise|undefined} + * @memberof IpfsApi# + */ mv: promisify((args, opts, callback) => { if (typeof opts === 'function' && callback === undefined) { diff --git a/src/api/get.js b/src/api/get.js index 3b4c0c983..670b37c73 100644 --- a/src/api/get.js +++ b/src/api/get.js @@ -5,6 +5,12 @@ const cleanMultihash = require('../clean-multihash') const TarStreamToObjects = require('../tar-stream-to-objects') module.exports = (send) => { + /** + * @alias get + * @method + * @returns {Promise|undefined} + * @memberof IpfsApi# + */ return promisify((path, opts, callback) => { if (typeof opts === 'function' && !callback) { diff --git a/src/api/id.js b/src/api/id.js index beb970f42..734f68863 100644 --- a/src/api/id.js +++ b/src/api/id.js @@ -3,6 +3,12 @@ const promisify = require('promisify-es6') module.exports = (send) => { + /** + * @alias id + * @method + * @returns {Promise|undefined} + * @memberof IpfsApi# + */ return promisify((opts, callback) => { if (typeof opts === 'function') { callback = opts diff --git a/src/api/log.js b/src/api/log.js index 74c750d5e..686852b85 100644 --- a/src/api/log.js +++ b/src/api/log.js @@ -6,6 +6,12 @@ const promisify = require('promisify-es6') module.exports = (send) => { return { + /** + * @alias log.tail + * @method + * @returns {Promise|undefined} + * @memberof IpfsApi# + */ tail: promisify((callback) => { return send({ path: 'log/tail' diff --git a/src/api/ls.js b/src/api/ls.js index 8098fdeb8..ae1403158 100644 --- a/src/api/ls.js +++ b/src/api/ls.js @@ -3,6 +3,12 @@ const promisify = require('promisify-es6') module.exports = (send) => { + /** + * @alias ls + * @method + * @returns {Promise|undefined} + * @memberof IpfsApi# + */ return promisify((args, opts, callback) => { if (typeof (opts) === 'function') { callback = opts diff --git a/src/api/mount.js b/src/api/mount.js index a01c56825..c320b80fe 100644 --- a/src/api/mount.js +++ b/src/api/mount.js @@ -3,6 +3,12 @@ const promisify = require('promisify-es6') module.exports = (send) => { + /** + * @alias mount + * @method + * @returns {Promise|undefined} + * @memberof IpfsApi# + */ return promisify((ipfs, ipns, callback) => { if (typeof ipfs === 'function') { callback = ipfs diff --git a/src/api/name.js b/src/api/name.js index 77fd39fe0..4830a5f12 100644 --- a/src/api/name.js +++ b/src/api/name.js @@ -4,6 +4,12 @@ const promisify = require('promisify-es6') module.exports = (send) => { return { + /** + * @alias name.publish + * @method + * @returns {Promise|undefined} + * @memberof IpfsApi# + */ publish: promisify((args, opts, callback) => { if (typeof (opts) === 'function') { callback = opts @@ -15,6 +21,13 @@ module.exports = (send) => { qs: opts }, callback) }), + + /** + * @alias name.resolve + * @method + * @returns {Promise|undefined} + * @memberof IpfsApi# + */ resolve: promisify((args, opts, callback) => { if (typeof (opts) === 'function') { callback = opts diff --git a/src/api/object.js b/src/api/object.js index f7cd675a8..f21fb9b35 100644 --- a/src/api/object.js +++ b/src/api/object.js @@ -16,6 +16,12 @@ const cache = LRU(lruOptions) module.exports = (send) => { const api = { + /** + * @alias object.get + * @method + * @returns {Promise|undefined} + * @memberof IpfsApi# + */ get: promisify((multihash, options, callback) => { if (typeof options === 'function') { callback = options @@ -60,6 +66,12 @@ module.exports = (send) => { }) }), + /** + * @alias object.put + * @method + * @returns {Promise|undefined} + * @memberof IpfsApi# + */ put: promisify((obj, options, callback) => { if (typeof options === 'function') { callback = options @@ -158,6 +170,13 @@ module.exports = (send) => { } }) }), + + /** + * @alias object.data + * @method + * @returns {Promise|undefined} + * @memberof IpfsApi# + */ data: promisify((multihash, options, callback) => { if (typeof options === 'function') { callback = options @@ -194,6 +213,13 @@ module.exports = (send) => { } }) }), + + /** + * @alias object.links + * @method + * @returns {Promise|undefined} + * @memberof IpfsApi# + */ links: promisify((multihash, options, callback) => { if (typeof options === 'function') { callback = options @@ -233,6 +259,13 @@ module.exports = (send) => { callback(null, links) }) }), + + /** + * @alias object.stat + * @method + * @returns {Promise|undefined} + * @memberof IpfsApi# + */ stat: promisify((multihash, opts, callback) => { if (typeof opts === 'function') { callback = opts @@ -253,6 +286,12 @@ module.exports = (send) => { args: multihash }, callback) }), + /** + * @alias object.new + * @method + * @returns {Promise|undefined} + * @memberof IpfsApi# + */ new: promisify((template, callback) => { if (typeof template === 'function') { callback = template @@ -292,6 +331,13 @@ module.exports = (send) => { }) }) }), + + /** + * @alias object.patch + * @method + * @returns {Promise|undefined} + * @memberof IpfsApi# + */ patch: { addLink: promisify((multihash, dLink, opts, callback) => { if (typeof opts === 'function') { @@ -322,6 +368,13 @@ module.exports = (send) => { api.get(result.Hash, { enc: 'base58' }, callback) }) }), + + /** + * @alias object.rmLink + * @method + * @returns {Promise|undefined} + * @memberof IpfsApi# + */ rmLink: promisify((multihash, dLink, opts, callback) => { if (typeof opts === 'function') { callback = opts @@ -350,6 +403,13 @@ module.exports = (send) => { api.get(result.Hash, { enc: 'base58' }, callback) }) }), + + /** + * @alias object.setData + * @method + * @returns {Promise|undefined} + * @memberof IpfsApi# + */ setData: promisify((multihash, data, opts, callback) => { if (typeof opts === 'function') { callback = opts @@ -376,6 +436,13 @@ module.exports = (send) => { api.get(result.Hash, { enc: 'base58' }, callback) }) }), + + /** + * @alias object.appendData + * @method + * @returns {Promise|undefined} + * @memberof IpfsApi# + */ appendData: promisify((multihash, data, opts, callback) => { if (typeof opts === 'function') { callback = opts diff --git a/src/api/pin.js b/src/api/pin.js index cbd96eee0..d050cae92 100644 --- a/src/api/pin.js +++ b/src/api/pin.js @@ -4,6 +4,12 @@ const promisify = require('promisify-es6') module.exports = (send) => { return { + /** + * @alias pin.add + * @method + * @returns {Promise|undefined} + * @memberof IpfsApi# + */ add: promisify((hash, opts, callback) => { if (typeof opts === 'function') { callback = opts @@ -20,6 +26,13 @@ module.exports = (send) => { callback(null, res.Pins) }) }), + + /** + * @alias pin.rm + * @method + * @returns {Promise|undefined} + * @memberof IpfsApi# + */ rm: promisify((hash, opts, callback) => { if (typeof opts === 'function') { callback = opts @@ -36,6 +49,13 @@ module.exports = (send) => { callback(null, res.Pins) }) }), + + /** + * @alias pin.ls + * @method + * @returns {Promise|undefined} + * @memberof IpfsApi# + */ ls: promisify((hash, opts, callback) => { if (typeof opts === 'function') { callback = opts diff --git a/src/api/ping.js b/src/api/ping.js index eeaa3125a..c54790c30 100644 --- a/src/api/ping.js +++ b/src/api/ping.js @@ -4,6 +4,12 @@ const promisify = require('promisify-es6') const streamToValue = require('../stream-to-value') module.exports = (send) => { + /** + * @alias ping + * @method + * @returns {Promise|undefined} + * @memberof IpfsApi# + */ return promisify((id, callback) => { const request = { path: 'ping', diff --git a/src/api/refs.js b/src/api/refs.js index 56958ca7f..84403da90 100644 --- a/src/api/refs.js +++ b/src/api/refs.js @@ -4,6 +4,12 @@ const promisify = require('promisify-es6') const streamToValue = require('../stream-to-value') module.exports = (send) => { + /** + * @alias refs + * @method + * @returns {Promise|undefined} + * @memberof IpfsApi# + */ const refs = promisify((args, opts, callback) => { if (typeof (opts) === 'function') { callback = opts @@ -19,6 +25,12 @@ module.exports = (send) => { send.andTransform(request, streamToValue, callback) }) + /** + * @alias refs.local + * @method + * @returns {Promise|undefined} + * @memberof IpfsApi# + */ refs.local = promisify((opts, callback) => { if (typeof (opts) === 'function') { callback = opts diff --git a/src/api/repo.js b/src/api/repo.js index 32cde20c8..21ba9a782 100644 --- a/src/api/repo.js +++ b/src/api/repo.js @@ -4,6 +4,12 @@ const promisify = require('promisify-es6') module.exports = (send) => { return { + /** + * @alias repo.gc + * @method + * @returns {Promise|undefined} + * @memberof IpfsApi# + */ gc: promisify((opts, callback) => { if (typeof (opts) === 'function') { callback = opts @@ -14,6 +20,13 @@ module.exports = (send) => { qs: opts }, callback) }), + + /** + * @alias repo.stat + * @method + * @returns {Promise|undefined} + * @memberof IpfsApi# + */ stat: promisify((opts, callback) => { if (typeof (opts) === 'function') { callback = opts diff --git a/src/api/swarm.js b/src/api/swarm.js index 293af9705..a617f3aec 100644 --- a/src/api/swarm.js +++ b/src/api/swarm.js @@ -7,6 +7,12 @@ const PeerInfo = require('peer-info') module.exports = (send) => { return { + /** + * @alias swarm.peers + * @method + * @returns {Promise|undefined} + * @memberof IpfsApi# + */ peers: promisify((opts, callback) => { if (typeof (opts) === 'function') { callback = opts @@ -64,6 +70,13 @@ module.exports = (send) => { } }) }), + + /** + * @alias swarm.connect + * @method + * @returns {Promise|undefined} + * @memberof IpfsApi# + */ connect: promisify((args, opts, callback) => { if (typeof (opts) === 'function') { callback = opts @@ -75,6 +88,13 @@ module.exports = (send) => { qs: opts }, callback) }), + + /** + * @alias swarm.disconnect + * @method + * @returns {Promise|undefined} + * @memberof IpfsApi# + */ disconnect: promisify((args, opts, callback) => { if (typeof (opts) === 'function') { callback = opts @@ -86,6 +106,13 @@ module.exports = (send) => { qs: opts }, callback) }), + + /** + * @alias swarm.addrs + * @method + * @returns {Promise|undefined} + * @memberof IpfsApi# + */ addrs: promisify((opts, callback) => { if (typeof (opts) === 'function') { callback = opts @@ -111,6 +138,13 @@ module.exports = (send) => { callback(null, peers) }) }), + + /** + * @alias swarm.localAddrs + * @method + * @returns {Promise|undefined} + * @memberof IpfsApi# + */ localAddrs: promisify((opts, callback) => { if (typeof (opts) === 'function') { callback = opts diff --git a/src/api/update.js b/src/api/update.js index 7d3e980a9..49c6099b4 100644 --- a/src/api/update.js +++ b/src/api/update.js @@ -4,6 +4,12 @@ const promisify = require('promisify-es6') module.exports = (send) => { return { + /** + * @alias update.apply + * @method + * @returns {Promise|undefined} + * @memberof IpfsApi# + */ apply: promisify((opts, callback) => { if (typeof (opts) === 'function') { callback = opts @@ -14,6 +20,13 @@ module.exports = (send) => { qs: opts }, callback) }), + + /** + * @alias update.check + * @method + * @returns {Promise|undefined} + * @memberof IpfsApi# + */ check: promisify((opts, callback) => { if (typeof (opts) === 'function') { callback = opts @@ -24,6 +37,13 @@ module.exports = (send) => { qs: opts }, callback) }), + + /** + * @alias update.log + * @method + * @returns {Promise|undefined} + * @memberof IpfsApi# + */ log: promisify((opts, callback) => { if (typeof (opts) === 'function') { callback = opts diff --git a/src/api/util/fs-add.js b/src/api/util/fs-add.js index 6c63cf1ab..cb72fcb04 100644 --- a/src/api/util/fs-add.js +++ b/src/api/util/fs-add.js @@ -5,6 +5,12 @@ const promisify = require('promisify-es6') const DAGNodeStream = require('../../dagnode-stream') module.exports = (send) => { + /** + * @alias util.addFromFs + * @method + * @returns {Promise|undefined} + * @memberof IpfsApi# + */ return promisify((path, opts, callback) => { if (typeof opts === 'function' && callback === undefined) { diff --git a/src/api/util/url-add.js b/src/api/util/url-add.js index 7db525ad7..75a279d2c 100644 --- a/src/api/util/url-add.js +++ b/src/api/util/url-add.js @@ -7,6 +7,12 @@ const request = require('../../request') const DAGNodeStream = require('../../dagnode-stream') module.exports = (send) => { + /** + * @alias util.addFromUrl + * @method + * @returns {Promise|undefined} + * @memberof IpfsApi# + */ return promisify((url, opts, callback) => { if (typeof (opts) === 'function' && callback === undefined) { diff --git a/src/api/version.js b/src/api/version.js index 5548b63f3..39c725843 100644 --- a/src/api/version.js +++ b/src/api/version.js @@ -3,6 +3,12 @@ const promisify = require('promisify-es6') module.exports = (send) => { + /** + * @alias version + * @method + * @returns {Promise|undefined} + * @memberof IpfsApi# + */ return promisify((opts, callback) => { if (typeof opts === 'function') { callback = opts diff --git a/src/index.js b/src/index.js index e5b4f3399..14155df52 100644 --- a/src/index.js +++ b/src/index.js @@ -1,11 +1,45 @@ 'use strict' const multiaddr = require('multiaddr') -const loadCommands = require('./load-commands') + const getConfig = require('./default-config') const getRequestAPI = require('./request-api') -function IpfsAPI (hostOrMultiaddr, port, opts) { +/** + * Create a new IpfsApi. + * + * > `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. You can use it today to consult the methods available. + * + * @constructor IpfsApi + * @param {string|Multiaddr} [hostOrMultiaddr='localhost'] - The host to connect to. + * @param {number|string} [port=5001] - The port to use to connect to the api. + * @param {Object} [opts={}] + * @param {string} [host] + * @param {number|string} [opts.port] + * @param {string} [opts.protocol='http'] - Can be either `http` or `https`. + * @returns {IpfsApi} + * + * @example + * const ipfsAPI = require('ipfs-api') + * + * // connect to ipfs daemon API server + * const ipfs = ipfsAPI('localhost', '5001', {protocol: 'http'}) + * // leaving out the arguments will default to these values + * + * // or connect with multiaddr + * const ipfs = ipfsAPI('/ip4/127.0.0.1/tcp/5001') + * + * // or using options + * const ipfs = ipfsAPI({host: 'localhost', port: '5001', procotol: 'http'}) + */ +function IpfsApi (hostOrMultiaddr, port, opts) { + if (!(this instanceof IpfsApi)) { + return new IpfsApi(hostOrMultiaddr, port, opts) + } + const config = getConfig() try { @@ -36,11 +70,60 @@ function IpfsAPI (hostOrMultiaddr, port, opts) { } const requestAPI = getRequestAPI(config) - const cmds = loadCommands(requestAPI) - cmds.send = requestAPI - cmds.Buffer = Buffer - return cmds + /** + * Send a request + * + * @private + */ + this.send = requestAPI + + /** + * Expose `buffer` module. + * + */ + this.Buffer = Buffer + + // add and createAddStream alias + this.add = require('./api/add')(this.send) + this.cat = require('./api/cat')(this.send) + this.createAddStream = require('./api/create-add-stream')(this.send) + this.bitswap = require('./api/bitswap')(this.send) + this.block = require('./api/block')(this.send) + this.bootstrap = require('./api/bootstrap')(this.send) + this.commands = require('./api/commands')(this.send) + this.config = require('./api/config')(this.send) + this.dht = require('./api/dht')(this.send) + this.diag = require('./api/diag')(this.send) + this.id = require('./api/id')(this.send) + this.get = require('./api/get')(this.send) + this.log = require('./api/log')(this.send) + this.ls = require('./api/ls')(this.send) + this.mount = require('./api/mount')(this.send) + this.name = require('./api/name')(this.send) + this.object = require('./api/object')(this.send) + this.pin = require('./api/pin')(this.send) + this.ping = require('./api/ping')(this.send) + this.refs = require('./api/refs')(this.send) + this.repo = require('./api/repo')(this.send) + this.swarm = require('./api/swarm')(this.send) + this.update = require('./api/update')(this.send) + this.version = require('./api/version')(this.send) + + // TODO: crowding the 'files' namespace temporarily for + // interface-ipfs-core compatibility, until + // 'files vs mfs' naming decision is resolved. + this.files = require('./api/files')(this.send) + this.files.add = require('./api/add')(this.send) + this.files.createAddStream = require('./api/create-add-stream.js')(this.send) + this.files.get = require('./api/get')(this.send) + this.files.cat = require('./api/cat')(this.send) + + this.util = { + addFromFs: require('./api/util/fs-add')(this.send), + addFromStream: require('./api/add')(this.send), + addFromURL: require('./api/util/url-add')(this.send) + } } -exports = module.exports = IpfsAPI +module.exports = exports = IpfsApi diff --git a/src/load-commands.js b/src/load-commands.js deleted file mode 100644 index b69c197cb..000000000 --- a/src/load-commands.js +++ /dev/null @@ -1,67 +0,0 @@ -'use strict' - -function requireCommands () { - const cmds = { - // add and createAddStream alias - add: require('./api/add'), - cat: require('./api/cat'), - createAddStream: require('./api/create-add-stream'), - bitswap: require('./api/bitswap'), - block: require('./api/block'), - bootstrap: require('./api/bootstrap'), - commands: require('./api/commands'), - config: require('./api/config'), - dht: require('./api/dht'), - diag: require('./api/diag'), - id: require('./api/id'), - get: require('./api/get'), - log: require('./api/log'), - ls: require('./api/ls'), - mount: require('./api/mount'), - name: require('./api/name'), - object: require('./api/object'), - pin: require('./api/pin'), - ping: require('./api/ping'), - refs: require('./api/refs'), - repo: require('./api/repo'), - swarm: require('./api/swarm'), - update: require('./api/update'), - version: require('./api/version') - } - - // TODO: crowding the 'files' namespace temporarily for interface-ipfs-core - // compatibility, until 'files vs mfs' naming decision is resolved. - cmds.files = function (send) { - const files = require('./api/files')(send) - files.add = require('./api/add')(send) - files.createAddStream = require('./api/create-add-stream.js')(send) - files.get = require('./api/get')(send) - files.cat = require('./api/cat')(send) - - return files - } - - cmds.util = function (send) { - const util = { - addFromFs: require('./api/util/fs-add')(send), - addFromStream: require('./api/add')(send), - addFromURL: require('./api/util/url-add')(send) - } - return util - } - - return cmds -} - -function loadCommands (send) { - const files = requireCommands() - const cmds = {} - - Object.keys(files).forEach((file) => { - cmds[file] = files[file](send) - }) - - return cmds -} - -module.exports = loadCommands