Comparing version 3.0.0-rc1 to 3.0.0
80
index.js
@@ -0,1 +1,3 @@ | ||
/* global indexedDB */ | ||
'use strict' | ||
@@ -6,6 +8,5 @@ | ||
var AbstractLevelDOWN = require('abstract-leveldown').AbstractLevelDOWN | ||
var util = require('util') | ||
var inherits = require('inherits') | ||
var Iterator = require('./iterator') | ||
var mixedToBuffer = require('./util/mixed-to-buffer') | ||
var isDataCloneError = require('./util/is-data-clone-error') | ||
var setImmediate = require('./util/immediate') | ||
@@ -25,3 +26,3 @@ var support = require('./util/support') | ||
util.inherits(Level, AbstractLevelDOWN) | ||
inherits(Level, AbstractLevelDOWN) | ||
@@ -74,3 +75,13 @@ // Detect binary and array key support (IndexedDB Second Edition) | ||
Level.prototype._get = function (key, options, callback) { | ||
this.await(this.store('readonly').get(key), function (err, value) { | ||
var store = this.store('readonly') | ||
try { | ||
var req = store.get(key) | ||
} catch (err) { | ||
return setImmediate(function () { | ||
callback(err) | ||
}) | ||
} | ||
this.await(req, function (err, value) { | ||
if (err) return callback(err) | ||
@@ -91,4 +102,14 @@ | ||
Level.prototype._del = function(key, options, callback) { | ||
this.await(this.store('readwrite').delete(key), callback) | ||
Level.prototype._del = function (key, options, callback) { | ||
var store = this.store('readwrite') | ||
try { | ||
var req = store.delete(key) | ||
} catch (err) { | ||
return setImmediate(function () { | ||
callback(err) | ||
}) | ||
} | ||
this.await(req, callback) | ||
} | ||
@@ -100,10 +121,6 @@ | ||
try { | ||
// Will throw a DataCloneError if the environment | ||
// does not support serializing the key or value. | ||
// Will throw a DataError or DataCloneError if the environment | ||
// does not support serializing the key or value respectively. | ||
var req = store.put(value, key) | ||
} catch (err) { | ||
if (!isDataCloneError(err)) { | ||
throw err | ||
} | ||
return setImmediate(function () { | ||
@@ -122,4 +139,4 @@ callback(err) | ||
// - String | ||
// - ArrayBuffer or a view thereof (typed arrays). In level-js we only support | ||
// Buffer (which is an Uint8Array). | ||
// - ArrayBuffer or a view thereof (typed arrays). In level-js we also support | ||
// Buffer (which is an Uint8Array) (and the primary binary type of Level). | ||
// - Array, except cyclical and empty (e.g. Array(10)). Elements must be valid | ||
@@ -132,7 +149,9 @@ // types themselves. | ||
return Level.arrayKeys ? key.map(this._serializeKey, this) : String(key) | ||
} else if ((typeof key === 'number' || key instanceof Date) && !isNaN(key)) { | ||
} else if (typeof key === 'boolean' || (typeof key === 'number' && isNaN(key))) { | ||
// These types are invalid per the IndexedDB spec and ideally we'd treat | ||
// them that way, but they're valid per the current abstract test suite. | ||
return String(key) | ||
} else { | ||
return key | ||
} | ||
return String(key) | ||
} | ||
@@ -154,5 +173,6 @@ | ||
var index = 0 | ||
var error | ||
transaction.onabort = function () { | ||
callback(transaction.error || new Error('aborted by user')) | ||
callback(error || transaction.error || new Error('aborted by user')) | ||
} | ||
@@ -168,4 +188,11 @@ | ||
var key = op.key | ||
var req = op.type === 'del' ? store.delete(key) : store.put(op.value, key) | ||
try { | ||
var req = op.type === 'del' ? store.delete(key) : store.put(op.value, key) | ||
} catch (err) { | ||
error = err | ||
transaction.abort() | ||
return | ||
} | ||
if (index < operations.length) { | ||
@@ -181,20 +208,17 @@ req.onsuccess = loop | ||
this.db.close() | ||
callback() | ||
setImmediate(callback) | ||
} | ||
Level.destroy = function (db, callback) { | ||
if (typeof db === 'object') { | ||
var prefix = db.prefix || DEFAULT_PREFIX | ||
var location = db.location | ||
} else { | ||
Level.destroy = function (location, prefix, callback) { | ||
if (typeof prefix === 'function') { | ||
callback = prefix | ||
prefix = DEFAULT_PREFIX | ||
location = db | ||
} | ||
var request = indexedDB.deleteDatabase(prefix + location) | ||
request.onsuccess = function() { | ||
request.onsuccess = function () { | ||
callback() | ||
} | ||
request.onerror = function(err) { | ||
request.onerror = function (err) { | ||
callback(err) | ||
} | ||
} |
@@ -0,5 +1,7 @@ | ||
/* global IDBKeyRange */ | ||
'use strict' | ||
var util = require('util') | ||
var AbstractIterator = require('abstract-leveldown').AbstractIterator | ||
var inherits = require('inherits') | ||
var AbstractIterator = require('abstract-leveldown').AbstractIterator | ||
var ltgt = require('ltgt') | ||
@@ -44,3 +46,3 @@ var mixedToBuffer = require('./util/mixed-to-buffer') | ||
util.inherits(Iterator, AbstractIterator) | ||
inherits(Iterator, AbstractIterator) | ||
@@ -121,3 +123,3 @@ Iterator.prototype.createKeyRange = function (options) { | ||
setImmediate(function() { | ||
setImmediate(function () { | ||
callback(err) | ||
@@ -132,3 +134,3 @@ }) | ||
setImmediate(function() { | ||
setImmediate(function () { | ||
callback(null, key, value) | ||
@@ -135,0 +137,0 @@ }) |
# The MIT License (MIT) | ||
## Copyright (c) 2012-2018 `level.js` contributors | ||
**Copyright © 2012-present [Max Ogden](https://github.com/maxogden) and [Contributors](./CONTRIBUTORS.md).** | ||
*`level.js` contributors listed at <https://github.com/level/community#contributors>* | ||
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: | ||
@@ -8,0 +6,0 @@ |
{ | ||
"name": "level-js", | ||
"version": "3.0.0-rc1", | ||
"description": "leveldown/leveldb library for browsers using IndexedDB", | ||
"version": "3.0.0", | ||
"description": "An abstract-leveldown compliant store on top of IndexedDB", | ||
"author": "max ogden", | ||
"license": "MIT", | ||
"main": "index.js", | ||
"scripts": { | ||
"test": "airtap --local --no-coverage test/index.js", | ||
"test-browsers": "airtap --sauce-connect --loopback airtap.local --no-coverage test/index.js" | ||
"test": "standard && airtap --local --no-coverage test/index.js", | ||
"test-browsers": "standard && airtap --sauce-connect --loopback airtap.local --no-coverage test/index.js", | ||
"remark": "remark README.md CONTRIBUTORS.md CHANGELOG.md UPGRADING.md -o" | ||
}, | ||
"repository": { | ||
"type": "git", | ||
"url": "git@github.com:Level/level.js.git" | ||
}, | ||
"keywords": [ | ||
"level", | ||
"leveldb" | ||
"files": [ | ||
"index.js", | ||
"iterator.js", | ||
"util", | ||
"CONTRIBUTORS.md", | ||
"CHANGELOG.md", | ||
"UPGRADING.md", | ||
"sauce-labs.svg" | ||
], | ||
"author": "max ogden", | ||
"license": "MIT", | ||
"devDependencies": { | ||
"airtap": "0.0.7", | ||
"browserify": "~16.2.2", | ||
"encoding-down": "~5.0.2", | ||
"levelup": "~3.0.0", | ||
"pinkie": "~2.0.4", | ||
"tape": "^4.0.0" | ||
"browser": { | ||
"./util/immediate.js": "./util/immediate-browser.js" | ||
}, | ||
"standard": { | ||
"ignore": [ | ||
"test/util/idb-shim.js" | ||
] | ||
}, | ||
"dependencies": { | ||
"abstract-leveldown": "~5.0.0", | ||
"immediate": "~3.2.3", | ||
"inherits": "^2.0.3", | ||
"ltgt": "^2.1.2", | ||
"typedarray-to-buffer": "~3.1.5" | ||
}, | ||
"browser": { | ||
"./util/immediate.js": "./util/immediate-browser.js" | ||
} | ||
"devDependencies": { | ||
"airtap": "0.0.7", | ||
"buffer": "~5.1.0", | ||
"level-community": "~3.0.0", | ||
"remark-cli": "^5.0.0", | ||
"remark-collapse": "~0.1.2", | ||
"remark-git-contributors": "~0.2.1", | ||
"remark-github": "~7.0.3", | ||
"remark-toc": "~5.0.0", | ||
"standard": "^11.0.1", | ||
"tape": "^4.0.0" | ||
}, | ||
"remarkConfig": { | ||
"plugins": [ | ||
[ | ||
"remark-git-contributors", | ||
"level-community" | ||
], | ||
[ | ||
"remark-github" | ||
], | ||
[ | ||
"remark-toc", | ||
{ | ||
"maxDepth": 2, | ||
"tight": true | ||
} | ||
], | ||
[ | ||
"remark-collapse", | ||
{ | ||
"test": "Table of Contents", | ||
"summary": "Click to expand" | ||
} | ||
] | ||
] | ||
}, | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/Level/level-js.git" | ||
}, | ||
"keywords": [ | ||
"level", | ||
"leveldb", | ||
"indexeddb", | ||
"abstract-leveldown" | ||
] | ||
} |
184
README.md
# level-js | ||
> 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. | ||
> 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. | ||
[![level badge][level-badge]](https://github.com/level/awesome) | ||
[![level badge][level-badge]][awesome] | ||
[![npm](https://img.shields.io/npm/v/level-js.svg)](https://www.npmjs.com/package/level-js) | ||
[![npm next](https://img.shields.io/npm/v/level-js/next.svg)](https://www.npmjs.com/package/level-js) | ||
[![Travis](https://secure.travis-ci.org/Level/level.js.svg?branch=master)](http://travis-ci.org/Level/level.js) | ||
[![Travis](https://secure.travis-ci.org/Level/level-js.svg?branch=master)](http://travis-ci.org/Level/level-js) | ||
[![npm](https://img.shields.io/npm/dm/level-js.svg)](https://www.npmjs.com/package/level-js) | ||
[![JavaScript Style Guide](https://img.shields.io/badge/code_style-standard-brightgreen.svg)](https://standardjs.com) | ||
## Table of Contents | ||
<details><summary>Click to expand</summary> | ||
- [Background](#background) | ||
- [Example](#example) | ||
- [Browser Support](#browser-support) | ||
- [Type Support](#type-support) | ||
- [Install](#install) | ||
- [API](#api) | ||
- [Running Tests](#running-tests) | ||
- [Big Thanks](#big-thanks) | ||
- [License](#license) | ||
</details> | ||
## Background | ||
@@ -15,15 +31,15 @@ | ||
- Store large amounts of data in modern browsers | ||
- Pass the full `abstract-leveldown` test suite | ||
- Support [Buffer](https://nodejs.org/api/buffer.html) values (in all target environments) | ||
- Support all key types of IndexedDB Second Edition, including binary keys (depends on environment) | ||
- Support all value types of the structured clone algorithm (depends on environment) | ||
- Be as fast as possible | ||
- Sync with [multilevel](https://github.com/juliangruber/multilevel) over either ASCII or binary transports. | ||
- Store large amounts of data in modern browsers | ||
- Pass the full [`abstract-leveldown`][abstract-leveldown] test suite | ||
- Support [`Buffer`][buffer] keys and values | ||
- Support all key types of IndexedDB Second Edition | ||
- Support all value types of the [structured clone algorithm][structured-clone-algorithm] except for `null` and `undefined` | ||
- Be as fast as possible | ||
- Sync with [multilevel](https://github.com/juliangruber/multilevel) over ASCII or binary transports. | ||
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). | ||
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**](https://github.com/brycebaril)'s presentation [Path of the NodeBases Jedi](http://brycebaril.github.io/nodebase_jedi/#/vanilla). | ||
## Example | ||
**This assumes use of version `3.0.0-rc1`. The next release will have an upgrade guide.** | ||
**If you are upgrading:** please see [UPGRADING.md](UPGRADING.md). | ||
@@ -46,2 +62,13 @@ ```js | ||
In ES6 browsers: | ||
```js | ||
const levelup = require('levelup') | ||
const leveljs = require('level-js') | ||
const db = levelup(leveljs('bigdata')) | ||
await db.put('hello', Buffer.from('world')) | ||
const value = await db.get('hello') | ||
``` | ||
## Browser Support | ||
@@ -51,7 +78,91 @@ | ||
## Type Support | ||
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]. | ||
### Values | ||
All value types of the [structured clone algorithm][structured-clone-algorithm] are supported except for `null` and `undefined`. Depending on the environment, this includes: | ||
- Number, including `NaN`, `Infinity` and `-Infinity` | ||
- String, Boolean, Date, RegExp, Array, Object | ||
- ArrayBuffer or a view thereof (typed arrays); | ||
- Map, Set, Blob, File, FileList, ImageData (limited support). | ||
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. | ||
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`: | ||
```js | ||
db.get('key', { asBuffer: false }) | ||
db.iterator({ valueAsBuffer: false }) | ||
``` | ||
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. | ||
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. | ||
### Keys | ||
All key types of IndexedDB Second Edition are supported. Depending on the environment, this includes: | ||
- Number, including `Infinity` and `-Infinity`, but not `NaN` | ||
- Date, except invalid (`NaN`) | ||
- String | ||
- ArrayBuffer or a view thereof (typed arrays); | ||
- Array, except cyclical, empty and sparse arrays. Elements must be valid types themselves. | ||
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`: | ||
```js | ||
db.iterator({ keyAsBuffer: false }) | ||
``` | ||
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. | ||
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: | ||
- `null` and `undefined`: rejected early by `abstract-leveldown` | ||
- Boolean and `NaN`: though invalid per the IndexedDB specification, they are converted to strings for `abstract-leveldown` compatibility; | ||
- Binary and array keys: if not supported by the environment, `level-js` falls back to `String(key)`. | ||
### Normalization | ||
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. | ||
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`. | ||
### Buffer vs ArrayBuffer | ||
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. | ||
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`: | ||
```js | ||
const db = levelup(leveljs('mydb')) | ||
// Yields an ArrayBuffer, Buffer and ArrayBuffer | ||
const value1 = await db.get('key', { asBuffer: false }) | ||
const value2 = await db.get('key') | ||
const value3 = value2.buffer | ||
``` | ||
With `encoding-down` (or `level-browserify`) you can use the `id` encoding to selectively bypass encodings: | ||
```js | ||
const encode = require('encoding-down') | ||
const db = levelup(encode(leveljs('mydb'), { valueEncoding: 'binary' })) | ||
// Yields an ArrayBuffer, Buffer and ArrayBuffer | ||
const value1 = await db.get('key', { valueEncoding: 'id' }) | ||
const value2 = await db.get('key') | ||
const value3 = value2.buffer | ||
``` | ||
## Install | ||
With [npm](https://npmjs.org) do: | ||
```bash | ||
npm install level-js # Stable | ||
npm install level-js@next # Bleeding edge | ||
npm install level-js | ||
``` | ||
@@ -63,7 +174,22 @@ | ||
## API | ||
### `db = leveljs(location[, options])` | ||
Returns a new `leveljs` instance. `location` is the string name of the [`IDBDatabase`](https://developer.mozilla.org/en-US/docs/Web/API/IDBDatabase) to be opened, as well as the object store within that database. The database name will be prefixed with `options.prefix`. | ||
#### `options` | ||
The optional `options` argument may contain: | ||
- `prefix` _(string, default: `'level-js-'`)_: Prefix for `IDBDatabase` name. | ||
- `version` _(string | number, default: `1`)_: The version to open the database with. | ||
See [`IDBFactory#open`](https://developer.mozilla.org/en-US/docs/Web/API/IDBFactory/open) for more details. | ||
## Running Tests | ||
```sh | ||
git clone git@github.com:Level/level.js.git | ||
cd level.js | ||
git clone git@github.com:Level/level-js.git | ||
cd level-js | ||
npm install | ||
@@ -83,6 +209,24 @@ npm test | ||
Copyright (c) 2012-2018 `level.js` [contributors](https://github.com/level/community#contributors). | ||
[MIT](./LICENSE.md) © 2012-present [Max Ogden](https://github.com/maxogden) and [Contributors](./CONTRIBUTORS.md). | ||
`level.js` is licensed under the MIT license. All rights not explicitly granted in the MIT license are reserved. See the included `LICENSE.md` file for more details. | ||
[level-badge]: http://leveldb.org/img/badge.svg | ||
[level-badge]: http://leveldb.org/img/badge.svg | ||
[indexeddb]: https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API | ||
[leveldb]: https://github.com/google/leveldb | ||
[buffer]: https://nodejs.org/api/buffer.html | ||
[awesome]: https://github.com/Level/awesome | ||
[abstract-leveldown]: https://github.com/Level/abstract-leveldown | ||
[levelup]: https://github.com/Level/levelup | ||
[leveldown]: https://github.com/Level/leveldown | ||
[level-browserify]: https://github.com/Level/level-browserify | ||
[encoding-down]: https://github.com/Level/encoding-down | ||
[structured-clone-algorithm]: https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm |
@@ -7,3 +7,4 @@ 'use strict' | ||
if (value instanceof Uint8Array) return toBuffer(value) | ||
else if (value instanceof ArrayBuffer) return Buffer.from(value) | ||
else return Buffer.from(String(value)) | ||
} |
'use strict' | ||
exports.binaryKeys = function (impl) { | ||
try { | ||
impl.cmp(new Uint8Array(0), 0) | ||
return true | ||
} catch (err) { | ||
return false | ||
exports.test = function (key) { | ||
return function test (impl) { | ||
try { | ||
impl.cmp(key, 0) | ||
return true | ||
} catch (err) { | ||
return false | ||
} | ||
} | ||
} | ||
exports.arrayKeys = function (impl) { | ||
try { | ||
impl.cmp([1], 0) | ||
return true | ||
} catch (err) { | ||
return false | ||
} | ||
} | ||
exports.binaryKeys = exports.test(new Uint8Array(0)) | ||
exports.arrayKeys = exports.test([1]) |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
1
228
1
57422
5
10
13
322
+ Addedinherits@^2.0.3
+ Addedinherits@2.0.4(transitive)