Initial
This commit is contained in:
818
resources/app/node_modules/abstract-level/abstract-level.js
generated
vendored
Normal file
818
resources/app/node_modules/abstract-level/abstract-level.js
generated
vendored
Normal file
@@ -0,0 +1,818 @@
|
||||
'use strict'
|
||||
|
||||
const { supports } = require('level-supports')
|
||||
const { Transcoder } = require('level-transcoder')
|
||||
const { EventEmitter } = require('events')
|
||||
const { fromCallback } = require('catering')
|
||||
const ModuleError = require('module-error')
|
||||
const { AbstractIterator } = require('./abstract-iterator')
|
||||
const { DefaultKeyIterator, DefaultValueIterator } = require('./lib/default-kv-iterator')
|
||||
const { DeferredIterator, DeferredKeyIterator, DeferredValueIterator } = require('./lib/deferred-iterator')
|
||||
const { DefaultChainedBatch } = require('./lib/default-chained-batch')
|
||||
const { getCallback, getOptions } = require('./lib/common')
|
||||
const rangeOptions = require('./lib/range-options')
|
||||
|
||||
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 = require('./lib/next-tick')
|
||||
|
||||
const { AbstractSublevel } = require('./lib/abstract-sublevel')({ 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])
|
||||
}
|
||||
Reference in New Issue
Block a user