diff --git a/dist/es5/OrbitDB.js b/dist/es5/OrbitDB.js new file mode 100644 index 0000000..f89f533 --- /dev/null +++ b/dist/es5/OrbitDB.js @@ -0,0 +1,457 @@ +'use strict'; + +var _stringify = require('babel-runtime/core-js/json/stringify'); + +var _stringify2 = _interopRequireDefault(_stringify); + +var _setImmediate2 = require('babel-runtime/core-js/set-immediate'); + +var _setImmediate3 = _interopRequireDefault(_setImmediate2); + +var _getIterator2 = require('babel-runtime/core-js/get-iterator'); + +var _getIterator3 = _interopRequireDefault(_getIterator2); + +var _values = require('babel-runtime/core-js/object/values'); + +var _values2 = _interopRequireDefault(_values); + +var _assign = require('babel-runtime/core-js/object/assign'); + +var _assign2 = _interopRequireDefault(_assign); + +var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck'); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +var _createClass2 = require('babel-runtime/helpers/createClass'); + +var _createClass3 = _interopRequireDefault(_createClass2); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var path = require('path'); +var EventStore = require('orbit-db-eventstore'); +var FeedStore = require('orbit-db-feedstore'); +var KeyValueStore = require('orbit-db-kvstore'); +var CounterStore = require('orbit-db-counterstore'); +var DocumentStore = require('orbit-db-docstore'); +var Pubsub = require('orbit-db-pubsub'); +var Cache = require('orbit-db-cache'); +var Keystore = require('orbit-db-keystore'); +var AccessController = require('./ipfs-access-controller'); +var OrbitDBAddress = require('./orbit-db-address'); + +var Logger = require('logplease'); +var logger = Logger.create("orbit-db"); +Logger.setLogLevel('NONE'); + +var validTypes = ['eventlog', 'feed', 'docstore', 'counter', 'keyvalue']; + +var OrbitDB = function () { + function OrbitDB(ipfs, directory) { + var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; + (0, _classCallCheck3.default)(this, OrbitDB); + + this._ipfs = ipfs; + this.id = options.peerId || (this._ipfs._peerInfo ? this._ipfs._peerInfo.id._idB58String : 'default'); + this._pubsub = options && options.broker ? new options.broker(this._ipfs) : new Pubsub(this._ipfs, this.id); + this.stores = {}; + this.types = validTypes; + this.directory = directory || './orbitdb'; + this.keystore = new Keystore(path.join(this.directory, this.id, '/keystore')); + this.key = this.keystore.getKey(this.id) || this.keystore.createKey(this.id); + } + + /* Databases */ + + + (0, _createClass3.default)(OrbitDB, [{ + key: 'feed', + value: async function feed(address) { + var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + options = (0, _assign2.default)({ create: true, type: 'feed' }, options); + return this.open(address, options); + } + }, { + key: 'log', + value: async function log(address, options) { + options = (0, _assign2.default)({ create: true, type: 'eventlog' }, options); + return this.open(address, options); + } + }, { + key: 'eventlog', + value: async function eventlog(address) { + var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + return this.log(address, options); + } + }, { + key: 'keyvalue', + value: async function keyvalue(address, options) { + options = (0, _assign2.default)({ create: true, type: 'keyvalue' }, options); + return this.open(address, options); + } + }, { + key: 'kvstore', + value: async function kvstore(address, options) { + return this.keyvalue(address, options); + } + }, { + key: 'counter', + value: async function counter(address) { + var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + options = (0, _assign2.default)({ create: true, type: 'counter' }, options); + return this.open(address, options); + } + }, { + key: 'docs', + value: async function docs(address) { + var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + options = (0, _assign2.default)({ create: true, type: 'docstore' }, options); + return this.open(address, options); + } + }, { + key: 'docstore', + value: async function docstore(address) { + var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + return this.docs(address, options); + } + }, { + key: 'disconnect', + value: async function disconnect() { + // Close all open databases + var databases = (0, _values2.default)(this.stores); + var _iteratorNormalCompletion = true; + var _didIteratorError = false; + var _iteratorError = undefined; + + try { + for (var _iterator = (0, _getIterator3.default)(databases), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { + var db = _step.value; + + await db.close(); + delete this.stores[db.address.toString()]; + } + + // Disconnect from pubsub + } catch (err) { + _didIteratorError = true; + _iteratorError = err; + } finally { + try { + if (!_iteratorNormalCompletion && _iterator.return) { + _iterator.return(); + } + } finally { + if (_didIteratorError) { + throw _iteratorError; + } + } + } + + if (this._pubsub) this._pubsub.disconnect + + // Remove all databases from the state + ();this.stores = {}; + } + + // Alias for disconnect() + + }, { + key: 'stop', + value: async function stop() { + await this.disconnect(); + } + + /* Private methods */ + + }, { + key: '_createStore', + value: async function _createStore(Store, address, options) { + var addr = address.toString(); + + var accessController = void 0; + if (options.accessControllerAddress) { + accessController = new AccessController(this._ipfs); + await accessController.load(options.accessControllerAddress); + } + + var opts = (0, _assign2.default)({ replicate: true }, options, { + accessController: accessController, + keystore: this.keystore, + cache: this._cache + }); + + var store = new Store(this._ipfs, this.id, address, opts); + store.events.on('write', this._onWrite.bind(this)); + store.events.on('closed', this._onClosed.bind(this)); + + this.stores[addr] = store; + + if (opts.replicate && this._pubsub) this._pubsub.subscribe(addr, this._onMessage.bind(this), this._onPeerConnected.bind(this)); + + return store; + } + + // Callback for local writes to the database. We the update to pubsub. + + }, { + key: '_onWrite', + value: function _onWrite(address, entry, heads) { + var _this = this; + + if (!heads) throw new Error("'heads' not defined"); + if (this._pubsub) (0, _setImmediate3.default)(function () { + return _this._pubsub.publish(address, heads); + }); + } + + // Callback for receiving a message from the network + + }, { + key: '_onMessage', + value: async function _onMessage(address, heads) { + var store = this.stores[address]; + try { + logger.debug('Received heads for \'' + address + '\':\n', (0, _stringify2.default)(heads, null, 2)); + await store.sync(heads); + } catch (e) { + logger.error(e); + } + } + + // Callback for when a peer connected to a database + + }, { + key: '_onPeerConnected', + value: function _onPeerConnected(address, peer, room) { + logger.debug('New peer \'' + peer + '\' connected to \'' + address + '\''); + var store = this.stores[address]; + if (store) { + // Send the newly connected peer our latest heads + var heads = store._oplog.heads; + if (heads.length > 0) { + logger.debug('Send latest heads:\n', (0, _stringify2.default)(heads, null, 2)); + room.sendTo(peer, new Buffer((0, _stringify2.default)(heads))); + } + store.events.emit('peer', peer); + } + } + + // Callback when database was closed + + }, { + key: '_onClosed', + value: function _onClosed(address) { + logger.debug('Database \'' + address + '\' was closed' + + // Remove the callback from the database + );this.stores[address].events.removeAllListeners('closed' + + // Unsubscribe from pubsub + );if (this._pubsub) this._pubsub.unsubscribe(address); + + delete this.stores[address]; + } + + /* Create and Open databases */ + + /* + options = { + admin: [], // array of keys that are the admins of this database (same as write access) + write: [], // array of keys that can write to this database + directory: './orbitdb', // directory in which to place the database files + overwrite: false, // whether we should overwrite the existing database if it exists + } + */ + + }, { + key: 'create', + value: async function create(name, type) { + var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; + + if (!OrbitDB.isValidType(type)) throw new Error('Invalid database type \'' + type + '\''); + + // The directory to look databases from can be passed in as an option + var directory = options.directory || this.directory; + logger.debug('Creating database \'' + name + '\' as ' + type + ' in \'' + directory + '\''); + + if (OrbitDBAddress.isValid(name)) throw new Error('Given database name is an address. Please give only the name of the database!'); + + // Create an AccessController + var accessController = new AccessController(this._ipfs); + /* Disabled temporarily until we do something with the admin keys */ + // Add admins of the database to the access controller + // if (options && options.admin) { + // options.admin.forEach(e => accessController.add('admin', e)) + // } else { + // // Default is to add ourselves as the admin of the database + // accessController.add('admin', this.key.getPublic('hex')) + // } + // Add keys that can write to the database + if (options && options.write) { + options.write.forEach(function (e) { + return accessController.add('write', e); + }); + } else { + // Default is to add ourselves as the admin of the database + accessController.add('write', this.key.getPublic('hex')); + } + // Save the Access Controller in IPFS + var accessControllerAddress = await accessController.save + + // Creates a DB manifest file + ();var createDBManifest = function createDBManifest() { + return { + name: name, + type: type, + accessController: path.join('/ipfs', accessControllerAddress) + }; + }; + + // Save the manifest to IPFS + var manifest = createDBManifest(); + var dag = await this._ipfs.object.put(new Buffer((0, _stringify2.default)(manifest))); + var manifestHash = dag.toJSON().multihash.toString + + // Create the database address + ();var address = path.join('/orbitdb', manifestHash, name); + var dbAddress = OrbitDBAddress.parse(address + + // Load local cache + );try { + var cacheFilePath = path.join(dbAddress.root, dbAddress.path); + this._cache = new Cache(path.join(directory), cacheFilePath); + await this._cache.load(); + } catch (e) { + logger.warn("Couldn't load Cache:", e); + } + + // Check if we already have the database + var localData = await this._cache.get(dbAddress.toString()); + + if (localData && localData.manifest && !options.overwrite) throw new Error('Database \'' + dbAddress + '\' already exists!'); + + // Save the database locally + localData = (0, _assign2.default)({}, this._cache.get(dbAddress.toString()), { + manifest: dbAddress.root + }); + await this._cache.set(dbAddress.toString(), localData); + logger.debug('Saved manifest to IPFS as \'' + dbAddress.root + '\''); + + logger.debug('Created database \'' + dbAddress + '\'' + + // Open the database + );return this.open(dbAddress, options); + } + + /* + options = { + localOnly: false // if set to true, throws an error if database can't be found locally + create: false // wether to create the database + type: TODO + overwrite: TODO + } + */ + + }, { + key: 'open', + value: async function open(address) { + var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + options = (0, _assign2.default)({ localOnly: false, create: false }, options); + logger.debug('Open database \'' + address + '\'' + + // The directory to look databases from can be passed in as an option + );var directory = options.directory || this.directory; + logger.debug('Look from \'' + directory + '\'' + + // If address is just the name of database, check the options to crate the database + );if (!OrbitDBAddress.isValid(address)) { + if (!options.create) { + throw new Error('\'options.create\' set to \'false\'. If you want to create a database, set \'options.create\' to \'true\'.'); + } else if (options.create && !options.type) { + throw new Error('Database type not provided! Provide a type with \'options.type\' (' + validTypes.join('|') + ')'); + } else { + logger.warn('Not a valid OrbitDB address \'' + address + '\', creating the database'); + options.overwrite = options.overwrite ? options.overwrite : true; + return this.create(address, options.type, options); + } + } + + // Parse the database address + var dbAddress = OrbitDBAddress.parse(address + + // Load local cache + );try { + var cacheFilePath = path.join(dbAddress.root, dbAddress.path); + this._cache = new Cache(path.join(directory), cacheFilePath); + await this._cache.load(); + } catch (e) { + console.warn(e); + logger.warn("Couldn't load Cache:", e); + } + + // Check if we have the database + var localData = await this._cache.get(dbAddress.toString()); + var haveDB = localData && localData.manifest; + logger.debug((haveDB ? 'Found' : 'Didn\'t find') + (' database \'' + dbAddress + '\'') + + // If we want to try and open the database local-only, throw an error + // if we don't have the database locally + );if (options.localOnly && !haveDB) { + logger.error('Database \'' + dbAddress + '\' doesn\'t exist!'); + throw new Error('Database \'' + dbAddress + '\' doesn\'t exist!'); + } + + logger.debug('Loading Manifest for \'' + dbAddress + '\'' + + // Get the database manifest from IPFS + );var dag = await this._ipfs.object.get(dbAddress.root); + var manifest = JSON.parse(dag.toJSON().data); + logger.debug('Manifest for \'' + dbAddress + '\':\n' + (0, _stringify2.default)(manifest, null, 2) + + // Make sure the type from the manifest matches the type that was given as an option + );if (options.type && manifest.type !== options.type) throw new Error('Database \'' + dbAddress + '\' is type \'' + manifest.type + '\' but was opened as \'' + options.type + '\''); + + // Save the database locally + localData = (0, _assign2.default)({}, this._cache.get(dbAddress.toString()), { + manifest: dbAddress.root + }); + await this._cache.set(dbAddress.toString(), localData); + logger.debug('Saved manifest to IPFS as \'' + dbAddress.root + '\'' + + // Open the the database + );options = (0, _assign2.default)({}, options, { accessControllerAddress: manifest.accessController }); + return this._openDatabase(dbAddress, manifest.type, options); + } + }, { + key: '_openDatabase', + value: async function _openDatabase(address, type, options) { + if (type === 'counter') return this._createStore(CounterStore, address, options);else if (type === 'eventlog') return this._createStore(EventStore, address, options);else if (type === 'feed') return this._createStore(FeedStore, address, options);else if (type === 'docstore') return this._createStore(DocumentStore, address, options);else if (type === 'keyvalue') return this._createStore(KeyValueStore, address, options);else throw new Error('Invalid database type \'' + type + '\''); + } + }], [{ + key: 'isValidType', + value: function isValidType(type) { + return validTypes.includes(type); + } + }, { + key: 'create', + value: function create() { + return new Error('Not implemented yet!'); + } + }, { + key: 'open', + value: function open() { + return new Error('Not implemented yet!'); + } + }]); + return OrbitDB; +}(); + +module.exports = OrbitDB; \ No newline at end of file diff --git a/dist/es5/access-controller.js b/dist/es5/access-controller.js new file mode 100644 index 0000000..d333446 --- /dev/null +++ b/dist/es5/access-controller.js @@ -0,0 +1,115 @@ +'use strict'; + +var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck'); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +var _createClass2 = require('babel-runtime/helpers/createClass'); + +var _createClass3 = _interopRequireDefault(_createClass2); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var AccessController = function () { + function AccessController() { + (0, _classCallCheck3.default)(this, AccessController); + + this._access = { + admin: [], + write: [], + read: [] // Not used atm + }; + } + + /* Overridable functions */ + + + (0, _createClass3.default)(AccessController, [{ + key: 'load', + value: async function load(address) {} + }, { + key: 'save', + value: async function save() {} + + /* Properties */ + + }, { + key: 'add', + + + /* Public Methods */ + value: function add(access, key) { + // if(!Object.keys(this._access).includes(access)) + // throw new Error(`unknown access level: ${access}`) + // if (!this._access[access].includes(key)) + // this._access[access].push(key) + + // TODO: uniques only + switch (access) { + case 'admin': + this._access.admin.push(key); + break; + case 'write': + this._access.write.push(key); + break; + case 'read': + this._access.read.push(key); + break; + default: + break; + } + } + }, { + key: 'remove', + value: function remove(access, key) { + var without = function without(arr, e) { + var reducer = function reducer(res, val) { + if (val !== key) res.push(val); + return res; + }; + return arr.reduce(reducer, []); + }; + + // if(!Object.keys(this._access).includes(access)) + // throw new Error(`unknown access level: ${access}`) + // if (this._access[access].includes(key)) + // this._access[access] = without(this._access[access], key) + + switch (access) { + case 'admin': + this._access.admin = without(this._access.admin, key); + break; + case 'write': + this._access.write = without(this._access.write, key); + break; + case 'read': + this._access.read = without(this._access.read, key); + break; + default: + break; + } + } + }, { + key: 'admin', + get: function get() { + return this._access.admin; + } + }, { + key: 'write', + get: function get() { + // Both admins and write keys can write + return this._access.write.concat(this._access.admin); + } + + // Not used atm + + }, { + key: 'read', + get: function get() { + return this._access.read; + } + }]); + return AccessController; +}(); + +module.exports = AccessController; \ No newline at end of file diff --git a/dist/es5/ipfs-access-controller.js b/dist/es5/ipfs-access-controller.js new file mode 100644 index 0000000..94fbd10 --- /dev/null +++ b/dist/es5/ipfs-access-controller.js @@ -0,0 +1,75 @@ +'use strict'; + +var _stringify = require('babel-runtime/core-js/json/stringify'); + +var _stringify2 = _interopRequireDefault(_stringify); + +var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of'); + +var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf); + +var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck'); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +var _createClass2 = require('babel-runtime/helpers/createClass'); + +var _createClass3 = _interopRequireDefault(_createClass2); + +var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn'); + +var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); + +var _inherits2 = require('babel-runtime/helpers/inherits'); + +var _inherits3 = _interopRequireDefault(_inherits2); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var AccessController = require('./access-controller'); + +var IPFSAccessController = function (_AccessController) { + (0, _inherits3.default)(IPFSAccessController, _AccessController); + + function IPFSAccessController(ipfs) { + (0, _classCallCheck3.default)(this, IPFSAccessController); + + var _this = (0, _possibleConstructorReturn3.default)(this, (IPFSAccessController.__proto__ || (0, _getPrototypeOf2.default)(IPFSAccessController)).call(this)); + + _this._ipfs = ipfs; + return _this; + } + + (0, _createClass3.default)(IPFSAccessController, [{ + key: 'load', + value: async function load(address) { + // Transform '/ipfs/QmPFtHi3cmfZerxtH9ySLdzpg1yFhocYDZgEZywdUXHxFU' + // to 'QmPFtHi3cmfZerxtH9ySLdzpg1yFhocYDZgEZywdUXHxFU' + if (address.indexOf('/ipfs') === 0) address = address.split('/')[2]; + + try { + var dag = await this._ipfs.object.get(address); + var obj = JSON.parse(dag.toJSON().data); + this._access = obj; + } catch (e) { + console.log("ACCESS ERROR:", e); + } + } + }, { + key: 'save', + value: async function save() { + var hash = void 0; + try { + var access = (0, _stringify2.default)(this._access, null, 2); + var dag = await this._ipfs.object.put(new Buffer(access)); + hash = dag.toJSON().multihash.toString(); + } catch (e) { + console.log("ACCESS ERROR:", e); + } + return hash; + } + }]); + return IPFSAccessController; +}(AccessController); + +module.exports = IPFSAccessController; \ No newline at end of file diff --git a/dist/es5/orbit-db-address.js b/dist/es5/orbit-db-address.js new file mode 100644 index 0000000..ee6d2e5 --- /dev/null +++ b/dist/es5/orbit-db-address.js @@ -0,0 +1,66 @@ +'use strict'; + +var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck'); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +var _createClass2 = require('babel-runtime/helpers/createClass'); + +var _createClass3 = _interopRequireDefault(_createClass2); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var path = require('path'); +var multihash = require('multihashes'); + +var OrbitDBAddress = function () { + function OrbitDBAddress(root, path) { + (0, _classCallCheck3.default)(this, OrbitDBAddress); + + this.root = root; + this.path = path; + } + + (0, _createClass3.default)(OrbitDBAddress, [{ + key: 'toString', + value: function toString() { + return path.join('/orbitdb', this.root, this.path); + } + }], [{ + key: 'isValid', + value: function isValid(address) { + var parts = address.toString().split('/').filter(function (e, i) { + return !((i === 0 || i === 1) && address.toString().indexOf('/orbit') === 0 && e === 'orbitdb'); + }).filter(function (e) { + return e !== '' && e !== ' '; + }); + + var accessControllerHash = parts[0].indexOf('Qm') > -1 ? multihash.fromB58String(parts[0]) : null; + try { + multihash.validate(accessControllerHash); + } catch (e) { + return false; + } + + return accessControllerHash !== null; + } + }, { + key: 'parse', + value: function parse(address) { + if (!address) throw new Error('Not a valid OrbitDB address: ' + address); + + if (!OrbitDBAddress.isValid(address)) throw new Error('Not a valid OrbitDB address: ' + address); + + var parts = address.toString().split('/').filter(function (e, i) { + return !((i === 0 || i === 1) && address.toString().indexOf('/orbit') === 0 && e === 'orbitdb'); + }).filter(function (e) { + return e !== '' && e !== ' '; + }); + + return new OrbitDBAddress(parts[0], parts.slice(1, parts.length).join('/')); + } + }]); + return OrbitDBAddress; +}(); + +module.exports = OrbitDBAddress; \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index c9720fd..7ff7a0f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4954,9 +4954,9 @@ } }, "idb-wrapper": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/idb-wrapper/-/idb-wrapper-1.7.1.tgz", - "integrity": "sha1-ajJnASLhc6hOzFz6lmj6LOsiGwQ=", + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/idb-wrapper/-/idb-wrapper-1.7.2.tgz", + "integrity": "sha512-zfNREywMuf0NzDo9mVsL0yegjsirJxHpKHvWcyRozIqQy89g0a3U+oBPOCN4cc0oCiOuYgZHimzaW/R46G1Mpg==", "dev": true }, "ieee754": { @@ -5189,7 +5189,7 @@ "dev": true, "requires": { "abstract-leveldown": "0.12.4", - "idb-wrapper": "1.7.1", + "idb-wrapper": "1.7.2", "isbuffer": "0.0.0", "ltgt": "2.2.0", "typedarray-to-buffer": "1.0.4", @@ -5696,7 +5696,7 @@ "dev": true, "requires": { "abstract-leveldown": "0.12.4", - "idb-wrapper": "1.7.1", + "idb-wrapper": "1.7.2", "isbuffer": "0.0.0", "ltgt": "2.2.0", "typedarray-to-buffer": "1.0.4", @@ -6270,7 +6270,7 @@ "dev": true, "requires": { "abstract-leveldown": "0.12.4", - "idb-wrapper": "1.7.1", + "idb-wrapper": "1.7.2", "isbuffer": "0.0.0", "ltgt": "2.2.0", "typedarray-to-buffer": "1.0.4", diff --git a/package.json b/package.json index 2f358c2..9009ab0 100644 --- a/package.json +++ b/package.json @@ -48,9 +48,10 @@ "examples:node": "node examples/eventlog.js", "examples:browser": "open examples/browser/browser.html", "test": "mocha", - "build": "npm run build:dist && npm run build:examples", + "build": "npm run build:es5 && npm run build:dist && npm run build:examples", "build:examples": "webpack --config conf/webpack.example.config.js --sort-modules-by size", "build:dist": "webpack --config conf/webpack.config.js --sort-modules-by size && cp dist/orbitdb.min.js examples/browser/lib/orbitdb.min.js", - "build:debug": "webpack --config conf/webpack.debug.config.js --sort-modules-by size && cp dist/orbitdb.js examples/browser/lib/orbitdb.min.js" + "build:debug": "webpack --config conf/webpack.debug.config.js --sort-modules-by size && cp dist/orbitdb.js examples/browser/lib/orbitdb.min.js", + "build:es5": "babel src --out-dir ./dist/es5/ --presets babel-preset-es2015 --plugins babel-plugin-transform-runtime" } }