diff --git a/.aegir.js b/.aegir.js index c09767c77d..cc10babb26 100644 --- a/.aegir.js +++ b/.aegir.js @@ -10,7 +10,8 @@ const preloadNode = MockPreloadNode.createNode() module.exports = { webpack: { resolve: { - mainFields: ['browser', 'main'] + mainFields: ['browser', 'main'], + aliasFields: ['browser', 'browser-all-ipld-formats'], } }, karma: { diff --git a/README.md b/README.md index 37629b9486..a32bf0943e 100644 --- a/README.md +++ b/README.md @@ -326,6 +326,146 @@ 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. + + > Browser config does **NOT** include by default all the IPLD formats. Only `ipld-dag-pb`, `ipld-dag-cbor` and `ipld-raw` are included. + + To add support for other formats we provide two options, one sync and another async. + + Examples for the sync option: + +
ESM Environments + +```js +import ipldGit from 'ipld-git' +import ipldBitcoin from 'ipld-bitcoin' + +const node = new IPFS( + { + ipld: { + formats: [ipldGit, ipldBitcoin] + } + } +) +``` +
+
Commonjs Environments + +```js +const node = new IPFS( + { + ipld: { + formats: [require('ipld-git'), require('ipld-bitcoin')] + } + } +) +``` +
+
Using script tags + +```html + + + + +``` +
+ + Examples for the async option: + + +
ESM Environments + +```js +const node = new IPFS( + { + ipld: { + async loadFormat (codec) { + if (codec === 'git-raw') { + return import('ipld-git') // This is a dynamic import + } else { + throw new Error('unable to load format ' + multicodec.print[codec]) + } + } + } + } +) +``` +> For more information about dynamic imports please check [webpack docs](https://webpack.js.org/guides/code-splitting/#dynamic-imports) or search your bundler documention. + +Using dynamic imports will tell your bundler to create a separate file (normally called *chunk*) that will **only** be requested by the browser if it's really needed. This strategy will reduce your bundle size and load times without removing any functionality. + +With Webpack IPLD formats can even be grouped together using magic comments `import(/* webpackChunkName: "ipld-formats" */ 'ipld-git')` to produce a single file with all of them. + +
+
Commonjs Environments + +```js +const node = new IPFS( + { + ipld: { + async loadFormat (codec) { + if (codec === 'git-raw') { + return require('ipld-git') + } else { + throw new Error('unable to load format ' + multicodec.print[codec]) + } + } + } + } +) +``` +
+ +
Using Script tags + +```js + + +``` +
+ + ##### `options.libp2p` | Type | Default | diff --git a/package.json b/package.json index 53dbec020a..458e70fc4d 100644 --- a/package.json +++ b/package.json @@ -16,10 +16,14 @@ "./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" }, + "browser-all-ipld-formats": { + "./src/core/runtime/ipld-browser.js": "./src/core/runtime/ipld-browser-all.js" + }, "engines": { "node": ">=10.0.0", "npm": ">=6.0.0" @@ -115,9 +119,11 @@ "ipfs-unixfs-importer": "~0.38.5", "ipld": "~0.21.1", "ipld-bitcoin": "~0.1.8", + "ipld-dag-cbor": "~0.13.1", "ipld-dag-pb": "~0.15.3", "ipld-ethereum": "^2.0.1", "ipld-git": "~0.3.0", + "ipld-raw": "^2.0.1", "ipld-zcash": "~0.1.6", "ipns": "~0.5.0", "is-ipfs": "~0.6.0", diff --git a/src/core/index.js b/src/core/index.js index 812043f7ca..d457cb6149 100644 --- a/src/core/index.js +++ b/src/core/index.js @@ -25,40 +25,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) { @@ -106,14 +73,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-all.js b/src/core/runtime/ipld-browser-all.js new file mode 100644 index 0000000000..be618364fa --- /dev/null +++ b/src/core/runtime/ipld-browser-all.js @@ -0,0 +1,26 @@ +'use strict' +const mergeOptions = require('merge-options') + +module.exports = (blockService, options = {}) => { + return mergeOptions.call( + // ensure we have the defaults formats even if the user overrides `formats: []` + { concatArrays: true }, + { + blockService: blockService, + formats: [ + require('ipld-dag-cbor'), + require('ipld-dag-pb'), + require('ipld-raw'), + require('ipld-bitcoin'), + require('ipld-ethereum').ethAccountSnapshot, + require('ipld-ethereum').ethBlock, + require('ipld-ethereum').ethBlockList, + require('ipld-ethereum').ethStateTrie, + require('ipld-ethereum').ethStorageTrie, + require('ipld-ethereum').ethTx, + require('ipld-ethereum').ethTxTrie, + require('ipld-git'), + require('ipld-zcash') + ] + }, options) +} diff --git a/src/core/runtime/ipld-browser.js b/src/core/runtime/ipld-browser.js new file mode 100644 index 0000000000..31c19c141a --- /dev/null +++ b/src/core/runtime/ipld-browser.js @@ -0,0 +1,15 @@ +'use strict' +const mergeOptions = require('merge-options') +const ipldDagCbor = require('ipld-dag-cbor') +const ipldDagPb = require('ipld-dag-pb') +const ipldRaw = require('ipld-raw') + +module.exports = (blockService, options = {}) => { + return mergeOptions.call( + // ensure we have the defaults formats even if the user overrides `formats: []` + { concatArrays: true }, + { + blockService: blockService, + formats: [ipldDagCbor, ipldDagPb, ipldRaw] + }, options) +} diff --git a/src/core/runtime/ipld-nodejs.js b/src/core/runtime/ipld-nodejs.js new file mode 100644 index 0000000000..aa2172fe82 --- /dev/null +++ b/src/core/runtime/ipld-nodejs.js @@ -0,0 +1,54 @@ +'use strict' +const mergeOptions = require('merge-options') +const ipldDagCbor = require('ipld-dag-cbor') +const ipldDagPb = require('ipld-dag-pb') +const ipldRaw = require('ipld-raw') + +// 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.call( + // ensure we have the defaults formats even if the user overrides `formats: []` + { concatArrays: true }, + { + blockService: blockService, + formats: [ipldDagCbor, ipldDagPb, ipldRaw], + loadFormat: (codec, callback) => { + log('Loading IPLD format', codec) + if (IpldFormats[codec]) return callback(null, IpldFormats[codec]) + callback(new Error(`Missing IPLD format "${codec}"`)) + } + }, options) +}