Initial
This commit is contained in:
21
resources/app/node_modules/abstract-level/LICENSE
generated
vendored
Normal file
21
resources/app/node_modules/abstract-level/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright © 2013 Rod Vagg and the contributors to abstract-level.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
479
resources/app/node_modules/abstract-level/UPGRADING.md
generated
vendored
Normal file
479
resources/app/node_modules/abstract-level/UPGRADING.md
generated
vendored
Normal file
@@ -0,0 +1,479 @@
|
||||
# Upgrade Guide
|
||||
|
||||
This document describes breaking changes and how to upgrade. For a complete list of changes including minor and patch releases, please refer to the [changelog](CHANGELOG.md).
|
||||
|
||||
## Table of Contents
|
||||
|
||||
<details><summary>Click to expand</summary>
|
||||
|
||||
- [1.0.0](#100)
|
||||
- [1. API parity with `levelup`](#1-api-parity-with-levelup)
|
||||
- [1.1. New: promises](#11-new-promises)
|
||||
- [1.2. New: events](#12-new-events)
|
||||
- [1.3. New: idempotent open](#13-new-idempotent-open)
|
||||
- [1.4. New: deferred open](#14-new-deferred-open)
|
||||
- [1.5. No constructor callback](#15-no-constructor-callback)
|
||||
- [1.6. New: state checks](#16-new-state-checks)
|
||||
- [1.7. New: chained batch length](#17-new-chained-batch-length)
|
||||
- [2. API parity with `level`](#2-api-parity-with-level)
|
||||
- [2.1. For consumers](#21-for-consumers)
|
||||
- [2.2. For implementors](#22-for-implementors)
|
||||
- [2.3. Other notable changes](#23-other-notable-changes)
|
||||
- [3. Streams have moved](#3-streams-have-moved)
|
||||
- [4. Zero-length keys and range options are now valid](#4-zero-length-keys-and-range-options-are-now-valid)
|
||||
- [5. Resources are auto-closed](#5-resources-are-auto-closed)
|
||||
- [5.1. Closing iterators is idempotent](#51-closing-iterators-is-idempotent)
|
||||
- [5.2. Chained batch can be closed](#52-chained-batch-can-be-closed)
|
||||
- [6. Errors now use codes](#6-errors-now-use-codes)
|
||||
- [7. Semi-private properties have been removed](#7-semi-private-properties-have-been-removed)
|
||||
- [8. Changes to test suite](#8-changes-to-test-suite)
|
||||
- [9. Sublevels are builtin](#9-sublevels-are-builtin)
|
||||
|
||||
</details>
|
||||
|
||||
## 1.0.0
|
||||
|
||||
**Introducing `abstract-level`: a fork of [`abstract-leveldown`](https://github.com/Level/abstract-leveldown) that removes the need for [`levelup`](https://github.com/Level/levelup), [`encoding-down`](https://github.com/Level/encoding-down) and more. An `abstract-level` database is a complete solution that doesn't need to be wrapped. It has the same API as `level(up)` including encodings, promises and events. In addition, implementations can now choose to use Uint8Array instead of Buffer. Consumers of an implementation can use both. Sublevels are builtin.**
|
||||
|
||||
We've put together several upgrade guides for different modules. See the [FAQ](https://github.com/Level/community#faq) to find the best upgrade guide for you. This upgrade guide describes how to replace `abstract-leveldown` with `abstract-level`. Implementations that do so, can no longer be wrapped with `levelup`.
|
||||
|
||||
The npm package name is `abstract-level` and the main export is called `AbstractLevel` rather than `AbstractLevelDOWN`. It started using classes. Support of Node.js 10 has been dropped.
|
||||
|
||||
For most folks, a database that upgraded from `abstract-leveldown` to `abstract-level` can be a drop-in replacement for a `level(up)` database (with the exception of stream methods). Let's start this guide there: all methods have been enhanced to reach API parity with `levelup` and `level`.
|
||||
|
||||
### 1. API parity with `levelup`
|
||||
|
||||
#### 1.1. New: promises
|
||||
|
||||
Methods that take a callback now also support promises. They return a promise if no callback is provided, the same as `levelup`. Implementations that override public (non-underscored) methods _must_ do the same and any implementation _should_ do the same for additional methods if any.
|
||||
|
||||
#### 1.2. New: events
|
||||
|
||||
An `abstract-level` database emits the same events as `levelup` would.
|
||||
|
||||
#### 1.3. New: idempotent open
|
||||
|
||||
Opening and closing a database is idempotent and safe, similar to `levelup` but more precise. If `open()` and `close()` are called repeatedly, the last call dictates the final status. Callbacks are not called (or promises not resolved) until any pending state changes are done. Same for events. Unlike on `levelup` it is safe to call `open()` while status is `'closing'`: the database will wait for closing to complete and then reopen. None of these changes are likely to constitute a breaking change; they increase state consistency in edge cases.
|
||||
|
||||
The `open()` method has a new option called `passive`. If set to `true` the call will wait for, but not initiate, opening of the database. To similar effect as `db.once('open', callback)` with added benefit that it also works if the database is already open. Implementations that wrap another database can use the `passive` option to open themselves without taking full control of the database that they wrap.
|
||||
|
||||
#### 1.4. New: deferred open
|
||||
|
||||
Deferred open is built-in. This means a database opens itself a tick after its constructor returns (unless `open()` was called manually). Any operations made until opening has completed are queued up in memory. When opening completes the operations are replayed. If opening failed (and this is a new behavior compared to `levelup`) the operations will yield errors. The `AbstractLevel` class has a new `defer()` method for an implementation to defer custom operations.
|
||||
|
||||
The initial `status` of a database is `'opening'` rather than `'new'`, which no longer exists. Wrapping a database with [`deferred-leveldown`](https://github.com/Level/deferred-leveldown) is not supported and will exhibit undefined behavior.
|
||||
|
||||
Implementations must also accept options for `open()` in their constructor, which was previously done by `levelup`. For example, usage of the [`classic-level`](https://github.com/Level/classic-level) implementation is as follows:
|
||||
|
||||
```js
|
||||
const db = new ClassicLevel('./db', {
|
||||
createIfMissing: false,
|
||||
compression: false
|
||||
})
|
||||
```
|
||||
|
||||
This works by first forwarding options to the `AbstractLevel` constructor, which in turn forwards them to `open(options)`. If `open(options)` is called manually those options will be shallowly merged with options from the constructor:
|
||||
|
||||
```js
|
||||
// Results in { createIfMissing: false, compression: true }
|
||||
await db.open({ compression: true })
|
||||
```
|
||||
|
||||
A database is not "patch-safe". If some form of plugin monkey-patches a database like in the following example, it must now also take the responsibility of deferring the operation (as well as handling promises and callbacks) using `db.defer()`. I.e. this example is incomplete:
|
||||
|
||||
```js
|
||||
function plugin (db) {
|
||||
const original = db.get
|
||||
|
||||
db.get = function (...args) {
|
||||
original.call(this, ...args)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 1.5. No constructor callback
|
||||
|
||||
The database constructor does not take a callback argument, unlike `levelup`. This goes for `abstract-level` as well as implementations - which is to say, implementors don't have to (and should not) support this old pattern.
|
||||
|
||||
Instead call `db.open()` if you wish to wait for opening (which is not necessary to use the database) or to capture an error. If that's your reason for using the callback and you previously initialized a database like so (simplified):
|
||||
|
||||
```js
|
||||
levelup(function (err, db) {
|
||||
// ..
|
||||
})
|
||||
```
|
||||
|
||||
You must now do:
|
||||
|
||||
```js
|
||||
db.open(function (err) {
|
||||
// ..
|
||||
})
|
||||
```
|
||||
|
||||
Or using promises:
|
||||
|
||||
```js
|
||||
await db.open()
|
||||
```
|
||||
|
||||
#### 1.6. New: state checks
|
||||
|
||||
On any operation, an `abstract-level` database checks if it's open. If not, it will either throw an error (if the relevant API is synchronous) or asynchronously yield an error. For example:
|
||||
|
||||
```js
|
||||
await db.close()
|
||||
|
||||
try {
|
||||
db.iterator()
|
||||
} catch (err) {
|
||||
console.log(err.code) // LEVEL_DATABASE_NOT_OPEN
|
||||
}
|
||||
```
|
||||
|
||||
_Errors now have a `code` property. More on that below\._
|
||||
|
||||
This may be a breaking change downstream because it changes error messages for implementations that had their own safety checks (which will now be ineffective because `abstract-level` checks are performed first) or implicitly relied on `levelup` checks. By safety we mean mainly that yielding a JavaScript error is preferred over segmentation faults, though non-native implementations also benefit from detecting incorrect usage.
|
||||
|
||||
Implementations that have additional methods should add or align their own safety checks for consistency. Like so:
|
||||
|
||||
<details>
|
||||
<summary>Click to expand</summary>
|
||||
|
||||
```js
|
||||
const ModuleError = require('module-error')
|
||||
|
||||
class ExampleLevel extends AbstractLevel {
|
||||
// For brevity this example does not implement promises or encodings
|
||||
approximateSize (start, end, callback) {
|
||||
if (this.status === 'opening') {
|
||||
this.defer(() => this.approximateSize(start, end, callback))
|
||||
} else if (this.status !== 'open') {
|
||||
this.nextTick(callback, new ModuleError('Database is not open', {
|
||||
code: 'LEVEL_DATABASE_NOT_OPEN'
|
||||
}))
|
||||
} else {
|
||||
// ..
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
#### 1.7. New: chained batch length
|
||||
|
||||
The `AbstractChainedBatch` prototype has a new `length` property that, like a chained batch in `levelup`, returns the number of queued operations in the batch. Implementations should not have to make changes for this unless they monkey-patched public methods of `AbstractChainedBatch`.
|
||||
|
||||
### 2. API parity with `level`
|
||||
|
||||
It was previously necessary to use [`level`](https://github.com/Level/level) to get the "full experience". Or similar modules like [`level-mem`](https://github.com/Level/mem), [`level-rocksdb`](https://github.com/Level/level-rocksdb) and more. These modules combined an `abstract-leveldown` implementation with [`encoding-down`](https://github.com/Level/encoding-down) and [`levelup`](https://github.com/Level/levelup). Encodings are now built-in to `abstract-level`, using [`level-transcoder`](https://github.com/Level/transcoder) rather than [`level-codec`](https://github.com/Level/codec). The main change is that logic from the existing public API has been expanded down into the storage layer.
|
||||
|
||||
The `level` module still has a place, for its support of both Node.js and browsers and for being the main entrypoint into the Level ecosystem. The next major version of `level`, that's v8.0.0, will likely simply export [`classic-level`](https://github.com/Level/classic-level) in Node.js and [`browser-level`](https://github.com/Level/browser-level) in browsers. To differentiate, the text below will refer to the old version as `level@7`.
|
||||
|
||||
#### 2.1. For consumers
|
||||
|
||||
All relevant methods including the database constructor now accept `keyEncoding` and `valueEncoding` options, the same as `level@7`. Read operations now yield strings rather than buffers by default, having the same default `'utf8'` encoding as `level@7` and friends.
|
||||
|
||||
There are a few differences from `level@7` and `encoding-down`. Some breaking:
|
||||
|
||||
- The lesser-used `'ascii'`, `'ucs2'` and `'utf16le'` encodings are not supported
|
||||
- The `'id'` encoding, which was not supported by any active `abstract-leveldown` implementation and aliased as `'none'`, has been removed
|
||||
- The undocumented `encoding` option (as an alias for `valueEncoding`) is not supported.
|
||||
|
||||
And some non-breaking:
|
||||
|
||||
- The `'binary'` encoding has been renamed to `'buffer'`, with `'binary'` as an alias
|
||||
- The `'utf8'` encoding previously did not touch Buffers. Now it will call `buffer.toString('utf8')` for consistency. Consumers can use the `'buffer'` encoding to avoid this conversion.
|
||||
|
||||
If you previously did one of the following (on a database that's defaulting to the `'utf8'` encoding):
|
||||
|
||||
```js
|
||||
await db.put('a', Buffer.from('x'))
|
||||
await db.put('a', Buffer.from('x'), { valueEncoding: 'binary' })
|
||||
```
|
||||
|
||||
Both examples will still work (assuming the buffer contains only UTF8 data) but you should now do:
|
||||
|
||||
```js
|
||||
await db.put('a', Buffer.from('x'), { valueEncoding: 'buffer' })
|
||||
```
|
||||
|
||||
Or use the new `'view'` encoding which accepts Uint8Arrays (and therefore also Buffer):
|
||||
|
||||
```js
|
||||
await db.put('a', new Uint8Array(...), { valueEncoding: 'view' })
|
||||
```
|
||||
|
||||
#### 2.2. For implementors
|
||||
|
||||
_You can skip this section if you're consuming (rather than writing) an `abstract-level` implementation._
|
||||
|
||||
Both the public and private API of `abstract-level` are encoding-aware. This means that private methods receive `keyEncoding` and `valueEncoding` options too, instead of the `keyAsBuffer`, `valueAsBuffer` and `asBuffer` options that `abstract-leveldown` had. Implementations don't need to perform encoding or decoding themselves. In fact they can do less: the `_serializeKey()` and `_serializeValue()` methods are also gone and implementations are less likely to have to convert between strings and buffers.
|
||||
|
||||
For example: a call like `db.put(key, { x: 2 }, { valueEncoding: 'json' })` will encode the `{ x: 2 }` value and might forward it to the private API as `db._put(key, '{"x":2}', { valueEncoding: 'utf8' }, callback)`. Same for the key, omitted for brevity. We say "might" because it depends on the implementation, which can now declare which encodings it supports.
|
||||
|
||||
To first give a concrete example for `get()`, if your implementation previously did:
|
||||
|
||||
```js
|
||||
class ExampleLeveldown extends AbstractLevelDOWN {
|
||||
_get (key, options, callback) {
|
||||
if (options.asBuffer) {
|
||||
this.nextTick(callback, null, Buffer.from('abc'))
|
||||
} else {
|
||||
this.nextTick(callback, null, 'abc')
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
You must now do (if still relevant):
|
||||
|
||||
```js
|
||||
class ExampleLevel extends AbstractLevel {
|
||||
_get (key, options, callback) {
|
||||
if (options.valueEncoding === 'buffer') {
|
||||
this.nextTick(callback, null, Buffer.from('abc'))
|
||||
} else {
|
||||
this.nextTick(callback, null, 'abc')
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The encoding options and data received by the private API depend on which encodings it supports. It must declare those via the manifest passed to the `AbstractLevel` constructor. See the [`README`](README.md) for details. For example, an implementation might only support storing data as Uint8Arrays, known here as the `'view'` encoding:
|
||||
|
||||
```js
|
||||
class ExampleLevel extends AbstractLevel {
|
||||
constructor (location, options) {
|
||||
super({ encodings: { view: true } }, options)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The earlier `put()` example would then result in `db._put(key, value, { valueEncoding: 'view' }, callback)` where `value` is a Uint8Array containing JSON in binary form. And the earlier `_get()` example can be simplified to:
|
||||
|
||||
```js
|
||||
class ExampleLevel extends AbstractLevel {
|
||||
_get (key, options, callback) {
|
||||
// No need to check valueEncoding as it's always 'view'
|
||||
this.nextTick(callback, null, new Uint8Array(...))
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Implementations can also declare support of multiple encodings; keys and values will then be encoded via the most optimal path. For example:
|
||||
|
||||
```js
|
||||
super({
|
||||
encodings: {
|
||||
view: true,
|
||||
utf8: true
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
#### 2.3. Other notable changes
|
||||
|
||||
- The `AbstractIterator` constructor now requires an `options` argument, for encoding options
|
||||
- The `AbstractIterator#_seek()` method got a new `options` argument, for a `keyEncoding` option
|
||||
- The `db.supports.bufferKeys` property has been removed. Use `db.supports.encodings.buffer` instead.
|
||||
|
||||
### 3. Streams have moved
|
||||
|
||||
Node.js readable streams must now be created with a new standalone module called [`level-read-stream`](https://github.com/Level/read-stream), rather than database methods like `db.createReadStream()`. Please see its [upgrade guide](https://github.com/Level/read-stream/blob/main/UPGRADING.md#100) for details.
|
||||
|
||||
To offer an alternative to `db.createKeyStream()` and `db.createValueStream()`, two new types of iterators have been added: `db.keys()` and `db.values()`. Their default implementations are functional but implementors may want to override them for optimal performance. The same goes for two new methods on iterators: `nextv()` and `all()`. To achieve this and honor the `limit` option, abstract iterators now count how many items they yielded, which may remove the need for implementations to do so on their own. Please see the README for details.
|
||||
|
||||
### 4. Zero-length keys and range options are now valid
|
||||
|
||||
These keys sort before anything else. Historically they weren't supported for causing segmentation faults in `leveldown`. That doesn't apply to today's codebase. Implementations must now support:
|
||||
|
||||
```js
|
||||
await db.put('', 'example')
|
||||
|
||||
console.log(await db.get('')) // 'example'
|
||||
|
||||
for await (const [key, value] of db.iterator({ lte: '' })) {
|
||||
console.log(value) // 'example'
|
||||
}
|
||||
```
|
||||
|
||||
Same goes for zero-length Buffer and Uint8Array keys. Zero-length keys would previously result in an error and never reach the private API.
|
||||
|
||||
### 5. Resources are auto-closed
|
||||
|
||||
To further improve safety and consistency, additional changes were made that make an `abstract-level` database safer to use than `abstract-leveldown` wrapped with `levelup`.
|
||||
|
||||
#### 5.1. Closing iterators is idempotent
|
||||
|
||||
The `iterator.end()` method has been renamed to `iterator.close()`, with `end()` being an alias until a next major version in the future. The term "close" makes it easier to differentiate between the iterator having reached its natural end (data-wise) versus closing it to cleanup resources. If you previously did:
|
||||
|
||||
```js
|
||||
const iterator = db.iterator()
|
||||
iterator.end(callback)
|
||||
```
|
||||
|
||||
You should now do one of:
|
||||
|
||||
```js
|
||||
iterator.close(callback)
|
||||
await iterator.close()
|
||||
```
|
||||
|
||||
Likewise, in the private API for implementors, `_end()` has been renamed to `_close()` but without an alias. This method is no longer allowed to yield an error.
|
||||
|
||||
On `db.close()`, non-closed iterators are now automatically closed. This may be a breaking change but only if an implementation has (at its own risk) overridden the public `end()` method, because `close()` or `end()` is now an idempotent operation rather than yielding an `end() already called on iterator` error. If a `next()` call is in progress, closing the iterator (or database) will wait for that.
|
||||
|
||||
The error message `cannot call next() after end()` has been replaced with code `LEVEL_ITERATOR_NOT_OPEN`, the error `cannot call seek() after end()` has been removed in favor of a silent return, and `cannot call next() before previous next() has completed` and `cannot call seek() before next() has completed` have been replaced with code `LEVEL_ITERATOR_BUSY`.
|
||||
|
||||
The `next()` method no longer returns `this` (when a callback is provided).
|
||||
|
||||
#### 5.2. Chained batch can be closed
|
||||
|
||||
Chained batch has a new method `close()` which is an idempotent operation and automatically called after `write()` (for backwards compatibility) or on `db.close()`. This to ensure batches can't be used after closing and reopening a db. If a `write()` is in progress, closing will wait for that. If `write()` is never called then `close()` must be. For example:
|
||||
|
||||
```js
|
||||
const batch = db.batch()
|
||||
.put('abc', 'zyz')
|
||||
.del('foo')
|
||||
|
||||
if (someCondition) {
|
||||
await batch.write()
|
||||
} else {
|
||||
// Decided not to commit
|
||||
await batch.close()
|
||||
}
|
||||
|
||||
// In either case this will throw
|
||||
batch.put('more', 'data')
|
||||
```
|
||||
|
||||
These changes could be breaking for an implementation that has (at its own risk) overridden the public `write()` method. In addition, the error message `write() already called on this batch` has been replaced with code `LEVEL_BATCH_NOT_OPEN`.
|
||||
|
||||
An implementation can optionally override `AbstractChainedBatch#_close()` if it has resources to free and wishes to free them earlier than GC would.
|
||||
|
||||
### 6. Errors now use codes
|
||||
|
||||
The [`level-errors`](https://github.com/Level/errors) module as used by `levelup` and friends, is not used or exposed by `abstract-level`. Instead errors thrown or yielded from a database have a `code` property. See the [`README`](./README.md#errors) for details. Going forward, the semver contract will be on `code` and error messages will change without a semver-major bump.
|
||||
|
||||
To minimize breakage, the most used error as yielded by `get()` when an entry is not found, has the same properties that `level-errors` added (`notFound` and `status`) in addition to code `LEVEL_NOT_FOUND`. Those properties will be removed in a future version. Implementations can still yield an error that matches `/NotFound/i.test(err)` or they can start using the code. Either way `abstract-level` will normalize the error.
|
||||
|
||||
If you previously did:
|
||||
|
||||
```js
|
||||
db.get('abc', function (err, value) {
|
||||
if (err && err.notFound) {
|
||||
// Handle missing entry
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
That will still work but it's preferred to do:
|
||||
|
||||
```js
|
||||
db.get('abc', function (err, value) {
|
||||
if (err && err.code === 'LEVEL_NOT_FOUND') {
|
||||
// Handle missing entry
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
Or using promises:
|
||||
|
||||
```js
|
||||
try {
|
||||
const value = await db.get('abc')
|
||||
} catch (err) {
|
||||
if (err.code === 'LEVEL_NOT_FOUND') {
|
||||
// Handle missing entry
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 7. Semi-private properties have been removed
|
||||
|
||||
The following properties and methods can no longer be accessed, as they've been removed or replaced with internal [symbols](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol):
|
||||
|
||||
- `AbstractIterator#_nexting`
|
||||
- `AbstractIterator#_ended`
|
||||
- `AbstractChainedBatch#_written`
|
||||
- `AbstractChainedBatch#_checkWritten()`
|
||||
- `AbstractChainedBatch#_operations`
|
||||
- `AbstractLevel#_setupIteratorOptions()`
|
||||
|
||||
### 8. Changes to test suite
|
||||
|
||||
_You can skip this section if you're consuming (rather than writing) an `abstract-level` implementation._
|
||||
|
||||
The abstract test suite of `abstract-level` has some breaking changes compared to `abstract-leveldown`:
|
||||
|
||||
- Options to skip tests have been removed in favor of `db.supports`
|
||||
- Support of `db.clear()` and `db.getMany()` is now mandatory. The default (slow) implementation of `_clear()` has been removed.
|
||||
- Added tests that `gte` and `lte` range options take precedence over `gt` and `lt` respectively. This is incompatible with [`ltgt`](https://github.com/dominictarr/ltgt) but aligns with `subleveldown`, [`level-option-wrap`](https://github.com/substack/level-option-wrap) and half of `leveldown`. There was no good choice.
|
||||
- The `setUp` and `tearDown` functions have been removed from the test suite and `suite.common()`.
|
||||
- Added ability to access manifests via `testCommon.supports`, by lazily copying it from `testCommon.factory().supports`. This requires that the manifest does not change during the lifetime of a `db`.
|
||||
- Your `factory()` function must now accept an `options` argument.
|
||||
|
||||
Many tests were imported from `levelup`, `encoding-down`, `deferred-leveldown`, `memdown`, `level-js` and `leveldown`. They test the changes described above and improve coverage of existing behavior.
|
||||
|
||||
Lastly, it's recommended to revisit any custom tests of an implementation. In particular if those tests relied upon the previously loose state checking of `abstract-leveldown`. For example, making a `db.put()` call before `db.open()`. Such a test now has a different meaning. The previous meaning can typically be restored by inserting `db.once('open', ...)` or `await db.open()` logic.
|
||||
|
||||
### 9. Sublevels are builtin
|
||||
|
||||
_This section is only relevant if you use [`subleveldown`](https://github.com/Level/subleveldown) (which can not wrap an `abstract-level` database)._
|
||||
|
||||
Sublevels are now builtin. If you previously did:
|
||||
|
||||
```js
|
||||
const sub = require('subleveldown')
|
||||
const example1 = sub(db, 'example1')
|
||||
const example2 = sub(db, 'example2', { valueEncoding: 'json' })
|
||||
```
|
||||
|
||||
You must now do:
|
||||
|
||||
```js
|
||||
const example1 = db.sublevel('example1')
|
||||
const example2 = db.sublevel('example2', { valueEncoding: 'json' })
|
||||
```
|
||||
|
||||
The key structure is equal to that of `subleveldown`. This means that an `abstract-level` sublevel can read sublevels previously created with (and populated by) `subleveldown`. There are some new features:
|
||||
|
||||
- `db.batch(..)` takes a `sublevel` option on operations, to atomically commit data to multiple sublevels
|
||||
- Sublevels support Uint8Array in addition to Buffer
|
||||
- `AbstractLevel#_sublevel()` can be overridden to add additional methods to sublevels.
|
||||
|
||||
To reduce function overloads, the prefix argument (`example1` above) is now required and it's called `name` here. If you previously did one of the following, resulting in an empty name:
|
||||
|
||||
```js
|
||||
subleveldown(db)
|
||||
subleveldown(db, { separator: '@' })
|
||||
```
|
||||
|
||||
You must now use an explicit empty name:
|
||||
|
||||
```js
|
||||
db.sublevel('')
|
||||
db.sublevel('', { separator: '@' })
|
||||
```
|
||||
|
||||
The string shorthand for `{ separator }` has also been removed. If you previously did:
|
||||
|
||||
```js
|
||||
subleveldown(db, 'example', '@')
|
||||
```
|
||||
|
||||
You must now do:
|
||||
|
||||
```js
|
||||
db.sublevel('example', { separator: '@' })
|
||||
```
|
||||
|
||||
Third, the `open` option has been removed. If you need an asynchronous open hook, feel free to open an issue to discuss restoring this API. Should it support promises? Should `abstract-level` support it on any database and not just sublevels?
|
||||
|
||||
Lastly, the error message `Parent database is not open` (courtesy of `subleveldown` which had to check open state to prevent segmentation faults from underlying databases) changed to error code [`LEVEL_DATABASE_NOT_OPEN`](https://github.com/Level/abstract-level#errors) (courtesy of `abstract-level` which does those checks on any database).
|
||||
|
||||
---
|
||||
|
||||
_For earlier releases, before `abstract-level` was forked from `abstract-leveldown` (v7.2.0), please see [the upgrade guide of `abstract-leveldown`](https://github.com/Level/abstract-leveldown/blob/master/UPGRADING.md)._
|
||||
181
resources/app/node_modules/abstract-level/abstract-chained-batch.js
generated
vendored
Normal file
181
resources/app/node_modules/abstract-level/abstract-chained-batch.js
generated
vendored
Normal file
@@ -0,0 +1,181 @@
|
||||
'use strict'
|
||||
|
||||
const { fromCallback } = require('catering')
|
||||
const ModuleError = require('module-error')
|
||||
const { getCallback, getOptions } = require('./lib/common')
|
||||
|
||||
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
|
||||
490
resources/app/node_modules/abstract-level/abstract-iterator.js
generated
vendored
Normal file
490
resources/app/node_modules/abstract-level/abstract-iterator.js
generated
vendored
Normal file
@@ -0,0 +1,490 @@
|
||||
'use strict'
|
||||
|
||||
const { fromCallback } = require('catering')
|
||||
const ModuleError = require('module-error')
|
||||
const { getOptions, getCallback } = require('./lib/common')
|
||||
|
||||
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
|
||||
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])
|
||||
}
|
||||
8
resources/app/node_modules/abstract-level/index.js
generated
vendored
Normal file
8
resources/app/node_modules/abstract-level/index.js
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
'use strict'
|
||||
|
||||
exports.AbstractLevel = require('./abstract-level').AbstractLevel
|
||||
exports.AbstractSublevel = require('./abstract-level').AbstractSublevel
|
||||
exports.AbstractIterator = require('./abstract-iterator').AbstractIterator
|
||||
exports.AbstractKeyIterator = require('./abstract-iterator').AbstractKeyIterator
|
||||
exports.AbstractValueIterator = require('./abstract-iterator').AbstractValueIterator
|
||||
exports.AbstractChainedBatch = require('./abstract-chained-batch').AbstractChainedBatch
|
||||
124
resources/app/node_modules/abstract-level/lib/abstract-sublevel-iterator.js
generated
vendored
Normal file
124
resources/app/node_modules/abstract-level/lib/abstract-sublevel-iterator.js
generated
vendored
Normal file
@@ -0,0 +1,124 @@
|
||||
'use strict'
|
||||
|
||||
const { AbstractIterator, AbstractKeyIterator, AbstractValueIterator } = require('../abstract-iterator')
|
||||
|
||||
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
|
||||
258
resources/app/node_modules/abstract-level/lib/abstract-sublevel.js
generated
vendored
Normal file
258
resources/app/node_modules/abstract-level/lib/abstract-sublevel.js
generated
vendored
Normal file
@@ -0,0 +1,258 @@
|
||||
'use strict'
|
||||
|
||||
const ModuleError = require('module-error')
|
||||
const { Buffer } = require('buffer') || {}
|
||||
const {
|
||||
AbstractSublevelIterator,
|
||||
AbstractSublevelKeyIterator,
|
||||
AbstractSublevelValueIterator
|
||||
} = require('./abstract-sublevel-iterator')
|
||||
|
||||
const kPrefix = Symbol('prefix')
|
||||
const kUpperBound = Symbol('upperBound')
|
||||
const kPrefixRange = Symbol('prefixRange')
|
||||
const kParent = Symbol('parent')
|
||||
const kUnfix = Symbol('unfix')
|
||||
|
||||
const textEncoder = new TextEncoder()
|
||||
const defaults = { separator: '!' }
|
||||
|
||||
// Wrapped to avoid circular dependency
|
||||
module.exports = function ({ AbstractLevel }) {
|
||||
class AbstractSublevel extends AbstractLevel {
|
||||
static defaults (options) {
|
||||
// To help migrating from subleveldown to abstract-level
|
||||
if (typeof options === 'string') {
|
||||
throw new ModuleError('The subleveldown string shorthand for { separator } has been removed', {
|
||||
code: 'LEVEL_LEGACY'
|
||||
})
|
||||
} else if (options && options.open) {
|
||||
throw new ModuleError('The subleveldown open option has been removed', {
|
||||
code: 'LEVEL_LEGACY'
|
||||
})
|
||||
}
|
||||
|
||||
if (options == null) {
|
||||
return defaults
|
||||
} else if (!options.separator) {
|
||||
return { ...options, separator: '!' }
|
||||
} else {
|
||||
return options
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: add autoClose option, which if true, does parent.attachResource(this)
|
||||
constructor (db, name, options) {
|
||||
// Don't forward AbstractSublevel options to AbstractLevel
|
||||
const { separator, manifest, ...forward } = AbstractSublevel.defaults(options)
|
||||
name = trim(name, separator)
|
||||
|
||||
// Reserve one character between separator and name to give us an upper bound
|
||||
const reserved = separator.charCodeAt(0) + 1
|
||||
const parent = db[kParent] || db
|
||||
|
||||
// Keys should sort like ['!a!', '!a!!a!', '!a"', '!aa!', '!b!'].
|
||||
// Use ASCII for consistent length between string, Buffer and Uint8Array
|
||||
if (!textEncoder.encode(name).every(x => x > reserved && x < 127)) {
|
||||
throw new ModuleError(`Prefix must use bytes > ${reserved} < ${127}`, {
|
||||
code: 'LEVEL_INVALID_PREFIX'
|
||||
})
|
||||
}
|
||||
|
||||
super(mergeManifests(parent, manifest), forward)
|
||||
|
||||
const prefix = (db.prefix || '') + separator + name + separator
|
||||
const upperBound = prefix.slice(0, -1) + String.fromCharCode(reserved)
|
||||
|
||||
this[kParent] = parent
|
||||
this[kPrefix] = new MultiFormat(prefix)
|
||||
this[kUpperBound] = new MultiFormat(upperBound)
|
||||
this[kUnfix] = new Unfixer()
|
||||
|
||||
this.nextTick = parent.nextTick
|
||||
}
|
||||
|
||||
prefixKey (key, keyFormat) {
|
||||
if (keyFormat === 'utf8') {
|
||||
return this[kPrefix].utf8 + key
|
||||
} else if (key.byteLength === 0) {
|
||||
// Fast path for empty key (no copy)
|
||||
return this[kPrefix][keyFormat]
|
||||
} else if (keyFormat === 'view') {
|
||||
const view = this[kPrefix].view
|
||||
const result = new Uint8Array(view.byteLength + key.byteLength)
|
||||
|
||||
result.set(view, 0)
|
||||
result.set(key, view.byteLength)
|
||||
|
||||
return result
|
||||
} else {
|
||||
const buffer = this[kPrefix].buffer
|
||||
return Buffer.concat([buffer, key], buffer.byteLength + key.byteLength)
|
||||
}
|
||||
}
|
||||
|
||||
// Not exposed for now.
|
||||
[kPrefixRange] (range, keyFormat) {
|
||||
if (range.gte !== undefined) {
|
||||
range.gte = this.prefixKey(range.gte, keyFormat)
|
||||
} else if (range.gt !== undefined) {
|
||||
range.gt = this.prefixKey(range.gt, keyFormat)
|
||||
} else {
|
||||
range.gte = this[kPrefix][keyFormat]
|
||||
}
|
||||
|
||||
if (range.lte !== undefined) {
|
||||
range.lte = this.prefixKey(range.lte, keyFormat)
|
||||
} else if (range.lt !== undefined) {
|
||||
range.lt = this.prefixKey(range.lt, keyFormat)
|
||||
} else {
|
||||
range.lte = this[kUpperBound][keyFormat]
|
||||
}
|
||||
}
|
||||
|
||||
get prefix () {
|
||||
return this[kPrefix].utf8
|
||||
}
|
||||
|
||||
get db () {
|
||||
return this[kParent]
|
||||
}
|
||||
|
||||
_open (options, callback) {
|
||||
// The parent db must open itself or be (re)opened by the user because
|
||||
// a sublevel should not initiate state changes on the rest of the db.
|
||||
this[kParent].open({ passive: true }, callback)
|
||||
}
|
||||
|
||||
_put (key, value, options, callback) {
|
||||
this[kParent].put(key, value, options, callback)
|
||||
}
|
||||
|
||||
_get (key, options, callback) {
|
||||
this[kParent].get(key, options, callback)
|
||||
}
|
||||
|
||||
_getMany (keys, options, callback) {
|
||||
this[kParent].getMany(keys, options, callback)
|
||||
}
|
||||
|
||||
_del (key, options, callback) {
|
||||
this[kParent].del(key, options, callback)
|
||||
}
|
||||
|
||||
_batch (operations, options, callback) {
|
||||
this[kParent].batch(operations, options, callback)
|
||||
}
|
||||
|
||||
_clear (options, callback) {
|
||||
// TODO (refactor): move to AbstractLevel
|
||||
this[kPrefixRange](options, options.keyEncoding)
|
||||
this[kParent].clear(options, callback)
|
||||
}
|
||||
|
||||
_iterator (options) {
|
||||
// TODO (refactor): move to AbstractLevel
|
||||
this[kPrefixRange](options, options.keyEncoding)
|
||||
const iterator = this[kParent].iterator(options)
|
||||
const unfix = this[kUnfix].get(this[kPrefix].utf8.length, options.keyEncoding)
|
||||
return new AbstractSublevelIterator(this, options, iterator, unfix)
|
||||
}
|
||||
|
||||
_keys (options) {
|
||||
this[kPrefixRange](options, options.keyEncoding)
|
||||
const iterator = this[kParent].keys(options)
|
||||
const unfix = this[kUnfix].get(this[kPrefix].utf8.length, options.keyEncoding)
|
||||
return new AbstractSublevelKeyIterator(this, options, iterator, unfix)
|
||||
}
|
||||
|
||||
_values (options) {
|
||||
this[kPrefixRange](options, options.keyEncoding)
|
||||
const iterator = this[kParent].values(options)
|
||||
return new AbstractSublevelValueIterator(this, options, iterator)
|
||||
}
|
||||
}
|
||||
|
||||
return { AbstractSublevel }
|
||||
}
|
||||
|
||||
const mergeManifests = function (parent, manifest) {
|
||||
return {
|
||||
// Inherit manifest of parent db
|
||||
...parent.supports,
|
||||
|
||||
// Disable unsupported features
|
||||
createIfMissing: false,
|
||||
errorIfExists: false,
|
||||
|
||||
// Unset additional events because we're not forwarding them
|
||||
events: {},
|
||||
|
||||
// Unset additional methods (like approximateSize) which we can't support here unless
|
||||
// the AbstractSublevel class is overridden by an implementation of `abstract-level`.
|
||||
additionalMethods: {},
|
||||
|
||||
// Inherit manifest of custom AbstractSublevel subclass. Such a class is not
|
||||
// allowed to override encodings.
|
||||
...manifest,
|
||||
|
||||
encodings: {
|
||||
utf8: supportsEncoding(parent, 'utf8'),
|
||||
buffer: supportsEncoding(parent, 'buffer'),
|
||||
view: supportsEncoding(parent, 'view')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const supportsEncoding = function (parent, encoding) {
|
||||
// Prefer a non-transcoded encoding for optimal performance
|
||||
return parent.supports.encodings[encoding]
|
||||
? parent.keyEncoding(encoding).name === encoding
|
||||
: false
|
||||
}
|
||||
|
||||
class MultiFormat {
|
||||
constructor (key) {
|
||||
this.utf8 = key
|
||||
this.view = textEncoder.encode(key)
|
||||
this.buffer = Buffer ? Buffer.from(this.view.buffer, 0, this.view.byteLength) : {}
|
||||
}
|
||||
}
|
||||
|
||||
class Unfixer {
|
||||
constructor () {
|
||||
this.cache = new Map()
|
||||
}
|
||||
|
||||
get (prefixLength, keyFormat) {
|
||||
let unfix = this.cache.get(keyFormat)
|
||||
|
||||
if (unfix === undefined) {
|
||||
if (keyFormat === 'view') {
|
||||
unfix = function (prefixLength, key) {
|
||||
// Avoid Uint8Array#slice() because it copies
|
||||
return key.subarray(prefixLength)
|
||||
}.bind(null, prefixLength)
|
||||
} else {
|
||||
unfix = function (prefixLength, key) {
|
||||
// Avoid Buffer#subarray() because it's slow
|
||||
return key.slice(prefixLength)
|
||||
}.bind(null, prefixLength)
|
||||
}
|
||||
|
||||
this.cache.set(keyFormat, unfix)
|
||||
}
|
||||
|
||||
return unfix
|
||||
}
|
||||
}
|
||||
|
||||
const trim = function (str, char) {
|
||||
let start = 0
|
||||
let end = str.length
|
||||
|
||||
while (start < end && str[start] === char) start++
|
||||
while (end > start && str[end - 1] === char) end--
|
||||
|
||||
return str.slice(start, end)
|
||||
}
|
||||
17
resources/app/node_modules/abstract-level/lib/common.js
generated
vendored
Normal file
17
resources/app/node_modules/abstract-level/lib/common.js
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
'use strict'
|
||||
|
||||
exports.getCallback = function (options, callback) {
|
||||
return typeof options === 'function' ? options : callback
|
||||
}
|
||||
|
||||
exports.getOptions = function (options, def) {
|
||||
if (typeof options === 'object' && options !== null) {
|
||||
return options
|
||||
}
|
||||
|
||||
if (def !== undefined) {
|
||||
return def
|
||||
}
|
||||
|
||||
return {}
|
||||
}
|
||||
41
resources/app/node_modules/abstract-level/lib/default-chained-batch.js
generated
vendored
Normal file
41
resources/app/node_modules/abstract-level/lib/default-chained-batch.js
generated
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
'use strict'
|
||||
|
||||
const { AbstractChainedBatch } = require('../abstract-chained-batch')
|
||||
const ModuleError = require('module-error')
|
||||
const kEncoded = Symbol('encoded')
|
||||
|
||||
// Functional default for chained batch, with support of deferred open
|
||||
class DefaultChainedBatch extends AbstractChainedBatch {
|
||||
constructor (db) {
|
||||
super(db)
|
||||
this[kEncoded] = []
|
||||
}
|
||||
|
||||
_put (key, value, options) {
|
||||
this[kEncoded].push({ ...options, type: 'put', key, value })
|
||||
}
|
||||
|
||||
_del (key, options) {
|
||||
this[kEncoded].push({ ...options, type: 'del', key })
|
||||
}
|
||||
|
||||
_clear () {
|
||||
this[kEncoded] = []
|
||||
}
|
||||
|
||||
// Assumes this[kEncoded] cannot change after write()
|
||||
_write (options, callback) {
|
||||
if (this.db.status === 'opening') {
|
||||
this.db.defer(() => this._write(options, callback))
|
||||
} else if (this.db.status === 'open') {
|
||||
if (this[kEncoded].length === 0) this.nextTick(callback)
|
||||
else this.db._batch(this[kEncoded], options, callback)
|
||||
} else {
|
||||
this.nextTick(callback, new ModuleError('Batch is not open: cannot call write() after write() or close()', {
|
||||
code: 'LEVEL_BATCH_NOT_OPEN'
|
||||
}))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
exports.DefaultChainedBatch = DefaultChainedBatch
|
||||
72
resources/app/node_modules/abstract-level/lib/default-kv-iterator.js
generated
vendored
Normal file
72
resources/app/node_modules/abstract-level/lib/default-kv-iterator.js
generated
vendored
Normal file
@@ -0,0 +1,72 @@
|
||||
'use strict'
|
||||
|
||||
const { AbstractKeyIterator, AbstractValueIterator } = require('../abstract-iterator')
|
||||
|
||||
const kIterator = Symbol('iterator')
|
||||
const kCallback = Symbol('callback')
|
||||
const kHandleOne = Symbol('handleOne')
|
||||
const kHandleMany = Symbol('handleMany')
|
||||
|
||||
class DefaultKeyIterator extends AbstractKeyIterator {
|
||||
constructor (db, options) {
|
||||
super(db, options)
|
||||
|
||||
this[kIterator] = db.iterator({ ...options, keys: true, values: false })
|
||||
this[kHandleOne] = this[kHandleOne].bind(this)
|
||||
this[kHandleMany] = this[kHandleMany].bind(this)
|
||||
}
|
||||
}
|
||||
|
||||
class DefaultValueIterator extends AbstractValueIterator {
|
||||
constructor (db, options) {
|
||||
super(db, options)
|
||||
|
||||
this[kIterator] = db.iterator({ ...options, keys: false, values: true })
|
||||
this[kHandleOne] = this[kHandleOne].bind(this)
|
||||
this[kHandleMany] = this[kHandleMany].bind(this)
|
||||
}
|
||||
}
|
||||
|
||||
for (const Iterator of [DefaultKeyIterator, DefaultValueIterator]) {
|
||||
const keys = Iterator === DefaultKeyIterator
|
||||
const mapEntry = keys ? (entry) => entry[0] : (entry) => entry[1]
|
||||
|
||||
Iterator.prototype._next = function (callback) {
|
||||
this[kCallback] = callback
|
||||
this[kIterator].next(this[kHandleOne])
|
||||
}
|
||||
|
||||
Iterator.prototype[kHandleOne] = function (err, key, value) {
|
||||
const callback = this[kCallback]
|
||||
if (err) callback(err)
|
||||
else callback(null, keys ? key : value)
|
||||
}
|
||||
|
||||
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])
|
||||
}
|
||||
|
||||
Iterator.prototype[kHandleMany] = function (err, entries) {
|
||||
const callback = this[kCallback]
|
||||
if (err) callback(err)
|
||||
else callback(null, entries.map(mapEntry))
|
||||
}
|
||||
|
||||
Iterator.prototype._seek = function (target, options) {
|
||||
this[kIterator].seek(target, options)
|
||||
}
|
||||
|
||||
Iterator.prototype._close = function (callback) {
|
||||
this[kIterator].close(callback)
|
||||
}
|
||||
}
|
||||
|
||||
// Internal utilities, should be typed as AbstractKeyIterator and AbstractValueIterator
|
||||
exports.DefaultKeyIterator = DefaultKeyIterator
|
||||
exports.DefaultValueIterator = DefaultValueIterator
|
||||
108
resources/app/node_modules/abstract-level/lib/deferred-iterator.js
generated
vendored
Normal file
108
resources/app/node_modules/abstract-level/lib/deferred-iterator.js
generated
vendored
Normal file
@@ -0,0 +1,108 @@
|
||||
'use strict'
|
||||
|
||||
const { AbstractIterator, AbstractKeyIterator, AbstractValueIterator } = require('../abstract-iterator')
|
||||
const ModuleError = require('module-error')
|
||||
|
||||
const kNut = Symbol('nut')
|
||||
const kUndefer = Symbol('undefer')
|
||||
const kFactory = Symbol('factory')
|
||||
|
||||
class DeferredIterator extends AbstractIterator {
|
||||
constructor (db, options) {
|
||||
super(db, options)
|
||||
|
||||
this[kNut] = null
|
||||
this[kFactory] = () => db.iterator(options)
|
||||
|
||||
this.db.defer(() => this[kUndefer]())
|
||||
}
|
||||
}
|
||||
|
||||
class DeferredKeyIterator extends AbstractKeyIterator {
|
||||
constructor (db, options) {
|
||||
super(db, options)
|
||||
|
||||
this[kNut] = null
|
||||
this[kFactory] = () => db.keys(options)
|
||||
|
||||
this.db.defer(() => this[kUndefer]())
|
||||
}
|
||||
}
|
||||
|
||||
class DeferredValueIterator extends AbstractValueIterator {
|
||||
constructor (db, options) {
|
||||
super(db, options)
|
||||
|
||||
this[kNut] = null
|
||||
this[kFactory] = () => db.values(options)
|
||||
|
||||
this.db.defer(() => this[kUndefer]())
|
||||
}
|
||||
}
|
||||
|
||||
for (const Iterator of [DeferredIterator, DeferredKeyIterator, DeferredValueIterator]) {
|
||||
Iterator.prototype[kUndefer] = function () {
|
||||
if (this.db.status === 'open') {
|
||||
this[kNut] = this[kFactory]()
|
||||
}
|
||||
}
|
||||
|
||||
Iterator.prototype._next = function (callback) {
|
||||
if (this[kNut] !== null) {
|
||||
this[kNut].next(callback)
|
||||
} else if (this.db.status === 'opening') {
|
||||
this.db.defer(() => this._next(callback))
|
||||
} else {
|
||||
this.nextTick(callback, new ModuleError('Iterator is not open: cannot call next() after close()', {
|
||||
code: 'LEVEL_ITERATOR_NOT_OPEN'
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
Iterator.prototype._nextv = function (size, options, callback) {
|
||||
if (this[kNut] !== null) {
|
||||
this[kNut].nextv(size, options, callback)
|
||||
} else if (this.db.status === 'opening') {
|
||||
this.db.defer(() => this._nextv(size, options, callback))
|
||||
} else {
|
||||
this.nextTick(callback, new ModuleError('Iterator is not open: cannot call nextv() after close()', {
|
||||
code: 'LEVEL_ITERATOR_NOT_OPEN'
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
Iterator.prototype._all = function (options, callback) {
|
||||
if (this[kNut] !== null) {
|
||||
this[kNut].all(callback)
|
||||
} else if (this.db.status === 'opening') {
|
||||
this.db.defer(() => this._all(options, callback))
|
||||
} else {
|
||||
this.nextTick(callback, new ModuleError('Iterator is not open: cannot call all() after close()', {
|
||||
code: 'LEVEL_ITERATOR_NOT_OPEN'
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
Iterator.prototype._seek = function (target, options) {
|
||||
if (this[kNut] !== null) {
|
||||
// TODO: explain why we need _seek() rather than seek() here
|
||||
this[kNut]._seek(target, options)
|
||||
} else if (this.db.status === 'opening') {
|
||||
this.db.defer(() => this._seek(target, options))
|
||||
}
|
||||
}
|
||||
|
||||
Iterator.prototype._close = function (callback) {
|
||||
if (this[kNut] !== null) {
|
||||
this[kNut].close(callback)
|
||||
} else if (this.db.status === 'opening') {
|
||||
this.db.defer(() => this._close(callback))
|
||||
} else {
|
||||
this.nextTick(callback)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
exports.DeferredIterator = DeferredIterator
|
||||
exports.DeferredKeyIterator = DeferredKeyIterator
|
||||
exports.DeferredValueIterator = DeferredValueIterator
|
||||
11
resources/app/node_modules/abstract-level/lib/next-tick-browser.js
generated
vendored
Normal file
11
resources/app/node_modules/abstract-level/lib/next-tick-browser.js
generated
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
'use strict'
|
||||
|
||||
const queueMicrotask = require('queue-microtask')
|
||||
|
||||
module.exports = function (fn, ...args) {
|
||||
if (args.length === 0) {
|
||||
queueMicrotask(fn)
|
||||
} else {
|
||||
queueMicrotask(() => fn(...args))
|
||||
}
|
||||
}
|
||||
3
resources/app/node_modules/abstract-level/lib/next-tick.js
generated
vendored
Normal file
3
resources/app/node_modules/abstract-level/lib/next-tick.js
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
'use strict'
|
||||
|
||||
module.exports = process.nextTick
|
||||
38
resources/app/node_modules/abstract-level/lib/range-options.js
generated
vendored
Normal file
38
resources/app/node_modules/abstract-level/lib/range-options.js
generated
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
'use strict'
|
||||
|
||||
const ModuleError = require('module-error')
|
||||
const hasOwnProperty = Object.prototype.hasOwnProperty
|
||||
const rangeOptions = new Set(['lt', 'lte', 'gt', 'gte'])
|
||||
|
||||
module.exports = function (options, keyEncoding) {
|
||||
const result = {}
|
||||
|
||||
for (const k in options) {
|
||||
if (!hasOwnProperty.call(options, k)) continue
|
||||
if (k === 'keyEncoding' || k === 'valueEncoding') continue
|
||||
|
||||
if (k === 'start' || k === 'end') {
|
||||
throw new ModuleError(`The legacy range option '${k}' has been removed`, {
|
||||
code: 'LEVEL_LEGACY'
|
||||
})
|
||||
} else if (k === 'encoding') {
|
||||
// To help migrating to abstract-level
|
||||
throw new ModuleError("The levelup-style 'encoding' alias has been removed, use 'valueEncoding' instead", {
|
||||
code: 'LEVEL_LEGACY'
|
||||
})
|
||||
}
|
||||
|
||||
if (rangeOptions.has(k)) {
|
||||
// Note that we don't reject nullish and empty options here. While
|
||||
// those types are invalid as keys, they are valid as range options.
|
||||
result[k] = keyEncoding.encode(options[k])
|
||||
} else {
|
||||
result[k] = options[k]
|
||||
}
|
||||
}
|
||||
|
||||
result.reverse = !!result.reverse
|
||||
result.limit = Number.isInteger(result.limit) && result.limit >= 0 ? result.limit : -1
|
||||
|
||||
return result
|
||||
}
|
||||
54
resources/app/node_modules/abstract-level/package.json
generated
vendored
Normal file
54
resources/app/node_modules/abstract-level/package.json
generated
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
{
|
||||
"name": "abstract-level",
|
||||
"version": "1.0.4",
|
||||
"description": "Abstract class for a lexicographically sorted key-value database",
|
||||
"license": "MIT",
|
||||
"main": "index.js",
|
||||
"browser": {
|
||||
"./lib/next-tick.js": "./lib/next-tick-browser.js"
|
||||
},
|
||||
"types": "./index.d.ts",
|
||||
"files": [
|
||||
"abstract-chained-batch.js",
|
||||
"abstract-iterator.js",
|
||||
"abstract-level.js",
|
||||
"index.js",
|
||||
"index.d.ts",
|
||||
"lib",
|
||||
"test",
|
||||
"types",
|
||||
"CHANGELOG.md",
|
||||
"UPGRADING.md"
|
||||
],
|
||||
"dependencies": {
|
||||
"buffer": "^6.0.3",
|
||||
"catering": "^2.1.0",
|
||||
"is-buffer": "^2.0.5",
|
||||
"level-supports": "^4.0.0",
|
||||
"level-transcoder": "^1.0.1",
|
||||
"module-error": "^1.0.1",
|
||||
"queue-microtask": "^1.2.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^18.0.0",
|
||||
"@voxpelli/tsconfig": "^4.0.0",
|
||||
"airtap": "^4.0.4",
|
||||
"airtap-playwright": "^1.0.1",
|
||||
"faucet": "^0.0.3",
|
||||
"hallmark": "^4.0.0",
|
||||
"nyc": "^15.1.0",
|
||||
"sinon": "^14.0.0",
|
||||
"standard": "^16.0.4",
|
||||
"tape": "^5.4.0",
|
||||
"ts-standard": "^11.0.0",
|
||||
"typescript": "^4.5.5"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Level/abstract-level.git"
|
||||
},
|
||||
"homepage": "https://github.com/Level/abstract-level",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user