@orbitdb/core
Version:
Distributed p2p database on IPFS
1,691 lines (1,340 loc) • 1.29 MB
JavaScript
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 */ "