diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 3e0a046..8aff810 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -5,7 +5,8 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
- node: [16, 18, 20]
+ # TODO (next major): officially drop node 16
+ node: [18, 20, 22]
name: Node ${{ matrix.node }}
steps:
- name: Checkout
@@ -17,12 +18,12 @@ jobs:
- name: Install
run: npm install
- name: Install Playwright
- if: matrix.node == 16
+ if: matrix.node == 18
run: npx playwright install --with-deps
- name: Test
run: npm test
- name: Test browsers
- if: matrix.node == 16
+ if: matrix.node == 18
run: npm run test-browsers-local
- name: Coverage
run: npm run coverage
diff --git a/README.md b/README.md
index a3cefe7..cf987b9 100644
--- a/README.md
+++ b/README.md
@@ -5,7 +5,7 @@
[![level badge][level-badge]](https://github.com/Level/awesome)
[](https://www.npmjs.com/package/level-supports)
[](https://www.npmjs.com/package/level-supports)
-[](https://github.com/Level/level/actions/workflows/test.yml)
+[](https://github.com/Level/level/actions/workflows/test.yml)
[](https://codecov.io/gh/Level/supports)
[](https://standardjs.com)
[](https://common-changelog.org)
@@ -41,66 +41,70 @@ Given zero or more manifest objects, returns a merged and enriched manifest obje
For future extensibility, the properties are truthy rather than strictly typed booleans. Falsy or absent properties are converted to `false`, other values are allowed:
```js
-supports().snapshots // false
-supports({ snapshots: true }).snapshots // true
-supports({ snapshots: {} }).snapshots // {}
-supports({ snapshots: 1 }, { snapshots: 2 }).snapshots // 2
+supports().seek // false
+supports({ seek: true }).seek // true
+supports({ seek: {} }).seek // {}
+supports({ seek: 1 }, { seek: 2 }).seek // 2
```
For consumers of the manifest this means they should check support like so:
```js
-if (db.supports.snapshots)
+if (db.supports.seek)
```
Rather than:
```js
-if (db.supports.snapshots === true)
+if (db.supports.seek === true)
```
**Note:** the manifest describes high-level features that typically encompass multiple methods of a db. It is currently not a goal to describe a full API, or versions of it.
## Features
-### `snapshots` (boolean)
+### `implicitSnapshots` (boolean)
-Does the database have snapshot guarantees? Meaning that reads are unaffected by simultaneous writes. For example, an iterator should read from a snapshot of the database, created at the time `db.iterator()` was called. This means the iterator will not see the data of simultaneous write operations.
-
-Must be `false` if any of the following is true:
+Does the database read from a snapshot as described in [`abstract-level`](https://github.com/Level/abstract-level#reading-from-snapshots)? Must be `false` if any of the following is true:
- Reads don't operate on a snapshot
- Snapshots are created asynchronously.
+Aliased as `snapshots` for backwards compatibility.
+
+
+Support matrix
+
+| Module | Implicit snapshots |
+| :-------------- | :-------------------------- |
+| `classic-level` | ✅ |
+| `memory-level` | ✅ |
+| `browser-level` | ❌ |
+| `level` | ✅ |
+| `many-level` | ✅ (unless `retry` is true) |
+| `rave-level` | ❌ (unless `retry` is false) |
+
+
+
+### `explicitSnapshots` (boolean)
+
+Does the database implement `db.snapshot()` and do read methods accept a `snapshot` option as described in [`abstract-level`](https://github.com/Level/abstract-level#reading-from-snapshots)?
+
Support matrix
-| Module | Snapshot guarantee |
-| :------------------- | :-------------------------- |
-| `classic-level` | ✅ |
-| `memory-level` | ✅ |
-| `browser-level` | ❌ |
-| `rocks-level` | ✅ |
-| `leveldown` | ✅ |
-| `rocksdb` | ✅ |
-| `memdown` | ✅ |
-| `level-js` | ✅ (by buffering) |
-| `encoding-down` | ✅ |
-| `deferred-leveldown` | ✅ |
-| `levelup` | ✅ |
-| `level-packager` | ✅ |
-| `level` | ✅ |
-| `level-mem` | ✅ |
-| `level-rocksdb` | ✅ |
-| `subleveldown` | ✅ |
-| `multileveldown` | ✅ (unless `retry` is true) |
-| `level-party` | ❌ (unless `retry` is false) |
+| Module | Explicit snapshots |
+| :-------------- | :----------------- |
+| `classic-level` | Not yet |
+| `memory-level` | Not yet |
+| `browser-level` | ❌ |
+| `rave-level` | TBD |
### `permanence` (boolean)
-Does data survive after process (or environment) exit? Typically true. False for [`memory-level`](https://github.com/Level/memory-level) and [`memdown`](https://github.com/Level/memdown).
+Does data survive after process (or environment) exit? Typically true. False for [`memory-level`](https://github.com/Level/memory-level).
### `seek` (boolean)
@@ -109,28 +113,15 @@ Do iterators support [`seek(..)`](https://github.com/Level/abstract-level/#itera
Support matrix
-| Module | Support |
-| :------------------- | :------ |
-| `abstract-level` | ✅ 1.0.0 |
-| `classic-level` | ✅ 1.0.0 |
-| `memory-level` | ✅ 1.0.0 |
-| `browser-level` | ✅ 1.0.0 |
-| `rocks-level` | ✅ 1.0.0 |
-| `abstract-leveldown` | ✅ 6.0.0 |
-| `leveldown` | ✅ 1.2.0 |
-| `rocksdb` | ✅ 1.0.0 |
-| `memdown` | ✅ 4.1.0 |
-| `level-js` | ❌ |
-| `encoding-down` | ✅ 6.1.0 |
-| `deferred-leveldown` | ✅ 5.1.0 |
-| `levelup` | ✅ n/a |
-| `level-packager` | ✅ n/a |
-| `level` | ✅ 8.0.0 |
-| `level-mem` | ✅ 4.0.0 |
-| `level-rocksdb` | ✅ 1.0.0 |
-| `subleveldown` | ✅ 4.1.0 |
-| `multileveldown` | ❌ |
-| `level-party` | ❌ |
+| Module | Support |
+| :--------------- | :------ |
+| `abstract-level` | ✅ 1.0.0 |
+| `classic-level` | ✅ 1.0.0 |
+| `memory-level` | ✅ 1.0.0 |
+| `browser-level` | ✅ 1.0.0 |
+| `level` | ✅ 8.0.0 |
+| `many-level` | ✅ 1.0.0 |
+| `rave-level` | ✅ 1.0.0 |
@@ -155,13 +146,8 @@ Does `db.open()` support these options?
| Module | Support |
| :-------------- | :------ |
| `classic-level` | ✅ |
-| `rocks-level` | ✅ |
| `memory-level` | ❌ |
| `browser-level` | ❌ |
-| `leveldown` | ✅ |
-| `rocksdb` | ✅ |
-| `memdown` | ❌ |
-| `level-js` | ❌ |
@@ -177,25 +163,7 @@ if (db.supports.events.put) {
### `streams` (boolean)
-Does database have the methods `createReadStream`, `createKeyStream` and `createValueStream`, following the API documented in `levelup`? For `abstract-level` databases, a standalone module called [`level-read-stream`](https://github.com/Level/read-stream) is available.
-
-
-Support matrix
-
-| Module | Support |
-| :---------------------------------- | :------ |
-| `abstract-level` and dependents | ❌ |
-| `abstract-leveldown` and dependents | ❌ |
-| `levelup` | ✅ |
-| `level-packager` | ✅ |
-| `level` | ✅ |
-| `level-mem` | ✅ |
-| `level-rocksdb` | ✅ |
-| `subleveldown` | ✅ |
-| `multileveldown` | ✅ |
-| `level-party` | ✅ |
-
-
+Does database have the methods `createReadStream`, `createKeyStream` and `createValueStream`, following the API documented in the legacy `levelup` module? Always false since the introduction of `abstract-level` which moved streams to a standalone module called [`level-read-stream`](https://github.com/Level/read-stream).
### `encodings` (object)
@@ -207,27 +175,6 @@ Which encodings (by name) does the database support, as indicated by nested prop
As the `encodings` property cannot be false (anymore, since `level-supports` v3.0.0) it implies that the database supports `keyEncoding` and `valueEncoding` options on all relevant methods, uses a default encoding of utf8 and that hence all of its read operations return strings rather than buffers by default.
-
-Support matrix (general support)
-
-_This matrix just indicates general support of encodings as a feature, not that the listed modules support the `encodings` property exactly as described above, which only works on `abstract-level` databases._
-
-| Module | Support |
-| :------------------------------------- | :------ |
-| `abstract-level` (and dependents) | ✅ |
-| `abstract-leveldown` (and dependents) | ❌ |
-| `encoding-down` | ✅ |
-| `levelup` | ✅ |
-| `level-packager` | ✅ |
-| `level` | ✅ |
-| `level-mem` | ✅ |
-| `level-rocksdb` | ✅ |
-| `subleveldown` | ✅ |
-| `multileveldown` | ✅ |
-| `level-party` | ✅ |
-
-
-
Support matrix (specific encodings)
@@ -238,7 +185,6 @@ _This matrix lists which encodings are supported as indicated by e.g. `db.suppor
| `classic-level` | ✅ | ✅ | ✅ 1 |
| `memory-level` | ✅ 2 | ✅ 2 | ✅ 2 |
| `browser-level` | ✅ 1 | ✅ 1 | ✅ |
-| `rocks-level` | ✅ | ✅ | ✅ 1 |
| `level@8` | ✅ 3 | ✅ 3 | ✅ 3 |
diff --git a/index.js b/index.js
index 803956c..618aa6c 100644
--- a/index.js
+++ b/index.js
@@ -3,8 +3,14 @@
exports.supports = function supports (...manifests) {
const manifest = manifests.reduce((acc, m) => Object.assign(acc, m), {})
+ // Snapshots is an alias for backwards compatibility
+ const implicitSnapshots = manifest.implicitSnapshots || manifest.snapshots || false
+ const explicitSnapshots = manifest.explicitSnapshots || false
+
return Object.assign(manifest, {
- snapshots: manifest.snapshots || false,
+ implicitSnapshots,
+ explicitSnapshots,
+ snapshots: implicitSnapshots,
permanence: manifest.permanence || false,
seek: manifest.seek || false,
createIfMissing: manifest.createIfMissing || false,
diff --git a/test/self.js b/test/self.js
index 2382a30..78eb8aa 100644
--- a/test/self.js
+++ b/test/self.js
@@ -73,3 +73,14 @@ test('does not merge additionalMethods', function (t) {
t.same(manifest.additionalMethods, { bar: true })
t.end()
})
+
+test('adds snapshots alias', function (t) {
+ for (const value of [true, false]) {
+ t.is(supports({ implicitSnapshots: value }).implicitSnapshots, value)
+ t.is(supports({ implicitSnapshots: value }).snapshots, value)
+ t.is(supports({ snapshots: value }).implicitSnapshots, value)
+ t.is(supports({ snapshots: value }).snapshots, value)
+ }
+
+ t.end()
+})