diff --git a/README.md b/README.md index 21a2584a81..f21dc9a18a 100644 --- a/README.md +++ b/README.md @@ -324,6 +324,14 @@ Enable and configure experimental features. Modify the default IPFS node config. This object will be *merged* with the default config; it will not replace it. +##### `options.ipld` + +| Type | Default | +|------|---------| +| object | [`ipld-nodejs.js`](https://github.com/ipfs/js-ipfs/tree/master/src/core/runtime/ipld-nodejs.js) in Node.js, [`ipld-browser.js`](https://github.com/ipfs/js-ipfs/tree/master/src/core/runtime/ipld-browser.js) in browsers | + +Modify the default IPLD config. This object will be *merged* with the default config; it will not replace it. Check IPLD [docs](https://github.com/ipld/js-ipld#ipld-constructor) for more information on the available options. + ##### `options.libp2p` | Type | Default | diff --git a/package.json b/package.json index 37ce2001f7..f1dc8de4ce 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,7 @@ "./src/core/runtime/libp2p-nodejs.js": "./src/core/runtime/libp2p-browser.js", "./src/core/runtime/preload-nodejs.js": "./src/core/runtime/preload-browser.js", "./src/core/runtime/repo-nodejs.js": "./src/core/runtime/repo-browser.js", + "./src/core/runtime/ipld-nodejs.js": "./src/core/runtime/ipld-browser.js", "./test/utils/create-repo-nodejs.js": "./test/utils/create-repo-browser.js", "stream": "readable-stream", "joi": "joi-browser" @@ -68,8 +69,8 @@ "execa": "^1.0.0", "form-data": "^2.3.3", "hat": "0.0.3", - "interface-ipfs-core": "~0.98.1", - "ipfsd-ctl": "~0.41.0", + "interface-ipfs-core": "~0.99.0", + "ipfsd-ctl": "~0.42.1", "libp2p-websocket-star": "~0.10.2", "ncp": "^2.0.0", "qs": "^6.5.2", @@ -78,11 +79,10 @@ "stream-to-promise": "^2.2.0" }, "dependencies": { - "@nodeutils/defaults-deep": "^1.1.0", "async": "^2.6.1", "bignumber.js": "^8.0.2", "binary-querystring": "~0.1.2", - "bl": "^2.1.2", + "bl": "^3.0.0", "boom": "^7.2.0", "bs58": "^4.0.1", "byteman": "^1.3.5", @@ -92,6 +92,7 @@ "datastore-core": "~0.6.0", "datastore-pubsub": "~0.1.1", "debug": "^4.1.0", + "dlv": "^1.1.2", "err-code": "^1.1.2", "file-type": "^10.2.0", "fnv1a": "^1.0.1", @@ -103,14 +104,14 @@ "hoek": "^6.1.2", "human-to-milliseconds": "^1.0.0", "interface-datastore": "~0.6.0", - "ipfs-bitswap": "~0.22.0", + "ipfs-bitswap": "~0.23.0", "ipfs-block": "~0.8.0", "ipfs-block-service": "~0.15.1", - "ipfs-http-client": "^29.0.0", + "ipfs-http-client": "^30.1.0", "ipfs-http-response": "~0.2.1", "ipfs-mfs": "~0.9.1", "ipfs-multipart": "~0.1.0", - "ipfs-repo": "~0.26.1", + "ipfs-repo": "~0.26.4", "ipfs-unixfs": "~0.1.16", "ipfs-unixfs-engine": "~0.35.3", "ipld": "~0.21.1", @@ -120,27 +121,31 @@ "ipld-git": "~0.2.2", "ipld-zcash": "~0.1.6", "ipns": "~0.5.0", - "is-ipfs": "~0.4.8", + "is-ipfs": "~0.6.0", "is-pull-stream": "~0.0.0", "is-stream": "^1.1.0", + "iso-url": "~0.4.4", "joi": "^14.3.0", - "joi-browser": "^13.4.0", "joi-multiaddr": "^4.0.0", + "just-flatten-it": "^2.1.0", + "just-range": "^2.1.0", + "just-safe-set": "^2.1.0", "libp2p": "~0.25.0-rc.3", "libp2p-bootstrap": "~0.9.3", "libp2p-crypto": "~0.16.0", "libp2p-kad-dht": "~0.14.7", - "libp2p-keychain": "~0.3.3", + "libp2p-keychain": "~0.4.1", "libp2p-mdns": "~0.12.0", "libp2p-mplex": "~0.8.4", "libp2p-record": "~0.6.1", "libp2p-secio": "~0.11.0", "libp2p-tcp": "~0.13.0", "libp2p-webrtc-star": "~0.15.5", - "libp2p-websocket-star-multi": "~0.4.0", + "libp2p-websocket-star-multi": "~0.4.4", "libp2p-websockets": "~0.12.2", "lodash": "^4.17.11", "mafmt": "^6.0.2", + "merge-options": "^1.0.1", "mime-types": "^2.1.21", "mkdirp": "~0.5.1", "multiaddr": "^6.0.0", @@ -170,12 +175,13 @@ "readable-stream": "^3.1.1", "receptacle": "^1.3.2", "stream-to-pull-stream": "^1.7.2", + "superstruct": "~0.6.0", "tar-stream": "^2.0.0", "temp": "~0.9.0", "update-notifier": "^2.5.0", "uri-to-multiaddr": "^3.0.1", "varint": "^5.0.0", - "yargs": "^12.0.5", + "yargs": "^13.2.2", "yargs-promise": "^1.1.0" }, "optionalDependencies": { @@ -295,4 +301,4 @@ "Łukasz Magiera ", "Максим Ильин " ] -} \ No newline at end of file +} diff --git a/src/cli/commands/add.js b/src/cli/commands/add.js index 11fc84c1ee..4ad22b7f6b 100644 --- a/src/cli/commands/add.js +++ b/src/cli/commands/add.js @@ -1,6 +1,5 @@ 'use strict' -const sortBy = require('lodash/sortBy') const pull = require('pull-stream') const promisify = require('promisify-es6') const getFolderSize = promisify(require('get-folder-size')) @@ -37,8 +36,16 @@ function addPipeline (source, addStream, options) { print(added.pop().hash) return resolve() } - - sortBy(added, 'path') + added + .sort((a, b) => { + if (a.path > b.path) { + return 1 + } + if (a.path < b.path) { + return -1 + } + return 0 + }) .reverse() .map((file) => { const log = options.quiet ? [] : ['added'] @@ -47,7 +54,6 @@ function addPipeline (source, addStream, options) { return log.join(' ') }) .forEach((msg) => print(msg)) - resolve() }) ) diff --git a/src/core/components/dag.js b/src/core/components/dag.js index dc9ef2bdf5..ffc6ccfd0a 100644 --- a/src/core/components/dag.js +++ b/src/core/components/dag.js @@ -5,7 +5,7 @@ const CID = require('cids') const pull = require('pull-stream') const mapAsync = require('async/map') const setImmediate = require('async/setImmediate') -const flattenDeep = require('lodash/flattenDeep') +const flattenDeep = require('just-flatten-it') const errCode = require('err-code') module.exports = function dag (self) { diff --git a/src/core/components/files-regular/add-from-url.js b/src/core/components/files-regular/add-from-url.js index b486c569d3..73697aa2cf 100644 --- a/src/core/components/files-regular/add-from-url.js +++ b/src/core/components/files-regular/add-from-url.js @@ -1,6 +1,6 @@ 'use strict' -const { URL } = require('url') +const { URL } = require('iso-url') const fetch = require('../../runtime/fetch-nodejs') module.exports = (self) => { diff --git a/src/core/components/files-regular/add.js b/src/core/components/files-regular/add.js index 1c36b7d20a..174cf8d51a 100644 --- a/src/core/components/files-regular/add.js +++ b/src/core/components/files-regular/add.js @@ -5,7 +5,6 @@ const pull = require('pull-stream') const sort = require('pull-sort') const isStream = require('is-stream') const isSource = require('is-pull-stream').isSource -const isString = require('lodash/isString') module.exports = function (self) { const add = promisify((data, options, callback) => { @@ -24,7 +23,7 @@ module.exports = function (self) { // path is optional if content is present if (obj.content) return isBufferOrStream(obj.content) // path must be a non-empty string if no content - return Boolean(obj.path) && isString(obj.path) + return Boolean(obj.path) && typeof obj.path === 'string' } // An input atom: a buffer, stream or content object const isInput = obj => isBufferOrStream(obj) || isContentObject(obj) diff --git a/src/core/components/init.js b/src/core/components/init.js index 29cac89402..96b8572baf 100644 --- a/src/core/components/init.js +++ b/src/core/components/init.js @@ -1,10 +1,10 @@ 'use strict' const peerId = require('peer-id') +const mergeOptions = require('merge-options') const waterfall = require('async/waterfall') const parallel = require('async/parallel') const promisify = require('promisify-es6') -const defaultsDeep = require('@nodeutils/defaults-deep') const defaultConfig = require('../runtime/config-nodejs.js') const Keychain = require('libp2p-keychain') const { @@ -59,7 +59,7 @@ module.exports = function init (self) { opts.bits = Number(opts.bits) || 2048 opts.log = opts.log || function () {} - const config = defaultsDeep(self._options.config, defaultConfig()) + const config = mergeOptions(defaultConfig(), self._options.config) let privateKey waterfall([ diff --git a/src/core/components/libp2p.js b/src/core/components/libp2p.js index 7fc21bc922..0390c3a72b 100644 --- a/src/core/components/libp2p.js +++ b/src/core/components/libp2p.js @@ -1,8 +1,8 @@ 'use strict' -const get = require('lodash/get') -const defaultsDeep = require('@nodeutils/defaults-deep') +const get = require('dlv') const ipnsUtils = require('../ipns/routing/utils') +const mergeOptions = require('merge-options') module.exports = function libp2p (self, config) { const options = self._options || {} @@ -102,7 +102,7 @@ function defaultBundle ({ datastore, peerInfo, peerBook, options, config }) { }) } - const libp2pOptions = defaultsDeep(get(options, 'libp2p', {}), libp2pDefaults) + const libp2pOptions = mergeOptions(libp2pDefaults, get(options, 'libp2p', {})) // Required inline to reduce startup time // Note: libp2p-nodejs gets replaced by libp2p-browser when webpacked/browserified diff --git a/src/core/components/pre-start.js b/src/core/components/pre-start.js index 13d914acc4..02cf59cb4b 100644 --- a/src/core/components/pre-start.js +++ b/src/core/components/pre-start.js @@ -3,9 +3,9 @@ const peerId = require('peer-id') const PeerInfo = require('peer-info') const multiaddr = require('multiaddr') +const mergeOptions = require('merge-options') const waterfall = require('async/waterfall') const Keychain = require('libp2p-keychain') -const defaultsDeep = require('@nodeutils/defaults-deep') const NoKeychain = require('./no-keychain') /* * Load stuff from Repo into memory @@ -22,7 +22,7 @@ module.exports = function preStart (self) { return cb(null, config) } - config = defaultsDeep(self._options.config, config) + config = mergeOptions(config, self._options.config) self.config.replace(config, (err) => { if (err) { diff --git a/src/core/components/start.js b/src/core/components/start.js index dda2faf267..64ee8c73e0 100644 --- a/src/core/components/start.js +++ b/src/core/components/start.js @@ -2,7 +2,7 @@ const series = require('async/series') const Bitswap = require('ipfs-bitswap') -const get = require('lodash/get') +const get = require('dlv') const setImmediate = require('async/setImmediate') const promisify = require('promisify-es6') const { TieredDatastore } = require('datastore-core') diff --git a/src/core/components/swarm.js b/src/core/components/swarm.js index 62da0ac76e..4869cf2032 100644 --- a/src/core/components/swarm.js +++ b/src/core/components/swarm.js @@ -1,7 +1,6 @@ 'use strict' const promisify = require('promisify-es6') -const values = require('lodash/values') const OFFLINE_ERROR = require('../utils').OFFLINE_ERROR @@ -25,7 +24,7 @@ module.exports = function swarm (self) { const peers = [] - values(self._peerInfoBook.getAll()).forEach((peer) => { + Object.values(self._peerInfoBook.getAll()).forEach((peer) => { const connectedAddr = peer.isConnected() if (!connectedAddr) { return } @@ -50,7 +49,7 @@ module.exports = function swarm (self) { return callback(new Error(OFFLINE_ERROR)) } - const peers = values(self._peerInfoBook.getAll()) + const peers = Object.values(self._peerInfoBook.getAll()) callback(null, peers) }), diff --git a/src/core/config.js b/src/core/config.js index c3b9e892a4..327f445d8e 100644 --- a/src/core/config.js +++ b/src/core/config.js @@ -1,62 +1,83 @@ 'use strict' -const Joi = require('joi').extend(require('joi-multiaddr')) +const Multiaddr = require('multiaddr') +const mafmt = require('mafmt') +const { struct, superstruct } = require('superstruct') +const { optional, union } = struct +const s = superstruct({ + types: { + multiaddr: v => { + if (v === null) { + return `multiaddr invalid, value must be a string, Buffer, or another Multiaddr got ${v}` + } -const schema = Joi.object().keys({ - repo: Joi.alternatives().try( - Joi.object(), // TODO: schema for IPFS repo - Joi.string() - ).allow(null), - repoOwner: Joi.boolean().default(true), - preload: Joi.object().keys({ - enabled: Joi.boolean().default(true), - addresses: Joi.array().items(Joi.multiaddr().options({ convert: false })), - interval: Joi.number().integer().default(30 * 1000) - }).allow(null), - init: Joi.alternatives().try( - Joi.boolean(), - Joi.object().keys({ bits: Joi.number().integer() }) - ).allow(null), - start: Joi.boolean(), - offline: Joi.boolean(), - pass: Joi.string().allow(''), - relay: Joi.object().keys({ - enabled: Joi.boolean(), - hop: Joi.object().keys({ - enabled: Joi.boolean(), - active: Joi.boolean() - }).allow(null) - }).allow(null), - EXPERIMENTAL: Joi.object().keys({ - pubsub: Joi.boolean(), - ipnsPubsub: Joi.boolean(), - sharding: Joi.boolean(), - dht: Joi.boolean() - }).allow(null), - connectionManager: Joi.object().allow(null), - config: Joi.object().keys({ - Addresses: Joi.object().keys({ - Swarm: Joi.array().items(Joi.multiaddr().options({ convert: false })), - API: Joi.multiaddr().options({ convert: false }), - Gateway: Joi.multiaddr().options({ convert: false }) - }).allow(null), - Discovery: Joi.object().keys({ - MDNS: Joi.object().keys({ - Enabled: Joi.boolean(), - Interval: Joi.number().integer() - }).allow(null), - webRTCStar: Joi.object().keys({ - Enabled: Joi.boolean() - }).allow(null) - }).allow(null), - Bootstrap: Joi.array().items(Joi.multiaddr().IPFS().options({ convert: false })) - }).allow(null), - libp2p: Joi.alternatives().try( - Joi.func(), - Joi.object().keys({ - modules: Joi.object().allow(null) // TODO: schemas for libp2p modules? - }) - ).allow(null) -}).options({ allowUnknown: true }) + try { + Multiaddr(v) + } catch (err) { + return `multiaddr invalid, ${err.message}` + } -module.exports.validate = (config) => Joi.attempt(config, schema) + return true + }, + 'multiaddr-ipfs': v => mafmt.IPFS.matches(v) ? true : `multiaddr IPFS invalid` + } +}) + +const configSchema = s({ + repo: optional(s('object|string')), + repoOwner: 'boolean?', + preload: s({ + enabled: 'boolean?', + addresses: optional(s(['multiaddr'])), + interval: 'number?' + }, { enabled: true, interval: 30 * 1000 }), + init: optional(union(['boolean', s({ + bits: 'number?', + emptyRepo: 'boolean?', + privateKey: optional(s('object|string')), // object should be a custom type for PeerId using 'kind-of' + pass: 'string?' + })])), + start: 'boolean?', + offline: 'boolean?', + pass: 'string?', + silent: 'boolean?', + relay: 'object?', // relay validates in libp2p + EXPERIMENTAL: optional(s({ + pubsub: 'boolean?', + ipnsPubsub: 'boolean?', + sharding: 'boolean?', + dht: 'boolean?' + })), + connectionManager: 'object?', + config: optional(s({ + API: 'object?', + Addresses: optional(s({ + Swarm: optional(s(['multiaddr'])), + API: 'multiaddr?', + Gateway: 'multiaddr' + })), + Discovery: optional(s({ + MDNS: optional(s({ + Enabled: 'boolean?', + Interval: 'number?' + })), + webRTCStar: optional(s({ + Enabled: 'boolean?' + })) + })), + Bootstrap: optional(s(['multiaddr-ipfs'])) + })), + libp2p: optional(union(['function', 'object'])) // libp2p validates this +}, { + repoOwner: true +}) +module.exports.validate = (opts) => { + const [error, options] = configSchema.validate(opts) + + // Improve errors throwed, reduce stack by throwing here and add reason to the message + if (error) { + throw new Error(`${error.message}${error.reason ? ' - ' + error.reason : ''}`) + } + + return options +} diff --git a/src/core/index.js b/src/core/index.js index 8248a21765..637040febe 100644 --- a/src/core/index.js +++ b/src/core/index.js @@ -13,7 +13,7 @@ const multibase = require('multibase') const multicodec = require('multicodec') const CID = require('cids') const debug = require('debug') -const defaultsDeep = require('@nodeutils/defaults-deep') +const mergeOptions = require('merge-options') const EventEmitter = require('events') const config = require('./config') @@ -24,40 +24,7 @@ const components = require('./components') const defaultRepo = require('./runtime/repo-nodejs') const preload = require('./preload') const mfsPreload = require('./mfs-preload') - -// All known (non-default) IPLD formats -const IpldFormats = { - get 'bitcoin-block' () { - return require('ipld-bitcoin') - }, - get 'eth-account-snapshot' () { - return require('ipld-ethereum').ethAccountSnapshot - }, - get 'eth-block' () { - return require('ipld-ethereum').ethBlock - }, - get 'eth-block-list' () { - return require('ipld-ethereum').ethBlockList - }, - get 'eth-state-trie' () { - return require('ipld-ethereum').ethStateTrie - }, - get 'eth-storage-trie' () { - return require('ipld-ethereum').ethStorageTrie - }, - get 'eth-tx' () { - return require('ipld-ethereum').ethTx - }, - get 'eth-tx-trie' () { - return require('ipld-ethereum').ethTxTrie - }, - get 'git-raw' () { - return require('ipld-git') - }, - get 'zcash-block' () { - return require('ipld-zcash') - } -} +const ipldOptions = require('./runtime/ipld-nodejs') class IPFS extends EventEmitter { constructor (options) { @@ -78,7 +45,7 @@ class IPFS extends EventEmitter { options = config.validate(options || {}) - this._options = defaultsDeep(options, defaults) + this._options = mergeOptions(defaults, options) if (options.init === false) { this._options.init = false @@ -105,14 +72,7 @@ class IPFS extends EventEmitter { this._peerInfo = undefined this._bitswap = undefined this._blockService = new BlockService(this._repo) - this._ipld = new Ipld({ - blockService: this._blockService, - loadFormat: (codec, callback) => { - this.log('Loading IPLD format', codec) - if (IpldFormats[codec]) return callback(null, IpldFormats[codec]) - callback(new Error(`Missing IPLD format "${codec}"`)) - } - }) + this._ipld = new Ipld(ipldOptions(this._blockService, this._options.ipld, this.log)) this._preload = preload(this) this._mfsPreload = mfsPreload(this) this._ipns = undefined diff --git a/src/core/runtime/ipld-browser.js b/src/core/runtime/ipld-browser.js new file mode 100644 index 0000000000..2420a8dae3 --- /dev/null +++ b/src/core/runtime/ipld-browser.js @@ -0,0 +1,8 @@ +'use strict' +const mergeOptions = require('merge-options') + +module.exports = (blockService, options = {}) => { + return mergeOptions({ + blockService: blockService + }, options) +} diff --git a/src/core/runtime/ipld-nodejs.js b/src/core/runtime/ipld-nodejs.js new file mode 100644 index 0000000000..e2d143d0e0 --- /dev/null +++ b/src/core/runtime/ipld-nodejs.js @@ -0,0 +1,47 @@ +'use strict' +const mergeOptions = require('merge-options') + +// All known (non-default) IPLD formats +const IpldFormats = { + get 'bitcoin-block' () { + return require('ipld-bitcoin') + }, + get 'eth-account-snapshot' () { + return require('ipld-ethereum').ethAccountSnapshot + }, + get 'eth-block' () { + return require('ipld-ethereum').ethBlock + }, + get 'eth-block-list' () { + return require('ipld-ethereum').ethBlockList + }, + get 'eth-state-trie' () { + return require('ipld-ethereum').ethStateTrie + }, + get 'eth-storage-trie' () { + return require('ipld-ethereum').ethStorageTrie + }, + get 'eth-tx' () { + return require('ipld-ethereum').ethTx + }, + get 'eth-tx-trie' () { + return require('ipld-ethereum').ethTxTrie + }, + get 'git-raw' () { + return require('ipld-git') + }, + get 'zcash-block' () { + return require('ipld-zcash') + } +} + +module.exports = (blockService, options = {}, log) => { + return mergeOptions({ + blockService: blockService, + loadFormat: (codec, callback) => { + log('Loading IPLD format', codec) + if (IpldFormats[codec]) return callback(null, IpldFormats[codec]) + callback(new Error(`Missing IPLD format "${codec}"`)) + } + }, options) +} diff --git a/src/core/runtime/libp2p-browser.js b/src/core/runtime/libp2p-browser.js index 8fae1ae176..19fe27398b 100644 --- a/src/core/runtime/libp2p-browser.js +++ b/src/core/runtime/libp2p-browser.js @@ -8,7 +8,7 @@ const SECIO = require('libp2p-secio') const Bootstrap = require('libp2p-bootstrap') const KadDHT = require('libp2p-kad-dht') const libp2p = require('libp2p') -const defaultsDeep = require('@nodeutils/defaults-deep') +const mergeOptions = require('merge-options') const multiaddr = require('multiaddr') class Node extends libp2p { @@ -62,7 +62,7 @@ class Node extends libp2p { } } - super(defaultsDeep(_options, defaults)) + super(mergeOptions(defaults, _options)) } } diff --git a/src/core/runtime/libp2p-nodejs.js b/src/core/runtime/libp2p-nodejs.js index 01e7046e19..4f11036a86 100644 --- a/src/core/runtime/libp2p-nodejs.js +++ b/src/core/runtime/libp2p-nodejs.js @@ -9,7 +9,7 @@ const KadDHT = require('libp2p-kad-dht') const Multiplex = require('libp2p-mplex') const SECIO = require('libp2p-secio') const libp2p = require('libp2p') -const defaultsDeep = require('@nodeutils/defaults-deep') +const mergeOptions = require('merge-options') const multiaddr = require('multiaddr') class Node extends libp2p { @@ -65,7 +65,7 @@ class Node extends libp2p { } } - super(defaultsDeep(_options, defaults)) + super(mergeOptions(defaults, _options)) } } diff --git a/src/http/api/resources/config.js b/src/http/api/resources/config.js index 944d6058ba..d0ee5011b8 100644 --- a/src/http/api/resources/config.js +++ b/src/http/api/resources/config.js @@ -1,8 +1,8 @@ 'use strict' const debug = require('debug') -const get = require('lodash/get') -const set = require('lodash/set') +const get = require('dlv') +const set = require('just-safe-set') const log = debug('ipfs:http-api:config') log.error = debug('ipfs:http-api:config:error') const multipart = require('ipfs-multipart') @@ -74,11 +74,14 @@ exports.getOrSet = { } } else { // Set the new value of a given key - const updatedConfig = set(originalConfig, key, value) + const result = set(originalConfig, key, value) + if (!result) { + throw Boom.badRequest('Failed to set config value') + } try { - await ipfs.config.replace(updatedConfig) + await ipfs.config.replace(originalConfig) } catch (err) { - throw Boom.boomify(err, { message: 'Failed to get config value' }) + throw Boom.boomify(err, { message: 'Failed to replace config value' }) } } diff --git a/src/http/api/resources/pin.js b/src/http/api/resources/pin.js index b4232c6916..29e80dcd9d 100644 --- a/src/http/api/resources/pin.js +++ b/src/http/api/resources/pin.js @@ -1,12 +1,10 @@ 'use strict' -const mapValues = require('lodash/mapValues') -const keyBy = require('lodash/keyBy') const multibase = require('multibase') -const Joi = require('joi') const Boom = require('boom') const isIpfs = require('is-ipfs') const { cidToString } = require('../../../utils/cid') +const Joi = require('joi') function parseArgs (request, h) { let { arg } = request.query @@ -63,10 +61,11 @@ exports.ls = { } return h.response({ - Keys: mapValues( - keyBy(result, obj => cidToString(obj.hash, { base: request.query['cid-base'] })), - obj => ({ Type: obj.type }) - ) + Keys: result.reduce((acc, v) => { + const prop = cidToString(v.hash, { base: request.query['cid-base'] }) + acc[prop] = { Type: v.type } + return acc + }, {}) }) } } diff --git a/test/cli/dag.js b/test/cli/dag.js index 9cd6a3a586..ba0c9f65b3 100644 --- a/test/cli/dag.js +++ b/test/cli/dag.js @@ -15,13 +15,15 @@ describe('dag', () => runOnAndOff.off((thing) => { this.timeout(20 * 1000) // put test eth-block - return ipfs('block put --format eth-block --mhtype keccak-256 test/fixtures/test-data/eth-block').then((out) => { - expect(out).to.eql('z43AaGF23fmvRnDP56Ub9WcJCfzSfqtmzNCCvmz5eudT8dtdCDS\n') - // lookup path on eth-block - return ipfs('dag get z43AaGF23fmvRnDP56Ub9WcJCfzSfqtmzNCCvmz5eudT8dtdCDS/parentHash') - }).then((out) => { - let expectHash = Buffer.from('c8c0a17305adea9bbb4b98a52d44f0c1478f5c48fc4b64739ee805242501b256', 'hex') - expect(out).to.be.eql('0x' + expectHash.toString('hex') + '\n') - }) + return ipfs('block put --format eth-block --mhtype keccak-256 test/fixtures/test-data/eth-block') + .then((out) => { + expect(out).to.eql('z43AaGF23fmvRnDP56Ub9WcJCfzSfqtmzNCCvmz5eudT8dtdCDS\n') + // lookup path on eth-block + return ipfs('dag get z43AaGF23fmvRnDP56Ub9WcJCfzSfqtmzNCCvmz5eudT8dtdCDS/parentHash') + }) + .then((out) => { + let expectHash = Buffer.from('c8c0a17305adea9bbb4b98a52d44f0c1478f5c48fc4b64739ee805242501b256', 'hex') + expect(out).to.be.eql('0x' + expectHash.toString('hex') + '\n') + }) }) })) diff --git a/test/cli/files.js b/test/cli/files.js index e9a6c69422..e5237ff0cc 100644 --- a/test/cli/files.js +++ b/test/cli/files.js @@ -311,7 +311,7 @@ describe('files', () => runOnAndOff((thing) => { it('add --silent', function () { this.timeout(30 * 1000) - return ipfs('add --silent src/init-files/init-docs/readme') + return ipfs('add src/init-files/init-docs/readme --silent') .then((out) => { expect(out) .to.eql('') diff --git a/test/core/bitswap.spec.js b/test/core/bitswap.spec.js index 9540aba53e..aba37ccfa5 100644 --- a/test/core/bitswap.spec.js +++ b/test/core/bitswap.spec.js @@ -6,7 +6,7 @@ const chai = require('chai') const dirtyChai = require('dirty-chai') const expect = chai.expect chai.use(dirtyChai) -const _ = require('lodash') +const range = require('just-range') const series = require('async/series') const waterfall = require('async/waterfall') const parallel = require('async/parallel') @@ -36,7 +36,7 @@ function wire (targetNode, dialerNode, callback) { expect(err).to.not.exist() const addr = identity.addresses .map((addr) => multiaddr(addr.toString().split('ipfs')[0])) - .filter((addr) => _.includes(addr.protoNames(), 'ws'))[0] + .filter((addr) => addr.protoNames().includes('ws'))[0] if (!addr) { // Note: the browser doesn't have a websockets listening addr @@ -113,10 +113,8 @@ describe('bitswap', function () { if (isNode) { config = Object.assign({}, config, { - config: { - Addresses: { - Swarm: ['/ip4/127.0.0.1/tcp/0'] - } + Addresses: { + Swarm: ['/ip4/127.0.0.1/tcp/0'] } }) } @@ -175,7 +173,7 @@ describe('bitswap', function () { const remoteNodes = [] series([ - (cb) => parallel(_.range(6).map((i) => makeBlock), (err, _blocks) => { + (cb) => parallel(range(6).map((i) => makeBlock), (err, _blocks) => { expect(err).to.not.exist() blocks = _blocks cb() @@ -196,7 +194,7 @@ describe('bitswap', function () { (cb) => inProcNode.block.put(blocks[4], cb), (cb) => inProcNode.block.put(blocks[5], cb), // 3. Fetch blocks on all nodes - (cb) => parallel(_.range(6).map((i) => (cbI) => { + (cb) => parallel(range(6).map((i) => (cbI) => { const check = (n, cid, callback) => { n.block.get(cid, (err, b) => { expect(err).to.not.exist() diff --git a/test/core/config.spec.js b/test/core/config.spec.js index 3250c5b9d4..4ce3ffab05 100644 --- a/test/core/config.spec.js +++ b/test/core/config.spec.js @@ -19,16 +19,10 @@ describe('config', () => { expect(() => config.validate(cfg)).to.not.throw() }) - it('should allow unknown key at root', () => { - const cfg = { [`${Date.now()}`]: 'test' } - expect(() => config.validate(cfg)).to.not.throw() - }) - it('should validate valid repo', () => { const cfgs = [ { repo: { unknown: 'value' } }, { repo: '/path/to-repo' }, - { repo: null }, { repo: undefined } ] @@ -46,10 +40,8 @@ describe('config', () => { it('should validate valid init', () => { const cfgs = [ { init: { bits: 138 } }, - { init: { bits: 138, unknown: 'value' } }, { init: true }, { init: false }, - { init: null }, { init: undefined } ] @@ -104,36 +96,10 @@ describe('config', () => { cfgs.forEach(cfg => expect(() => config.validate(cfg)).to.throw()) }) - it('should validate valid relay', () => { - const cfgs = [ - { relay: { enabled: true, hop: { enabled: true } } }, - { relay: { enabled: false, hop: { enabled: false } } }, - { relay: { enabled: false, hop: null } }, - { relay: { enabled: false } }, - { relay: null }, - { relay: undefined } - ] - - cfgs.forEach(cfg => expect(() => config.validate(cfg)).to.not.throw()) - }) - - it('should validate invalid relay', () => { - const cfgs = [ - { relay: 138 }, - { relay: { enabled: 138 } }, - { relay: { enabled: true, hop: 138 } }, - { relay: { enabled: true, hop: { enabled: 138 } } } - ] - - cfgs.forEach(cfg => expect(() => config.validate(cfg)).to.throw()) - }) - it('should validate valid EXPERIMENTAL', () => { const cfgs = [ { EXPERIMENTAL: { pubsub: true, dht: true, sharding: true } }, { EXPERIMENTAL: { pubsub: false, dht: false, sharding: false } }, - { EXPERIMENTAL: { unknown: 'value' } }, - { EXPERIMENTAL: null }, { EXPERIMENTAL: undefined } ] @@ -162,32 +128,22 @@ describe('config', () => { { config: { Addresses: { Gateway: '/ip4/127.0.0.1/tcp/9090' } } }, { config: { Addresses: { Gateway: undefined } } }, - { config: { Addresses: { unknown: 'value' } } }, - { config: { Addresses: null } }, { config: { Addresses: undefined } }, { config: { Discovery: { MDNS: { Enabled: true } } } }, { config: { Discovery: { MDNS: { Enabled: false } } } }, { config: { Discovery: { MDNS: { Interval: 138 } } } }, - { config: { Discovery: { MDNS: { unknown: 'value' } } } }, - { config: { Discovery: { MDNS: null } } }, { config: { Discovery: { MDNS: undefined } } }, { config: { Discovery: { webRTCStar: { Enabled: true } } } }, { config: { Discovery: { webRTCStar: { Enabled: false } } } }, - { config: { Discovery: { webRTCStar: { unknown: 'value' } } } }, - { config: { Discovery: { webRTCStar: null } } }, { config: { Discovery: { webRTCStar: undefined } } }, - { config: { Discovery: { unknown: 'value' } } }, - { config: { Discovery: null } }, { config: { Discovery: undefined } }, { config: { Bootstrap: ['/ip4/104.236.176.52/tcp/4001/ipfs/QmSoLnSGccFuZQJzRadHn95W2CrSFmZuTdDWP8HXaHca9z'] } }, { config: { Bootstrap: [] } }, - { config: { unknown: 'value' } }, - { config: null }, { config: undefined } ] @@ -222,12 +178,7 @@ describe('config', () => { it('should validate valid libp2p', () => { const cfgs = [ { libp2p: { modules: {} } }, - { libp2p: { modules: { unknown: 'value' } } }, - { libp2p: { modules: null } }, - { libp2p: { modules: undefined } }, - { libp2p: { unknown: 'value' } }, { libp2p: () => {} }, - { libp2p: null }, { libp2p: undefined } ] @@ -236,7 +187,7 @@ describe('config', () => { it('should validate invalid libp2p', () => { const cfgs = [ - { libp2p: { modules: 138 } }, + { libp2p: 'error' }, { libp2p: 138 } ] diff --git a/test/utils/ipfs-exec.js b/test/utils/ipfs-exec.js index 3f9572f2a3..7198dd4938 100644 --- a/test/utils/ipfs-exec.js +++ b/test/utils/ipfs-exec.js @@ -6,8 +6,6 @@ const dirtyChai = require('dirty-chai') const expect = chai.expect chai.use(dirtyChai) -const _ = require('lodash') - // This is our new test utility to easily check and execute ipfs cli commands. // // The top level export is a function that can be passed a `repoPath` @@ -19,12 +17,9 @@ const _ = require('lodash') // The `.fail` variation asserts that the command exited with `Code > 0` // and returns a promise that resolves to `stderr`. module.exports = (repoPath, opts) => { - const env = _.clone(process.env) - env.IPFS_PATH = repoPath - const config = Object.assign({}, { stripEof: false, - env: env, + env: Object.assign({ IPFS_PATH: repoPath }, process.env), timeout: 60 * 1000 }, opts)