Skip to content
This repository was archived by the owner on Dec 2, 2024. It is now read-only.

Commit 97c464f

Browse files
authored
Add UPGRADING.md (#143)
* add UPGRADING.md * don't to => don't be too * add remark-toc and remark-collapse * also run remark on UPGRADING.md (just for style) * move and expand type docs from UPGRADING to README * reuse reference links and shorten goals * it was => they were * fulfulling => fulfilling
1 parent 9d93fda commit 97c464f

File tree

4 files changed

+245
-15
lines changed

4 files changed

+245
-15
lines changed

Diff for: CHANGELOG.md

-4
Original file line numberDiff line numberDiff line change
@@ -59,10 +59,6 @@
5959
* Remove testling from `package.json` (@vweevers)
6060
* Remove `level.js` logo (@vweevers)
6161

62-
**Historical Note** As a result of removing `IDBWrapper`, only modern browsers with a non-prefixed `window.indexedDB` are supported in this release. The current test matrix of `level-js` includes the latest versions of Chrome, Firefox, Safari, Edge and IE.
63-
64-
**Historical Note** Though `level-js` now passes the full `abstract-leveldown` test suite, fulfulling the snapshot guarantee (reads not being affected by simultaneous writes) means a loss of backpressure as iterators have to keep reading from their IndexedDB cursors. Memory consumption might increase if an iterator is not consumed fast enough. A future release will have an option to favor backpressure over snapshot guarantees.
65-
6662
**Historical Note** This release introduced the boolean `binaryKeys` and `arrayKeys` properties on the constructor, indicating whether the environment supports binary and array keys respectively. These properties may become private.
6763

6864
**Historical Note** The vendored `IndexedDBShim` is still included, but likely to be removed.

Diff for: README.md

+139-9
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,47 @@
11
# level-js
22

3-
> An [`abstract-leveldown`](https://github.com/Level/abstract-leveldown) compliant store on top of [IndexedDB](https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API), which is in turn implemented on top of [LevelDB](https://github.com/google/leveldb) which brings this whole shebang full circle.
3+
> An [`abstract-leveldown`][abstract-leveldown] compliant store on top of [IndexedDB][indexeddb], which is in turn implemented on top of [LevelDB][leveldb] which brings this whole shebang full circle.
44
5-
[![level badge][level-badge]](https://github.com/level/awesome)
5+
[![level badge][level-badge]][awesome]
66
[![npm](https://img.shields.io/npm/v/level-js.svg)](https://www.npmjs.com/package/level-js)
77
[![npm next](https://img.shields.io/npm/v/level-js/next.svg)](https://www.npmjs.com/package/level-js)
88
[![Travis](https://secure.travis-ci.org/Level/level-js.svg?branch=master)](http://travis-ci.org/Level/level-js)
99
[![npm](https://img.shields.io/npm/dm/level-js.svg)](https://www.npmjs.com/package/level-js)
1010
[![JavaScript Style Guide](https://img.shields.io/badge/code_style-standard-brightgreen.svg)](https://standardjs.com)
1111

12+
## Table of Contents
13+
14+
<details><summary>Click to expand</summary>
15+
16+
- [Background](#background)
17+
- [Example](#example)
18+
- [Browser Support](#browser-support)
19+
- [Type Support](#type-support)
20+
- [Install](#install)
21+
- [API](#api)
22+
- [Running Tests](#running-tests)
23+
- [Big Thanks](#big-thanks)
24+
- [License](#license)
25+
26+
</details>
27+
1228
## Background
1329

1430
Here are the goals of `level-js`:
1531

1632
- Store large amounts of data in modern browsers
17-
- Pass the full `abstract-leveldown` test suite
18-
- Support [Buffer](https://nodejs.org/api/buffer.html) values (in all target environments)
19-
- Support all key types of IndexedDB Second Edition, including binary keys (depends on environment)
20-
- Support all value types of the structured clone algorithm (depends on environment) except for `null` and `undefined`
33+
- Pass the full [`abstract-leveldown`][abstract-leveldown] test suite
34+
- Support [`Buffer`][buffer] keys and values
35+
- Support all key types of IndexedDB Second Edition
36+
- Support all value types of the [structured clone algorithm][structured-clone-algorithm] except for `null` and `undefined`
2137
- Be as fast as possible
22-
- Sync with [multilevel](https://github.com/juliangruber/multilevel) over either ASCII or binary transports.
38+
- Sync with [multilevel](https://github.com/juliangruber/multilevel) over ASCII or binary transports.
2339

24-
Being `abstract-leveldown` compliant means you can use many of the [Level modules](https://github.com/Level/awesome/) on top of this library. For some demos of it working, see @brycebaril's presentation [Path of the NodeBases Jedi](http://brycebaril.github.io/nodebase_jedi/#/vanilla).
40+
Being `abstract-leveldown` compliant means you can use many of the [Level modules][awesome] on top of this library. For some demos of it working, see @brycebaril's presentation [Path of the NodeBases Jedi](http://brycebaril.github.io/nodebase_jedi/#/vanilla).
2541

2642
## Example
2743

28-
**This assumes use of version `3.0.0-rc1`. The next release will have an upgrade guide. Until then, please see the [changelog](CHANGELOG.md).**
44+
**If you are upgrading:** please see [UPGRADING.md](UPGRADING.md).
2945

3046
```js
3147
var levelup = require('levelup')
@@ -43,10 +59,104 @@ db.put('hello', Buffer.from('world'), function (err) {
4359
})
4460
```
4561

62+
In ES6 browsers:
63+
64+
```js
65+
const levelup = require('levelup')
66+
const leveljs = require('level-js')
67+
const db = levelup(leveljs('bigdata'))
68+
69+
await db.put('hello', Buffer.from('world'))
70+
const value = await db.get('hello')
71+
```
72+
4673
## Browser Support
4774

4875
[![Sauce Test Status](https://saucelabs.com/browser-matrix/level-js.svg)](https://saucelabs.com/u/level-js)
4976

77+
## Type Support
78+
79+
Unlike [`leveldown`][leveldown], `level-js` does not stringify keys or values. This means that in addition to strings and Buffers you can store almost any JavaScript type without the need for [`encoding-down`][encoding-down].
80+
81+
### Values
82+
83+
All value types of the [structured clone algorithm][structured-clone-algorithm] are supported except for `null` and `undefined`. Depending on the environment, this includes:
84+
85+
- Number, including `NaN`, `Infinity` and `-Infinity`
86+
- String, Boolean, Date, RegExp, Array, Object
87+
- ArrayBuffer or a view thereof (typed arrays);
88+
- Map, Set, Blob, File, FileList, ImageData (limited support).
89+
90+
In addition `level-js` stores [`Buffer`][buffer] values without transformation. This works in all target environments because `Buffer` is a subclass of `Uint8Array`, meaning such values can be passed to `IndexedDB` as-is.
91+
92+
When getting or iterating binary values, regardless of whether they were stored as a `Buffer`, `ArrayBuffer` or a view thereof, values will return as a `Buffer`. This behavior can be disabled, in which case `ArrayBuffer` returns as `ArrayBuffer`, typed arrays return as typed arrays and `Buffer` returns as `Uint8Array`:
93+
94+
```js
95+
db.get('key', { asBuffer: false })
96+
db.iterator({ valueAsBuffer: false })
97+
```
98+
99+
If the environment does not support a type, it will throw an error which `level-js` catches and passes to the callbacks of `put` or `batch`. For example, IE does not support typed array values. At the time of writing, Chrome is the only browser that supports all types listed above.
100+
101+
Due to the special meaning that `null` and `undefined` have in `abstract-leveldown` iterators and Node.js streams, values of this type are converted to empty strings prior to storage.
102+
103+
### Keys
104+
105+
All key types of IndexedDB Second Edition are supported. Depending on the environment, this includes:
106+
107+
- Number, including `Infinity` and `-Infinity`, but not `NaN`
108+
- Date, except invalid (`NaN`)
109+
- String
110+
- ArrayBuffer or a view thereof (typed arrays);
111+
- Array, except cyclical, empty and sparse arrays. Elements must be valid types themselves.
112+
113+
In addition you can use [`Buffer`][buffer] keys, giving `level-js` the same power as implementations like `leveldown` and `memdown`. When iterating binary keys, regardless of whether they were stored as `Buffer`, `ArrayBuffer` or a view thereof, keys will return as a `Buffer`. This behavior can be disabled, in which case binary keys will always return as `ArrayBuffer`:
114+
115+
```js
116+
db.iterator({ keyAsBuffer: false })
117+
```
118+
119+
Note that this behavior is slightly different from values due to the way that IndexedDB works. IndexedDB stores binary _values_ using the structured clone algorithm, which preserves views, but it stores binary _keys_ as an array of octets, so that it is able to compare and sort differently typed keys.
120+
121+
If the environment does not support a type, it will throw an error which `level-js` catches and passes to the callbacks of `get`, `put`, `del`, `batch` or an iterator. Exceptions are:
122+
123+
- `null` and `undefined`: rejected early by `abstract-leveldown`
124+
- Boolean and `NaN`: though invalid per the IndexedDB specification, they are converted to strings for `abstract-leveldown` compatibility;
125+
- Binary and array keys: if not supported by the environment, `level-js` falls back to `String(key)`.
126+
127+
### Normalization
128+
129+
If you desire normalization for keys and values (e.g. to stringify numbers), wrap `level-js` with [`encoding-down`][encoding-down]. Alternatively install [`level-browserify`][level-browserify] which conveniently bundles [`levelup`][levelup], `level-js` and `encoding-down`. Such an approach is also recommended if you want to achieve universal (isomorphic) behavior or to smooth over type differences between browsers. For example, you could have [`leveldown`][leveldown] in a backend and `level-js` in the frontend.
130+
131+
Another reason you might want to use `encoding-down` is that the structured clone algorithm, while rich in types, can be slower than `JSON.stringify`.
132+
133+
### Buffer vs ArrayBuffer
134+
135+
For interoperability it is recommended to use `Buffer` as your binary type. While we recognize that Node.js core modules are moving towards supporting `ArrayBuffer` and views thereof, `Buffer` remains the primary binary type in the Level ecosystem.
136+
137+
That said: if you want to `put()` an `ArrayBuffer` you can! Just know that it will come back as a `Buffer` by default. If you want to `get()` or iterate stored `ArrayBuffer` data as an `ArrayBuffer`, you have a few options. Without `encoding-down`:
138+
139+
```js
140+
const db = levelup(leveljs('mydb'))
141+
142+
// Yields an ArrayBuffer, Buffer and ArrayBuffer
143+
const value1 = await db.get('key', { asBuffer: false })
144+
const value2 = await db.get('key')
145+
const value3 = value2.buffer
146+
```
147+
148+
With `encoding-down` (or `level-browserify`) you can use the `id` encoding to selectively bypass encodings:
149+
150+
```js
151+
const encode = require('encoding-down')
152+
const db = levelup(encode(leveljs('mydb'), { valueEncoding: 'binary' }))
153+
154+
// Yields an ArrayBuffer, Buffer and ArrayBuffer
155+
const value1 = await db.get('key', { valueEncoding: 'id' })
156+
const value2 = await db.get('key')
157+
const value3 = value2.buffer
158+
```
159+
50160
## Install
51161

52162
```bash
@@ -95,3 +205,23 @@ Cross-browser Testing Platform and Open Source ♥ Provided by [Sauce Labs](http
95205
[MIT](./LICENSE.md) © 2012-present [Max Ogden](https://github.com/maxogden) and [Contributors](./CONTRIBUTORS.md).
96206

97207
[level-badge]: http://leveldb.org/img/badge.svg
208+
209+
[indexeddb]: https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API
210+
211+
[leveldb]: https://github.com/google/leveldb
212+
213+
[buffer]: https://nodejs.org/api/buffer.html
214+
215+
[awesome]: https://github.com/Level/awesome
216+
217+
[abstract-leveldown]: https://github.com/Level/abstract-leveldown
218+
219+
[levelup]: https://github.com/Level/levelup
220+
221+
[leveldown]: https://github.com/Level/leveldown
222+
223+
[level-browserify]: https://github.com/Level/level-browserify
224+
225+
[encoding-down]: https://github.com/Level/encoding-down
226+
227+
[structured-clone-algorithm]: https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm

Diff for: UPGRADING.md

+93
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
# Upgrade Guide
2+
3+
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].
4+
5+
## V3
6+
7+
This release brings `level-js` up to par with latest [`levelup`][levelup] (v2), [`abstract-leveldown`][abstract-leveldown] (v5) and IndexedDB Second Edition. It targets modern `browserify` preferring [`Buffer`][buffer] over `ArrayBuffer`. Lastly, [`IDBWrapper`][idbwrapper] has been replaced with straight IndexedDB code.
8+
9+
### Usage with [`levelup`][levelup]
10+
11+
Usage has changed to:
12+
13+
```js
14+
const levelup = require('levelup')
15+
const leveljs = require('leveljs')
16+
17+
const db = levelup(leveljs('mydb'))
18+
```
19+
20+
From the old:
21+
22+
```js
23+
const db = levelup('mydb', { db: leveljs })
24+
```
25+
26+
Friendly reminder: encodings have moved from [`levelup`][levelup] to [`encoding-down`][encoding-down]. To get identical functionality to `levelup < 2` please use the [`level-browserify`][level-browserify] convenience package or wrap `level-js` with `encoding-down`:
27+
28+
```js
29+
const encode = require('encoding-down')
30+
const db = levelup(encode(leveljs('mydb')))
31+
```
32+
33+
### New database prefix
34+
35+
The default prefix of the [`IDBDatabase`][idbdatabase] name has changed from `IDBWrapper-` to `level-js-`. To access databases created using `level-js < 3`, pass a custom prefix to the `level-js` constructor:
36+
37+
```js
38+
const db = levelup(leveljs('mydb', { prefix: 'IDBWrapper-' }))
39+
```
40+
41+
### Browser support
42+
43+
As a result of removing [`IDBWrapper`][idbwrapper], only modern browsers with a non-prefixed `window.indexedDB` are supported in this release. The current test matrix of `level-js` includes the latest versions of Chrome, Firefox, Safari, Edge and IE.
44+
45+
:fire: Internet Explorer 10 is no longer supported.
46+
47+
### Type support
48+
49+
All value types of the [structured clone algorithm][structured-clone-algorithm] and all key types of IndexedDB Second Edition are now supported. This means you can store almost any JavaScript type without the need for [`encoding-down`][encoding-down]. In addition, you can use [`Buffer`][buffer] for both keys and values. For details and caveats please see the [readme][readme].
50+
51+
### No backpressure
52+
53+
In `level-js`, iterators are powered by IndexedDB cursors. To fulfill [`abstract-leveldown`][abstract-leveldown] snapshot guarantees (reads not being affected by simultaneous writes) cursors are started immediately and continuously read from, filling an in-memory cache.
54+
55+
Though `level-js` now passes the full [`abstract-leveldown`][abstract-leveldown] test suite, fulfilling the snapshot guarantee means a loss of backpressure. Memory consumption might increase if an iterator is not consumed fast enough. A future release will have an option to favor backpressure over snapshot guarantees.
56+
57+
### Removed `raw` option
58+
59+
Because `level-js` no longer stringifies values, the `raw` option (which bypassed conversion) became unnecessary and has been removed. If you use [`level-browserify`][level-browserify] or [`levelup`][levelup] with [`encoding-down`][encoding-down], you can store and retrieve raw values (as returned by IndexedDB) using the `id` encoding. Please refer to the [readme][readme] for an example.
60+
61+
### New `destroy()` function signature
62+
63+
Previously, a `level-js` instance could be passed to `destroy()`:
64+
65+
```js
66+
leveljs.destroy(db, callback)
67+
```
68+
69+
This was useful to destroy a database that used a custom prefix. The new signature is `destroy(location[, prefix], callback)`.
70+
71+
### Strict `.batch(array)`
72+
73+
The upgrade to [`abstract-leveldown`][abstract-leveldown] comes with a [breaking change](https://github.com/Level/abstract-leveldown/commit/a2621ad70571f6ade9d2be42632ece042e068805) for the array version of `.batch()`. This change ensures all elements in the batch array are objects. If you previously passed arrays to `.batch()` that contained `undefined` or `null`, they would be silently ignored. Now this will produce an error.
74+
75+
[readme]: README.md
76+
77+
[changelog]: CHANGELOG.md
78+
79+
[buffer]: https://nodejs.org/api/buffer.html
80+
81+
[idbwrapper]: https://www.npmjs.com/package/idb-wrapper
82+
83+
[abstract-leveldown]: https://github.com/Level/abstract-leveldown
84+
85+
[levelup]: https://github.com/Level/levelup
86+
87+
[encoding-down]: https://github.com/Level/encoding-down
88+
89+
[level-browserify]: https://github.com/Level/level-browserify
90+
91+
[idbdatabase]: https://developer.mozilla.org/en-US/docs/Web/API/IDBDatabase
92+
93+
[structured-clone-algorithm]: https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm

Diff for: package.json

+13-2
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,15 @@
88
"scripts": {
99
"test": "standard && airtap --local --no-coverage test/index.js",
1010
"test-browsers": "standard && airtap --sauce-connect --loopback airtap.local --no-coverage test/index.js",
11-
"remark": "remark README.md CONTRIBUTORS.md -o"
11+
"remark": "remark README.md CONTRIBUTORS.md UPGRADING.md -o"
1212
},
1313
"files": [
1414
"index.js",
1515
"iterator.js",
1616
"util",
1717
"CONTRIBUTORS.md",
1818
"CHANGELOG.md",
19+
"UPGRADING.md",
1920
"sauce-labs.svg"
2021
],
2122
"browser": {
@@ -38,13 +39,23 @@
3839
"buffer": "~5.1.0",
3940
"level-community": "~3.0.0",
4041
"remark-cli": "^5.0.0",
42+
"remark-collapse": "~0.1.2",
4143
"remark-git-contributors": "~0.2.0",
44+
"remark-toc": "~5.0.0",
4245
"standard": "^11.0.1",
4346
"tape": "^4.0.0"
4447
},
4548
"remarkConfig": {
4649
"plugins": {
47-
"remark-git-contributors": "level-community"
50+
"remark-git-contributors": "level-community",
51+
"remark-toc": {
52+
"maxDepth": 2,
53+
"tight": true
54+
},
55+
"remark-collapse": {
56+
"test": "Table of Contents",
57+
"summary": "Click to expand"
58+
}
4859
}
4960
},
5061
"repository": {

0 commit comments

Comments
 (0)