UNPKG

@orbitdb/core

Version:

Distributed p2p database on IPFS

1,691 lines (1,340 loc) 1.29 MB
var OrbitDB; /******/ (() => { // webpackBootstrap /******/ var __webpack_modules__ = ({ /***/ "./node_modules/abstract-level/abstract-chained-batch.js": /*!***************************************************************!*\ !*** ./node_modules/abstract-level/abstract-chained-batch.js ***! \***************************************************************/ /***/ ((__unused_webpack_module, exports, __webpack_require__) => { "use strict"; const { fromCallback } = __webpack_require__(/*! catering */ "./node_modules/catering/index.js") const ModuleError = __webpack_require__(/*! module-error */ "./node_modules/module-error/index.js") const { getCallback, getOptions } = __webpack_require__(/*! ./lib/common */ "./node_modules/abstract-level/lib/common.js") const kPromise = Symbol('promise') const kStatus = Symbol('status') const kOperations = Symbol('operations') const kFinishClose = Symbol('finishClose') const kCloseCallbacks = Symbol('closeCallbacks') class AbstractChainedBatch { constructor (db) { if (typeof db !== 'object' || db === null) { const hint = db === null ? 'null' : typeof db throw new TypeError(`The first argument must be an abstract-level database, received ${hint}`) } this[kOperations] = [] this[kCloseCallbacks] = [] this[kStatus] = 'open' this[kFinishClose] = this[kFinishClose].bind(this) this.db = db this.db.attachResource(this) this.nextTick = db.nextTick } get length () { return this[kOperations].length } put (key, value, options) { if (this[kStatus] !== 'open') { throw new ModuleError('Batch is not open: cannot call put() after write() or close()', { code: 'LEVEL_BATCH_NOT_OPEN' }) } const err = this.db._checkKey(key) || this.db._checkValue(value) if (err) throw err const db = options && options.sublevel != null ? options.sublevel : this.db const original = options const keyEncoding = db.keyEncoding(options && options.keyEncoding) const valueEncoding = db.valueEncoding(options && options.valueEncoding) const keyFormat = keyEncoding.format // Forward encoding options options = { ...options, keyEncoding: keyFormat, valueEncoding: valueEncoding.format } // Prevent double prefixing if (db !== this.db) { options.sublevel = null } const mappedKey = db.prefixKey(keyEncoding.encode(key), keyFormat) const mappedValue = valueEncoding.encode(value) this._put(mappedKey, mappedValue, options) this[kOperations].push({ ...original, type: 'put', key, value }) return this } _put (key, value, options) {} del (key, options) { if (this[kStatus] !== 'open') { throw new ModuleError('Batch is not open: cannot call del() after write() or close()', { code: 'LEVEL_BATCH_NOT_OPEN' }) } const err = this.db._checkKey(key) if (err) throw err const db = options && options.sublevel != null ? options.sublevel : this.db const original = options const keyEncoding = db.keyEncoding(options && options.keyEncoding) const keyFormat = keyEncoding.format // Forward encoding options options = { ...options, keyEncoding: keyFormat } // Prevent double prefixing if (db !== this.db) { options.sublevel = null } this._del(db.prefixKey(keyEncoding.encode(key), keyFormat), options) this[kOperations].push({ ...original, type: 'del', key }) return this } _del (key, options) {} clear () { if (this[kStatus] !== 'open') { throw new ModuleError('Batch is not open: cannot call clear() after write() or close()', { code: 'LEVEL_BATCH_NOT_OPEN' }) } this._clear() this[kOperations] = [] return this } _clear () {} write (options, callback) { callback = getCallback(options, callback) callback = fromCallback(callback, kPromise) options = getOptions(options) if (this[kStatus] !== 'open') { this.nextTick(callback, new ModuleError('Batch is not open: cannot call write() after write() or close()', { code: 'LEVEL_BATCH_NOT_OPEN' })) } else if (this.length === 0) { this.close(callback) } else { this[kStatus] = 'writing' this._write(options, (err) => { this[kStatus] = 'closing' this[kCloseCallbacks].push(() => callback(err)) // Emit after setting 'closing' status, because event may trigger a // db close which in turn triggers (idempotently) closing this batch. if (!err) this.db.emit('batch', this[kOperations]) this._close(this[kFinishClose]) }) } return callback[kPromise] } _write (options, callback) {} close (callback) { callback = fromCallback(callback, kPromise) if (this[kStatus] === 'closing') { this[kCloseCallbacks].push(callback) } else if (this[kStatus] === 'closed') { this.nextTick(callback) } else { this[kCloseCallbacks].push(callback) if (this[kStatus] !== 'writing') { this[kStatus] = 'closing' this._close(this[kFinishClose]) } } return callback[kPromise] } _close (callback) { this.nextTick(callback) } [kFinishClose] () { this[kStatus] = 'closed' this.db.detachResource(this) const callbacks = this[kCloseCallbacks] this[kCloseCallbacks] = [] for (const cb of callbacks) { cb() } } } exports.AbstractChainedBatch = AbstractChainedBatch /***/ }), /***/ "./node_modules/abstract-level/abstract-iterator.js": /*!**********************************************************!*\ !*** ./node_modules/abstract-level/abstract-iterator.js ***! \**********************************************************/ /***/ ((__unused_webpack_module, exports, __webpack_require__) => { "use strict"; const { fromCallback } = __webpack_require__(/*! catering */ "./node_modules/catering/index.js") const ModuleError = __webpack_require__(/*! module-error */ "./node_modules/module-error/index.js") const { getOptions, getCallback } = __webpack_require__(/*! ./lib/common */ "./node_modules/abstract-level/lib/common.js") const kPromise = Symbol('promise') const kCallback = Symbol('callback') const kWorking = Symbol('working') const kHandleOne = Symbol('handleOne') const kHandleMany = Symbol('handleMany') const kAutoClose = Symbol('autoClose') const kFinishWork = Symbol('finishWork') const kReturnMany = Symbol('returnMany') const kClosing = Symbol('closing') const kHandleClose = Symbol('handleClose') const kClosed = Symbol('closed') const kCloseCallbacks = Symbol('closeCallbacks') const kKeyEncoding = Symbol('keyEncoding') const kValueEncoding = Symbol('valueEncoding') const kAbortOnClose = Symbol('abortOnClose') const kLegacy = Symbol('legacy') const kKeys = Symbol('keys') const kValues = Symbol('values') const kLimit = Symbol('limit') const kCount = Symbol('count') const emptyOptions = Object.freeze({}) const noop = () => {} let warnedEnd = false // This class is an internal utility for common functionality between AbstractIterator, // AbstractKeyIterator and AbstractValueIterator. It's not exported. class CommonIterator { constructor (db, options, legacy) { if (typeof db !== 'object' || db === null) { const hint = db === null ? 'null' : typeof db throw new TypeError(`The first argument must be an abstract-level database, received ${hint}`) } if (typeof options !== 'object' || options === null) { throw new TypeError('The second argument must be an options object') } this[kClosed] = false this[kCloseCallbacks] = [] this[kWorking] = false this[kClosing] = false this[kAutoClose] = false this[kCallback] = null this[kHandleOne] = this[kHandleOne].bind(this) this[kHandleMany] = this[kHandleMany].bind(this) this[kHandleClose] = this[kHandleClose].bind(this) this[kKeyEncoding] = options[kKeyEncoding] this[kValueEncoding] = options[kValueEncoding] this[kLegacy] = legacy this[kLimit] = Number.isInteger(options.limit) && options.limit >= 0 ? options.limit : Infinity this[kCount] = 0 // Undocumented option to abort pending work on close(). Used by the // many-level module as a temporary solution to a blocked close(). // TODO (next major): consider making this the default behavior. Native // implementations should have their own logic to safely close iterators. this[kAbortOnClose] = !!options.abortOnClose this.db = db this.db.attachResource(this) this.nextTick = db.nextTick } get count () { return this[kCount] } get limit () { return this[kLimit] } next (callback) { let promise if (callback === undefined) { promise = new Promise((resolve, reject) => { callback = (err, key, value) => { if (err) reject(err) else if (!this[kLegacy]) resolve(key) else if (key === undefined && value === undefined) resolve() else resolve([key, value]) } }) } else if (typeof callback !== 'function') { throw new TypeError('Callback must be a function') } if (this[kClosing]) { this.nextTick(callback, new ModuleError('Iterator is not open: cannot call next() after close()', { code: 'LEVEL_ITERATOR_NOT_OPEN' })) } else if (this[kWorking]) { this.nextTick(callback, new ModuleError('Iterator is busy: cannot call next() until previous call has completed', { code: 'LEVEL_ITERATOR_BUSY' })) } else { this[kWorking] = true this[kCallback] = callback if (this[kCount] >= this[kLimit]) this.nextTick(this[kHandleOne], null) else this._next(this[kHandleOne]) } return promise } _next (callback) { this.nextTick(callback) } nextv (size, options, callback) { callback = getCallback(options, callback) callback = fromCallback(callback, kPromise) options = getOptions(options, emptyOptions) if (!Number.isInteger(size)) { this.nextTick(callback, new TypeError("The first argument 'size' must be an integer")) return callback[kPromise] } if (this[kClosing]) { this.nextTick(callback, new ModuleError('Iterator is not open: cannot call nextv() after close()', { code: 'LEVEL_ITERATOR_NOT_OPEN' })) } else if (this[kWorking]) { this.nextTick(callback, new ModuleError('Iterator is busy: cannot call nextv() until previous call has completed', { code: 'LEVEL_ITERATOR_BUSY' })) } else { if (size < 1) size = 1 if (this[kLimit] < Infinity) size = Math.min(size, this[kLimit] - this[kCount]) this[kWorking] = true this[kCallback] = callback if (size <= 0) this.nextTick(this[kHandleMany], null, []) else this._nextv(size, options, this[kHandleMany]) } return callback[kPromise] } _nextv (size, options, callback) { const acc = [] const onnext = (err, key, value) => { if (err) { return callback(err) } else if (this[kLegacy] ? key === undefined && value === undefined : key === undefined) { return callback(null, acc) } acc.push(this[kLegacy] ? [key, value] : key) if (acc.length === size) { callback(null, acc) } else { this._next(onnext) } } this._next(onnext) } all (options, callback) { callback = getCallback(options, callback) callback = fromCallback(callback, kPromise) options = getOptions(options, emptyOptions) if (this[kClosing]) { this.nextTick(callback, new ModuleError('Iterator is not open: cannot call all() after close()', { code: 'LEVEL_ITERATOR_NOT_OPEN' })) } else if (this[kWorking]) { this.nextTick(callback, new ModuleError('Iterator is busy: cannot call all() until previous call has completed', { code: 'LEVEL_ITERATOR_BUSY' })) } else { this[kWorking] = true this[kCallback] = callback this[kAutoClose] = true if (this[kCount] >= this[kLimit]) this.nextTick(this[kHandleMany], null, []) else this._all(options, this[kHandleMany]) } return callback[kPromise] } _all (options, callback) { // Must count here because we're directly calling _nextv() let count = this[kCount] const acc = [] const nextv = () => { // Not configurable, because implementations should optimize _all(). const size = this[kLimit] < Infinity ? Math.min(1e3, this[kLimit] - count) : 1e3 if (size <= 0) { this.nextTick(callback, null, acc) } else { this._nextv(size, emptyOptions, onnextv) } } const onnextv = (err, items) => { if (err) { callback(err) } else if (items.length === 0) { callback(null, acc) } else { acc.push.apply(acc, items) count += items.length nextv() } } nextv() } [kFinishWork] () { const cb = this[kCallback] // Callback will be null if work was aborted on close if (this[kAbortOnClose] && cb === null) return noop this[kWorking] = false this[kCallback] = null if (this[kClosing]) this._close(this[kHandleClose]) return cb } [kReturnMany] (cb, err, items) { if (this[kAutoClose]) { this.close(cb.bind(null, err, items)) } else { cb(err, items) } } seek (target, options) { options = getOptions(options, emptyOptions) if (this[kClosing]) { // Don't throw here, to be kind to implementations that wrap // another db and don't necessarily control when the db is closed } else if (this[kWorking]) { throw new ModuleError('Iterator is busy: cannot call seek() until next() has completed', { code: 'LEVEL_ITERATOR_BUSY' }) } else { const keyEncoding = this.db.keyEncoding(options.keyEncoding || this[kKeyEncoding]) const keyFormat = keyEncoding.format if (options.keyEncoding !== keyFormat) { options = { ...options, keyEncoding: keyFormat } } const mapped = this.db.prefixKey(keyEncoding.encode(target), keyFormat) this._seek(mapped, options) } } _seek (target, options) { throw new ModuleError('Iterator does not support seek()', { code: 'LEVEL_NOT_SUPPORTED' }) } close (callback) { callback = fromCallback(callback, kPromise) if (this[kClosed]) { this.nextTick(callback) } else if (this[kClosing]) { this[kCloseCallbacks].push(callback) } else { this[kClosing] = true this[kCloseCallbacks].push(callback) if (!this[kWorking]) { this._close(this[kHandleClose]) } else if (this[kAbortOnClose]) { // Don't wait for work to finish. Subsequently ignore the result. const cb = this[kFinishWork]() cb(new ModuleError('Aborted on iterator close()', { code: 'LEVEL_ITERATOR_NOT_OPEN' })) } } return callback[kPromise] } _close (callback) { this.nextTick(callback) } [kHandleClose] () { this[kClosed] = true this.db.detachResource(this) const callbacks = this[kCloseCallbacks] this[kCloseCallbacks] = [] for (const cb of callbacks) { cb() } } async * [Symbol.asyncIterator] () { try { let item while ((item = (await this.next())) !== undefined) { yield item } } finally { if (!this[kClosed]) await this.close() } } } // For backwards compatibility this class is not (yet) called AbstractEntryIterator. class AbstractIterator extends CommonIterator { constructor (db, options) { super(db, options, true) this[kKeys] = options.keys !== false this[kValues] = options.values !== false } [kHandleOne] (err, key, value) { const cb = this[kFinishWork]() if (err) return cb(err) try { key = this[kKeys] && key !== undefined ? this[kKeyEncoding].decode(key) : undefined value = this[kValues] && value !== undefined ? this[kValueEncoding].decode(value) : undefined } catch (err) { return cb(new IteratorDecodeError('entry', err)) } if (!(key === undefined && value === undefined)) { this[kCount]++ } cb(null, key, value) } [kHandleMany] (err, entries) { const cb = this[kFinishWork]() if (err) return this[kReturnMany](cb, err) try { for (const entry of entries) { const key = entry[0] const value = entry[1] entry[0] = this[kKeys] && key !== undefined ? this[kKeyEncoding].decode(key) : undefined entry[1] = this[kValues] && value !== undefined ? this[kValueEncoding].decode(value) : undefined } } catch (err) { return this[kReturnMany](cb, new IteratorDecodeError('entries', err)) } this[kCount] += entries.length this[kReturnMany](cb, null, entries) } end (callback) { if (!warnedEnd && typeof console !== 'undefined') { warnedEnd = true console.warn(new ModuleError( 'The iterator.end() method was renamed to close() and end() is an alias that will be removed in a future version', { code: 'LEVEL_LEGACY' } )) } return this.close(callback) } } class AbstractKeyIterator extends CommonIterator { constructor (db, options) { super(db, options, false) } [kHandleOne] (err, key) { const cb = this[kFinishWork]() if (err) return cb(err) try { key = key !== undefined ? this[kKeyEncoding].decode(key) : undefined } catch (err) { return cb(new IteratorDecodeError('key', err)) } if (key !== undefined) this[kCount]++ cb(null, key) } [kHandleMany] (err, keys) { const cb = this[kFinishWork]() if (err) return this[kReturnMany](cb, err) try { for (let i = 0; i < keys.length; i++) { const key = keys[i] keys[i] = key !== undefined ? this[kKeyEncoding].decode(key) : undefined } } catch (err) { return this[kReturnMany](cb, new IteratorDecodeError('keys', err)) } this[kCount] += keys.length this[kReturnMany](cb, null, keys) } } class AbstractValueIterator extends CommonIterator { constructor (db, options) { super(db, options, false) } [kHandleOne] (err, value) { const cb = this[kFinishWork]() if (err) return cb(err) try { value = value !== undefined ? this[kValueEncoding].decode(value) : undefined } catch (err) { return cb(new IteratorDecodeError('value', err)) } if (value !== undefined) this[kCount]++ cb(null, value) } [kHandleMany] (err, values) { const cb = this[kFinishWork]() if (err) return this[kReturnMany](cb, err) try { for (let i = 0; i < values.length; i++) { const value = values[i] values[i] = value !== undefined ? this[kValueEncoding].decode(value) : undefined } } catch (err) { return this[kReturnMany](cb, new IteratorDecodeError('values', err)) } this[kCount] += values.length this[kReturnMany](cb, null, values) } } // Internal utility, not typed or exported class IteratorDecodeError extends ModuleError { constructor (subject, cause) { super(`Iterator could not decode ${subject}`, { code: 'LEVEL_DECODE_ERROR', cause }) } } // To help migrating to abstract-level for (const k of ['_ended property', '_nexting property', '_end method']) { Object.defineProperty(AbstractIterator.prototype, k.split(' ')[0], { get () { throw new ModuleError(`The ${k} has been removed`, { code: 'LEVEL_LEGACY' }) }, set () { throw new ModuleError(`The ${k} has been removed`, { code: 'LEVEL_LEGACY' }) } }) } // Exposed so that AbstractLevel can set these options AbstractIterator.keyEncoding = kKeyEncoding AbstractIterator.valueEncoding = kValueEncoding exports.AbstractIterator = AbstractIterator exports.AbstractKeyIterator = AbstractKeyIterator exports.AbstractValueIterator = AbstractValueIterator /***/ }), /***/ "./node_modules/abstract-level/abstract-level.js": /*!*******************************************************!*\ !*** ./node_modules/abstract-level/abstract-level.js ***! \*******************************************************/ /***/ ((__unused_webpack_module, exports, __webpack_require__) => { "use strict"; const { supports } = __webpack_require__(/*! level-supports */ "./node_modules/level-supports/index.js") const { Transcoder } = __webpack_require__(/*! level-transcoder */ "./node_modules/level-transcoder/index.js") const { EventEmitter } = __webpack_require__(/*! events */ "./node_modules/events/events.js") const { fromCallback } = __webpack_require__(/*! catering */ "./node_modules/catering/index.js") const ModuleError = __webpack_require__(/*! module-error */ "./node_modules/module-error/index.js") const { AbstractIterator } = __webpack_require__(/*! ./abstract-iterator */ "./node_modules/abstract-level/abstract-iterator.js") const { DefaultKeyIterator, DefaultValueIterator } = __webpack_require__(/*! ./lib/default-kv-iterator */ "./node_modules/abstract-level/lib/default-kv-iterator.js") const { DeferredIterator, DeferredKeyIterator, DeferredValueIterator } = __webpack_require__(/*! ./lib/deferred-iterator */ "./node_modules/abstract-level/lib/deferred-iterator.js") const { DefaultChainedBatch } = __webpack_require__(/*! ./lib/default-chained-batch */ "./node_modules/abstract-level/lib/default-chained-batch.js") const { getCallback, getOptions } = __webpack_require__(/*! ./lib/common */ "./node_modules/abstract-level/lib/common.js") const rangeOptions = __webpack_require__(/*! ./lib/range-options */ "./node_modules/abstract-level/lib/range-options.js") const kPromise = Symbol('promise') const kLanded = Symbol('landed') const kResources = Symbol('resources') const kCloseResources = Symbol('closeResources') const kOperations = Symbol('operations') const kUndefer = Symbol('undefer') const kDeferOpen = Symbol('deferOpen') const kOptions = Symbol('options') const kStatus = Symbol('status') const kDefaultOptions = Symbol('defaultOptions') const kTranscoder = Symbol('transcoder') const kKeyEncoding = Symbol('keyEncoding') const kValueEncoding = Symbol('valueEncoding') const noop = () => {} class AbstractLevel extends EventEmitter { constructor (manifest, options) { super() if (typeof manifest !== 'object' || manifest === null) { throw new TypeError("The first argument 'manifest' must be an object") } options = getOptions(options) const { keyEncoding, valueEncoding, passive, ...forward } = options this[kResources] = new Set() this[kOperations] = [] this[kDeferOpen] = true this[kOptions] = forward this[kStatus] = 'opening' this.supports = supports(manifest, { status: true, promises: true, clear: true, getMany: true, deferredOpen: true, // TODO (next major): add seek snapshots: manifest.snapshots !== false, permanence: manifest.permanence !== false, // TODO: remove from level-supports because it's always supported keyIterator: true, valueIterator: true, iteratorNextv: true, iteratorAll: true, encodings: manifest.encodings || {}, events: Object.assign({}, manifest.events, { opening: true, open: true, closing: true, closed: true, put: true, del: true, batch: true, clear: true }) }) this[kTranscoder] = new Transcoder(formats(this)) this[kKeyEncoding] = this[kTranscoder].encoding(keyEncoding || 'utf8') this[kValueEncoding] = this[kTranscoder].encoding(valueEncoding || 'utf8') // Add custom and transcoder encodings to manifest for (const encoding of this[kTranscoder].encodings()) { if (!this.supports.encodings[encoding.commonName]) { this.supports.encodings[encoding.commonName] = true } } this[kDefaultOptions] = { empty: Object.freeze({}), entry: Object.freeze({ keyEncoding: this[kKeyEncoding].commonName, valueEncoding: this[kValueEncoding].commonName }), key: Object.freeze({ keyEncoding: this[kKeyEncoding].commonName }) } // Let subclass finish its constructor this.nextTick(() => { if (this[kDeferOpen]) { this.open({ passive: false }, noop) } }) } get status () { return this[kStatus] } keyEncoding (encoding) { return this[kTranscoder].encoding(encoding != null ? encoding : this[kKeyEncoding]) } valueEncoding (encoding) { return this[kTranscoder].encoding(encoding != null ? encoding : this[kValueEncoding]) } open (options, callback) { callback = getCallback(options, callback) callback = fromCallback(callback, kPromise) options = { ...this[kOptions], ...getOptions(options) } options.createIfMissing = options.createIfMissing !== false options.errorIfExists = !!options.errorIfExists const maybeOpened = (err) => { if (this[kStatus] === 'closing' || this[kStatus] === 'opening') { // Wait until pending state changes are done this.once(kLanded, err ? () => maybeOpened(err) : maybeOpened) } else if (this[kStatus] !== 'open') { callback(new ModuleError('Database is not open', { code: 'LEVEL_DATABASE_NOT_OPEN', cause: err })) } else { callback() } } if (options.passive) { if (this[kStatus] === 'opening') { this.once(kLanded, maybeOpened) } else { this.nextTick(maybeOpened) } } else if (this[kStatus] === 'closed' || this[kDeferOpen]) { this[kDeferOpen] = false this[kStatus] = 'opening' this.emit('opening') this._open(options, (err) => { if (err) { this[kStatus] = 'closed' // Resources must be safe to close in any db state this[kCloseResources](() => { this.emit(kLanded) maybeOpened(err) }) this[kUndefer]() return } this[kStatus] = 'open' this[kUndefer]() this.emit(kLanded) // Only emit public event if pending state changes are done if (this[kStatus] === 'open') this.emit('open') // TODO (next major): remove this alias if (this[kStatus] === 'open') this.emit('ready') maybeOpened() }) } else if (this[kStatus] === 'open') { this.nextTick(maybeOpened) } else { this.once(kLanded, () => this.open(options, callback)) } return callback[kPromise] } _open (options, callback) { this.nextTick(callback) } close (callback) { callback = fromCallback(callback, kPromise) const maybeClosed = (err) => { if (this[kStatus] === 'opening' || this[kStatus] === 'closing') { // Wait until pending state changes are done this.once(kLanded, err ? maybeClosed(err) : maybeClosed) } else if (this[kStatus] !== 'closed') { callback(new ModuleError('Database is not closed', { code: 'LEVEL_DATABASE_NOT_CLOSED', cause: err })) } else { callback() } } if (this[kStatus] === 'open') { this[kStatus] = 'closing' this.emit('closing') const cancel = (err) => { this[kStatus] = 'open' this[kUndefer]() this.emit(kLanded) maybeClosed(err) } this[kCloseResources](() => { this._close((err) => { if (err) return cancel(err) this[kStatus] = 'closed' this[kUndefer]() this.emit(kLanded) // Only emit public event if pending state changes are done if (this[kStatus] === 'closed') this.emit('closed') maybeClosed() }) }) } else if (this[kStatus] === 'closed') { this.nextTick(maybeClosed) } else { this.once(kLanded, () => this.close(callback)) } return callback[kPromise] } [kCloseResources] (callback) { if (this[kResources].size === 0) { return this.nextTick(callback) } let pending = this[kResources].size let sync = true const next = () => { if (--pending === 0) { // We don't have tests for generic resources, so dezalgo if (sync) this.nextTick(callback) else callback() } } // In parallel so that all resources know they are closed for (const resource of this[kResources]) { resource.close(next) } sync = false this[kResources].clear() } _close (callback) { this.nextTick(callback) } get (key, options, callback) { callback = getCallback(options, callback) callback = fromCallback(callback, kPromise) options = getOptions(options, this[kDefaultOptions].entry) if (this[kStatus] === 'opening') { this.defer(() => this.get(key, options, callback)) return callback[kPromise] } if (maybeError(this, callback)) { return callback[kPromise] } const err = this._checkKey(key) if (err) { this.nextTick(callback, err) return callback[kPromise] } const keyEncoding = this.keyEncoding(options.keyEncoding) const valueEncoding = this.valueEncoding(options.valueEncoding) const keyFormat = keyEncoding.format const valueFormat = valueEncoding.format // Forward encoding options to the underlying store if (options.keyEncoding !== keyFormat || options.valueEncoding !== valueFormat) { // Avoid spread operator because of https://bugs.chromium.org/p/chromium/issues/detail?id=1204540 options = Object.assign({}, options, { keyEncoding: keyFormat, valueEncoding: valueFormat }) } this._get(this.prefixKey(keyEncoding.encode(key), keyFormat), options, (err, value) => { if (err) { // Normalize not found error for backwards compatibility with abstract-leveldown and level(up) if (err.code === 'LEVEL_NOT_FOUND' || err.notFound || /NotFound/i.test(err)) { if (!err.code) err.code = 'LEVEL_NOT_FOUND' // Preferred way going forward if (!err.notFound) err.notFound = true // Same as level-errors if (!err.status) err.status = 404 // Same as level-errors } return callback(err) } try { value = valueEncoding.decode(value) } catch (err) { return callback(new ModuleError('Could not decode value', { code: 'LEVEL_DECODE_ERROR', cause: err })) } callback(null, value) }) return callback[kPromise] } _get (key, options, callback) { this.nextTick(callback, new Error('NotFound')) } getMany (keys, options, callback) { callback = getCallback(options, callback) callback = fromCallback(callback, kPromise) options = getOptions(options, this[kDefaultOptions].entry) if (this[kStatus] === 'opening') { this.defer(() => this.getMany(keys, options, callback)) return callback[kPromise] } if (maybeError(this, callback)) { return callback[kPromise] } if (!Array.isArray(keys)) { this.nextTick(callback, new TypeError("The first argument 'keys' must be an array")) return callback[kPromise] } if (keys.length === 0) { this.nextTick(callback, null, []) return callback[kPromise] } const keyEncoding = this.keyEncoding(options.keyEncoding) const valueEncoding = this.valueEncoding(options.valueEncoding) const keyFormat = keyEncoding.format const valueFormat = valueEncoding.format // Forward encoding options if (options.keyEncoding !== keyFormat || options.valueEncoding !== valueFormat) { options = Object.assign({}, options, { keyEncoding: keyFormat, valueEncoding: valueFormat }) } const mappedKeys = new Array(keys.length) for (let i = 0; i < keys.length; i++) { const key = keys[i] const err = this._checkKey(key) if (err) { this.nextTick(callback, err) return callback[kPromise] } mappedKeys[i] = this.prefixKey(keyEncoding.encode(key), keyFormat) } this._getMany(mappedKeys, options, (err, values) => { if (err) return callback(err) try { for (let i = 0; i < values.length; i++) { if (values[i] !== undefined) { values[i] = valueEncoding.decode(values[i]) } } } catch (err) { return callback(new ModuleError(`Could not decode one or more of ${values.length} value(s)`, { code: 'LEVEL_DECODE_ERROR', cause: err })) } callback(null, values) }) return callback[kPromise] } _getMany (keys, options, callback) { this.nextTick(callback, null, new Array(keys.length).fill(undefined)) } put (key, value, options, callback) { callback = getCallback(options, callback) callback = fromCallback(callback, kPromise) options = getOptions(options, this[kDefaultOptions].entry) if (this[kStatus] === 'opening') { this.defer(() => this.put(key, value, options, callback)) return callback[kPromise] } if (maybeError(this, callback)) { return callback[kPromise] } const err = this._checkKey(key) || this._checkValue(value) if (err) { this.nextTick(callback, err) return callback[kPromise] } const keyEncoding = this.keyEncoding(options.keyEncoding) const valueEncoding = this.valueEncoding(options.valueEncoding) const keyFormat = keyEncoding.format const valueFormat = valueEncoding.format // Forward encoding options if (options.keyEncoding !== keyFormat || options.valueEncoding !== valueFormat) { options = Object.assign({}, options, { keyEncoding: keyFormat, valueEncoding: valueFormat }) } const mappedKey = this.prefixKey(keyEncoding.encode(key), keyFormat) const mappedValue = valueEncoding.encode(value) this._put(mappedKey, mappedValue, options, (err) => { if (err) return callback(err) this.emit('put', key, value) callback() }) return callback[kPromise] } _put (key, value, options, callback) { this.nextTick(callback) } del (key, options, callback) { callback = getCallback(options, callback) callback = fromCallback(callback, kPromise) options = getOptions(options, this[kDefaultOptions].key) if (this[kStatus] === 'opening') { this.defer(() => this.del(key, options, callback)) return callback[kPromise] } if (maybeError(this, callback)) { return callback[kPromise] } const err = this._checkKey(key) if (err) { this.nextTick(callback, err) return callback[kPromise] } const keyEncoding = this.keyEncoding(options.keyEncoding) const keyFormat = keyEncoding.format // Forward encoding options if (options.keyEncoding !== keyFormat) { options = Object.assign({}, options, { keyEncoding: keyFormat }) } this._del(this.prefixKey(keyEncoding.encode(key), keyFormat), options, (err) => { if (err) return callback(err) this.emit('del', key) callback() }) return callback[kPromise] } _del (key, options, callback) { this.nextTick(callback) } batch (operations, options, callback) { if (!arguments.length) { if (this[kStatus] === 'opening') return new DefaultChainedBatch(this) if (this[kStatus] !== 'open') { throw new ModuleError('Database is not open', { code: 'LEVEL_DATABASE_NOT_OPEN' }) } return this._chainedBatch() } if (typeof operations === 'function') callback = operations else callback = getCallback(options, callback) callback = fromCallback(callback, kPromise) options = getOptions(options, this[kDefaultOptions].empty) if (this[kStatus] === 'opening') { this.defer(() => this.batch(operations, options, callback)) return callback[kPromise] } if (maybeError(this, callback)) { return callback[kPromise] } if (!Array.isArray(operations)) { this.nextTick(callback, new TypeError("The first argument 'operations' must be an array")) return callback[kPromise] } if (operations.length === 0) { this.nextTick(callback) return callback[kPromise] } const mapped = new Array(operations.length) const { keyEncoding: ke, valueEncoding: ve, ...forward } = options for (let i = 0; i < operations.length; i++) { if (typeof operations[i] !== 'object' || operations[i] === null) { this.nextTick(callback, new TypeError('A batch operation must be an object')) return callback[kPromise] } const op = Object.assign({}, operations[i]) if (op.type !== 'put' && op.type !== 'del') { this.nextTick(callback, new TypeError("A batch operation must have a type property that is 'put' or 'del'")) return callback[kPromise] } const err = this._checkKey(op.key) if (err) { this.nextTick(callback, err) return callback[kPromise] } const db = op.sublevel != null ? op.sublevel : this const keyEncoding = db.keyEncoding(op.keyEncoding || ke) const keyFormat = keyEncoding.format op.key = db.prefixKey(keyEncoding.encode(op.key), keyFormat) op.keyEncoding = keyFormat if (op.type === 'put') { const valueErr = this._checkValue(op.value) if (valueErr) { this.nextTick(callback, valueErr) return callback[kPromise] } const valueEncoding = db.valueEncoding(op.valueEncoding || ve) op.value = valueEncoding.encode(op.value) op.valueEncoding = valueEncoding.format } // Prevent double prefixing if (db !== this) { op.sublevel = null } mapped[i] = op } this._batch(mapped, forward, (err) => { if (err) return callback(err) this.emit('batch', operations) callback() }) return callback[kPromise] } _batch (operations, options, callback) { this.nextTick(callback) } sublevel (name, options) { return this._sublevel(name, AbstractSublevel.defaults(options)) } _sublevel (name, options) { return new AbstractSublevel(this, name, options) } prefixKey (key, keyFormat) { return key } clear (options, callback) { callback = getCallback(options, callback) callback = fromCallback(callback, kPromise) options = getOptions(options, this[kDefaultOptions].empty) if (this[kStatus] === 'opening') { this.defer(() => this.clear(options, callback)) return callback[kPromise] } if (maybeError(this, callback)) { return callback[kPromise] } const original = options const keyEncoding = this.keyEncoding(options.keyEncoding) options = rangeOptions(options, keyEncoding) options.keyEncoding = keyEncoding.format if (options.limit === 0) { this.nextTick(callback) } else { this._clear(options, (err) => { if (err) return callback(err) this.emit('clear', original) callback() }) } return callback[kPromise] } _clear (options, callback) { this.nextTick(callback) } iterator (options) { const keyEncoding = this.keyEncoding(options && options.keyEncoding) const valueEncoding = this.valueEncoding(options && options.valueEncoding) options = rangeOptions(options, keyEncoding) options.keys = options.keys !== false options.values = options.values !== false // We need the original encoding options in AbstractIterator in order to decode data options[AbstractIterator.keyEncoding] = keyEncoding options[AbstractIterator.valueEncoding] = valueEncoding // Forward encoding options to private API options.keyEncoding = keyEncoding.format options.valueEncoding = valueEncoding.format if (this[kStatus] === 'opening') { return new DeferredIterator(this, options) } else if (this[kStatus] !== 'open') { throw new ModuleError('Database is not open', { code: 'LEVEL_DATABASE_NOT_OPEN' }) } return this._iterator(options) } _iterator (options) { return new AbstractIterator(this, options) } keys (options) { // Also include valueEncoding (though unused) because we may fallback to _iterator() const keyEncoding = this.keyEncoding(options && options.keyEncoding) const valueEncoding = this.valueEncoding(options && options.valueEncoding) options = rangeOptions(options, keyEncoding) // We need the original encoding options in AbstractKeyIterator in order to decode data options[AbstractIterator.keyEncoding] = keyEncoding options[AbstractIterator.valueEncoding] = valueEncoding // Forward encoding options to private API options.keyEncoding = keyEncoding.format options.valueEncoding = valueEncoding.format if (this[kStatus] === 'opening') { return new DeferredKeyIterator(this, options) } else if (this[kStatus] !== 'open') { throw new ModuleError('Database is not open', { code: 'LEVEL_DATABASE_NOT_OPEN' }) } return this._keys(options) } _keys (options) { return new DefaultKeyIterator(this, options) } values (options) { const keyEncoding = this.keyEncoding(options && options.keyEncoding) const valueEncoding = this.valueEncoding(options && options.valueEncoding) options = rangeOptions(options, keyEncoding) // We need the original encoding options in AbstractValueIterator in order to decode data options[AbstractIterator.keyEncoding] = keyEncoding options[AbstractIterator.valueEncoding] = valueEncoding // Forward encoding options to private API options.keyEncoding = keyEncoding.format options.valueEncoding = valueEncoding.format if (this[kStatus] === 'opening') { return new DeferredValueIterator(this, options) } else if (this[kStatus] !== 'open') { throw new ModuleError('Database is not open', { code: 'LEVEL_DATABASE_NOT_OPEN' }) } return this._values(options) } _values (options) { return new DefaultValueIterator(this, options) } defer (fn) { if (typeof fn !== 'function') { throw new TypeError('The first argument must be a function') } this[kOperations].push(fn) } [kUndefer] () { if (this[kOperations].length === 0) { return } const operations = this[kOperations] this[kOperations] = [] for (const op of operations) { op() } } // TODO: docs and types attachResource (resource) { if (typeof resource !== 'object' || resource === null || typeof resource.close !== 'function') { throw new TypeError('The first argument must be a resource object') } this[kResources].add(resource) } // TODO: docs and types detachResource (resource) { this[kResources].delete(resource) } _chainedBatch () { return new DefaultChainedBatch(this) } _checkKey (key) { if (key === null || key === undefined) { return new ModuleError('Key cannot be null or undefined', { code: 'LEVEL_INVALID_KEY' }) } } _checkValue (value) { if (value === null || value === undefined) { return new ModuleError('Value cannot be null or undefined', { code: 'LEVEL_INVALID_VALUE' }) } } } // Expose browser-compatible nextTick for dependents // TODO: after we drop node 10, also use queueMicrotask in node AbstractLevel.prototype.nextTick = __webpack_require__(/*! ./lib/next-tick */ "./node_modules/abstract-level/lib/next-tick-browser.js") const { AbstractSublevel } = __webpack_require__(/*! ./lib/abstract-sublevel */ "./node_modules/abstract-level/lib/abstract-sublevel.js")({ AbstractLevel }) exports.AbstractLevel = AbstractLevel exports.AbstractSublevel = AbstractSublevel const maybeError = function (db, callback) { if (db[kStatus] !== 'open') { db.nextTick(callback, new ModuleError('Database is not open', { code: 'LEVEL_DATABASE_NOT_OPEN' })) return true } return false } const formats = function (db) { return Object.keys(db.supports.encodings) .filter(k => !!db.supports.encodings[k]) } /***/ }), /***/ "./node_modules/abstract-level/index.js": /*!**********************************************!*\ !*** ./node_modules/abstract-level/index.js ***! \**********************************************/ /***/ ((__unused_webpack_module, exports, __webpack_require__) => { "use strict"; exports.AbstractLevel = __webpack_require__(/*! ./abstract-level */ "./node_modules/abstract-level/abstract-level.js").AbstractLevel exports.AbstractSublevel = __webpack_require__(/*! ./abstract-level */ "./node_modules/abstract-level/abstract-level.js").AbstractSublevel exports.AbstractIterator = __webpack_require__(/*! ./abstract-iterator */ "./node_modules/abstract-level/abstract-iterator.js").AbstractIterator exports.AbstractKeyIterator = __webpack_require__(/*! ./abstract-iterator */ "./node_modules/abstract-level/abstract-iterator.js").AbstractKeyIterator exports.AbstractValueIterator = __webpack_require__(/*! ./abstract-iterator */ "./node_modules/abstract-level/abstract-iterator.js").AbstractValueIterator exports.AbstractChainedBatch = __webpack_require__(/*! ./abstract-chained-batch */ "./node_modules/abstract-level/abstract-chained-batch.js").AbstractChainedBatch /***/ }), /***/ "./node_modules/abstract-level/lib/abstract-sublevel-iterator.js": /*!***********************************************************************!*\ !*** ./node_modules/abstract-level/lib/abstract-sublevel-iterator.js ***! \***********************************************************************/ /***/ ((__unused_webpack_module, exports, __webpack_require__) => { "use strict"; const { AbstractIterator, AbstractKeyIterator, AbstractValueIterator } = __webpack_require__(/*! ../abstract-iterator */ "./node_modules/abstract-level/abstract-iterator.js") const kUnfix = Symbol('unfix') const kIterator = Symbol('iterator') const kHandleOne = Symbol('handleOne') const kHandleMany = Symbol('handleMany') const kCallback = Symbol('callback') // TODO: unfix natively if db supports it class AbstractSublevelIterator extends AbstractIterator { constructor (db, options, iterator, unfix) { super(db, options) this[kIterator] = iterator this[kUnfix] = unfix this[kHandleOne] = this[kHandleOne].bind(this) this[kHandleMany] = this[kHandleMany].bind(this) this[kCallback] = null } [kHandleOne] (err, key, value) { const callback = this[kCallback] if (err) return callback(err) if (key !== undefined) key = this[kUnfix](key) callback(err, key, value) } [kHandleMany] (err, entries) { const callback = this[kCallback] if (err) return callback(err) for (const entry of entries) { const key = entry[0] if (key !== undefined) entry[0] = this[kUnfix](key) } callback(err, entries) } } class AbstractSublevelKeyIterator extends AbstractKeyIterator { constructor (db, options, iterator, unfix) { super(db, options) this[kIterator] = iterator this[kUnfix] = unfix this[kHandleOne] = this[kHandleOne].bind(this) this[kHandleMany] = this[kHandleMany].bind(this) this[kCallback] = null } [kHandleOne] (err, key) { const callback = this[kCallback] if (err) return callback(err) if (key !== undefined) key = this[kUnfix](key) callback(err, key) } [kHandleMany] (err, keys) { const callback = this[kCallback] if (err) return callback(err) for (let i = 0; i < keys.length; i++) { const key = keys[i] if (key !== undefined) keys[i] = this[kUnfix](key) } callback(err, keys) } } class AbstractSublevelValueIterator extends AbstractValueIterator { constructor (db, options, iterator) { super(db, options) this[kIterator] = iterator } } for (const Iterator of [AbstractSublevelIterator, AbstractSublevelKeyIterator]) { Iterator.prototype._next = function (callback) { this[kCallback] = callback this[kIterator].next(this[kHandleOne]) } Iterator.prototype._nextv = function (size, options, callback) { this[kCallback] = callback this[kIterator].nextv(size, options, this[kHandleMany]) } Iterator.prototype._all = function (options, callback) { this[kCallback] = callback this[kIterator].all(options, this[kHandleMany]) } } for (const Iterator of [AbstractSublevelValueIterator]) { Iterator.prototype._next = function (callback) { this[kIterator].next(callback) } Iterator.prototype._nextv = function (size, options, callback) { this[kIterator].nextv(size, options, callback) } Iterator.prototype._all = function (options, callback) { this[kIterator].all(options, callback) } } for (const Iterator of [AbstractSublevelIterator, AbstractSublevelKeyIterator, AbstractSublevelValueIterator]) { Iterator.prototype._seek = function (target, options) { this[kIterator].seek(target, options) } Iterator.prototype._close = function (callback) { this[kIterator].close(callback) } } exports.AbstractSublevelIterator = AbstractSublevelIterator exports.AbstractSublevelKeyIterator = AbstractSublevelKeyIterator exports.AbstractSublevelValueIterator = AbstractSublevelValueIterator /***/ }), /***/ "./node_modules/abstract-level/lib/abstract-sublevel.js": /*!**************************************************************!*\ !*** ./node_modules/abstract-level/lib/abstract-sublevel.js ***! \**************************************************************/ /***/ ((module, __unused_webpack_exports, __webpack_require__) => { "use strict"; const ModuleError = __webpack_require__(/*! module-error */ "./node_modules/module-error/index.js") const { Buffer } = __webpack_require__(/*! buffer */ "