Socket
Socket
Sign inDemoInstall

abstract-leveldown

Package Overview
Dependencies
Maintainers
4
Versions
79
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

abstract-leveldown - npm Package Compare versions

Comparing version 5.0.0 to 6.0.0

CONTRIBUTORS.md

51

abstract-chained-batch.js

@@ -1,5 +0,7 @@

/* Copyright (c) 2017 Rod Vagg, MIT License */
function AbstractChainedBatch (db) {
if (typeof db !== 'object' || db === null) {
throw new TypeError('First argument must be an abstract-leveldown compliant store')
}
function AbstractChainedBatch (db) {
this._db = db
this.db = db
this._operations = []

@@ -9,10 +11,2 @@ this._written = false

AbstractChainedBatch.prototype._serializeKey = function (key) {
return this._db._serializeKey(key)
}
AbstractChainedBatch.prototype._serializeValue = function (value) {
return this._db._serializeValue(value)
}
AbstractChainedBatch.prototype._checkWritten = function () {

@@ -27,7 +21,7 @@ if (this._written) {

var err = this._db._checkKey(key, 'key')
if (err) { throw err }
var err = this.db._checkKey(key) || this.db._checkValue(value)
if (err) throw err
key = this._serializeKey(key)
value = this._serializeValue(value)
key = this.db._serializeKey(key)
value = this.db._serializeValue(value)

@@ -46,6 +40,6 @@ this._put(key, value)

var err = this._db._checkKey(key, 'key')
if (err) { throw err }
var err = this.db._checkKey(key)
if (err) throw err
key = this._serializeKey(key)
key = this.db._serializeKey(key)
this._del(key)

@@ -62,3 +56,2 @@

this._checkWritten()
this._operations = []
this._clear()

@@ -69,3 +62,5 @@

AbstractChainedBatch.prototype._clear = function noop () {}
AbstractChainedBatch.prototype._clear = function () {
this._operations = []
}

@@ -79,16 +74,14 @@ AbstractChainedBatch.prototype.write = function (options, callback) {

}
if (typeof options !== 'object') { options = {} }
if (typeof options !== 'object' || options === null) {
options = {}
}
this._written = true
this._write(options, callback)
}
// @ts-ignore
if (typeof this._write === 'function') { return this._write(callback) }
if (typeof this._db._batch === 'function') {
return this._db._batch(this._operations, options, callback)
}
process.nextTick(callback)
AbstractChainedBatch.prototype._write = function (options, callback) {
this.db._batch(this._operations, options, callback)
}
module.exports = AbstractChainedBatch

@@ -1,4 +0,6 @@

/* Copyright (c) 2017 Rod Vagg, MIT License */
function AbstractIterator (db) {
if (typeof db !== 'object' || db === null) {
throw new TypeError('First argument must be an abstract-leveldown compliant store')
}
function AbstractIterator (db) {
this.db = db

@@ -39,2 +41,16 @@ this._ended = false

AbstractIterator.prototype.seek = function (target) {
if (this._ended) {
throw new Error('cannot call seek() after end()')
}
if (this._nexting) {
throw new Error('cannot call seek() before next() has completed')
}
target = this.db._serializeKey(target)
this._seek(target)
}
AbstractIterator.prototype._seek = function (target) {}
AbstractIterator.prototype.end = function (callback) {

@@ -41,0 +57,0 @@ if (typeof callback !== 'function') {

@@ -1,3 +0,1 @@

/* Copyright (c) 2017 Rod Vagg, MIT License */
var xtend = require('xtend')

@@ -9,12 +7,3 @@ var AbstractIterator = require('./abstract-iterator')

function AbstractLevelDOWN (location) {
if (!arguments.length || location === undefined) {
throw new Error('constructor requires at least a location argument')
}
if (typeof location !== 'string') {
throw new Error('constructor requires a location string argument')
}
this.location = location
function AbstractLevelDOWN () {
this.status = 'new'

@@ -27,3 +16,3 @@ }

if (typeof options === 'function') { callback = options }
if (typeof options === 'function') callback = options

@@ -34,3 +23,3 @@ if (typeof callback !== 'function') {

if (typeof options !== 'object') { options = {} }
if (typeof options !== 'object' || options === null) options = {}

@@ -79,3 +68,3 @@ options.createIfMissing = options.createIfMissing !== false

AbstractLevelDOWN.prototype.get = function (key, options, callback) {
if (typeof options === 'function') { callback = options }
if (typeof options === 'function') callback = options

@@ -86,3 +75,3 @@ if (typeof callback !== 'function') {

var err = this._checkKey(key, 'key')
var err = this._checkKey(key)
if (err) return process.nextTick(callback, err)

@@ -92,3 +81,3 @@

if (typeof options !== 'object') { options = {} }
if (typeof options !== 'object' || options === null) options = {}

@@ -105,3 +94,3 @@ options.asBuffer = options.asBuffer !== false

AbstractLevelDOWN.prototype.put = function (key, value, options, callback) {
if (typeof options === 'function') { callback = options }
if (typeof options === 'function') callback = options

@@ -112,3 +101,3 @@ if (typeof callback !== 'function') {

var err = this._checkKey(key, 'key')
var err = this._checkKey(key) || this._checkValue(value)
if (err) return process.nextTick(callback, err)

@@ -119,3 +108,3 @@

if (typeof options !== 'object') { options = {} }
if (typeof options !== 'object' || options === null) options = {}

@@ -130,3 +119,3 @@ this._put(key, value, options, callback)

AbstractLevelDOWN.prototype.del = function (key, options, callback) {
if (typeof options === 'function') { callback = options }
if (typeof options === 'function') callback = options

@@ -137,3 +126,3 @@ if (typeof callback !== 'function') {

var err = this._checkKey(key, 'key')
var err = this._checkKey(key)
if (err) return process.nextTick(callback, err)

@@ -143,3 +132,3 @@

if (typeof options !== 'object') { options = {} }
if (typeof options !== 'object' || options === null) options = {}

@@ -154,7 +143,7 @@ this._del(key, options, callback)

AbstractLevelDOWN.prototype.batch = function (array, options, callback) {
if (!arguments.length) { return this._chainedBatch() }
if (!arguments.length) return this._chainedBatch()
if (typeof options === 'function') { callback = options }
if (typeof options === 'function') callback = options
if (typeof array === 'function') { callback = array }
if (typeof array === 'function') callback = array

@@ -169,3 +158,3 @@ if (typeof callback !== 'function') {

if (!options || typeof options !== 'object') { options = {} }
if (typeof options !== 'object' || options === null) options = {}

@@ -185,3 +174,3 @@ var serialized = new Array(array.length)

var err = this._checkKey(e.key, 'key')
var err = this._checkKey(e.key)
if (err) return process.nextTick(callback, err)

@@ -191,4 +180,9 @@

if (e.type === 'put') { e.value = this._serializeValue(e.value) }
if (e.type === 'put') {
var valueErr = this._checkValue(e.value)
if (valueErr) return process.nextTick(callback, valueErr)
e.value = this._serializeValue(e.value)
}
serialized[i] = e

@@ -205,3 +199,3 @@ }

AbstractLevelDOWN.prototype._setupIteratorOptions = function (options) {
options = cleanRangeOptions(options)
options = cleanRangeOptions(this, options)

@@ -218,3 +212,3 @@ options.reverse = !!options.reverse

function cleanRangeOptions (options) {
function cleanRangeOptions (db, options) {
var result = {}

@@ -224,5 +218,12 @@

if (!hasOwnProperty.call(options, k)) continue
if (isRangeOption(k) && isEmptyRangeOption(options[k])) continue
result[k] = options[k]
var opt = options[k]
if (isRangeOption(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.
opt = db._serializeKey(opt)
}
result[k] = opt
}

@@ -237,12 +238,4 @@

function isEmptyRangeOption (v) {
return v === '' || v == null || isEmptyBuffer(v)
}
function isEmptyBuffer (v) {
return Buffer.isBuffer(v) && v.length === 0
}
AbstractLevelDOWN.prototype.iterator = function (options) {
if (typeof options !== 'object') { options = {} }
if (typeof options !== 'object' || options === null) options = {}
options = this._setupIteratorOptions(options)

@@ -261,24 +254,27 @@ return this._iterator(options)

AbstractLevelDOWN.prototype._serializeKey = function (key) {
return Buffer.isBuffer(key) ? key : String(key)
return key
}
AbstractLevelDOWN.prototype._serializeValue = function (value) {
if (value == null) return ''
return Buffer.isBuffer(value) || process.browser ? value : String(value)
return value
}
AbstractLevelDOWN.prototype._checkKey = function (obj, type) {
if (obj === null || obj === undefined) {
return new Error(type + ' cannot be `null` or `undefined`')
AbstractLevelDOWN.prototype._checkKey = function (key) {
if (key === null || key === undefined) {
return new Error('key cannot be `null` or `undefined`')
} else if (Buffer.isBuffer(key) && key.length === 0) {
return new Error('key cannot be an empty Buffer')
} else if (key === '') {
return new Error('key cannot be an empty String')
} else if (Array.isArray(key) && key.length === 0) {
return new Error('key cannot be an empty Array')
}
}
if (Buffer.isBuffer(obj) && obj.length === 0) {
return new Error(type + ' cannot be an empty Buffer')
AbstractLevelDOWN.prototype._checkValue = function (value) {
if (value === null || value === undefined) {
return new Error('value cannot be `null` or `undefined`')
}
if (String(obj) === '') {
return new Error(type + ' cannot be an empty String')
}
}
module.exports = AbstractLevelDOWN

@@ -5,48 +5,112 @@ # Changelog

## [5.0.0] - 2018-05-22
## [6.0.0] - 2018-10-20
_If you are upgrading, please consult the [Upgrade Guide](UPGRADING.md#v6)._
### Changed
- Upgrade `airtap` devDependency from `0.0.5` to `0.1.0` ([#229](https://github.com/level/abstract-leveldown/issues/229), [#231](https://github.com/level/abstract-leveldown/issues/231), [#245](https://github.com/level/abstract-leveldown/issues/245), [`029f56a`](https://github.com/level/abstract-leveldown/commit/029f56a), [#252](https://github.com/level/abstract-leveldown/issues/252)) ([**@vweevers**](https://github.com/vweevers), [**@ralphtheninja**](https://github.com/ralphtheninja))
- Upgrade `sinon` devDependency from `^5.0.0` to `^6.0.0` ([#232](https://github.com/level/abstract-leveldown/issues/232)) ([**@ralphtheninja**](https://github.com/ralphtheninja))
- Upgrade `standard` devDependency from `^11.0.0` to `^12.0.0` ([#303](https://github.com/level/abstract-leveldown/issues/303)) ([**@ralphtheninja**](https://github.com/ralphtheninja))
- Reject nullish values ([#277](https://github.com/level/abstract-leveldown/issues/277)) ([**@vweevers**](https://github.com/vweevers))
- Make default `_serializeKey` and `_serializeValue` identity functions ([#277](https://github.com/level/abstract-leveldown/issues/277)) ([**@vweevers**](https://github.com/vweevers))
- Don't coerce keys to strings to check if they're empty, instead check arrays explicitly ([#277](https://github.com/level/abstract-leveldown/issues/277)) ([**@vweevers**](https://github.com/vweevers))
- Make `db` property mandatory and public on iterator and chained batch ([#257](https://github.com/level/abstract-leveldown/issues/257), [#309](https://github.com/level/abstract-leveldown/issues/309)) ([**@vweevers**](https://github.com/vweevers))
- Align `AbstractChainedBatch#_clear` with `_put` and `_del` ([#257](https://github.com/level/abstract-leveldown/issues/257)) ([**@vweevers**](https://github.com/vweevers))
- Add `AbstractChainedBatch#_write` with options ([#257](https://github.com/level/abstract-leveldown/issues/257)) ([**@vweevers**](https://github.com/vweevers))
- Use `level-concat-iterator` instead of `collectEntries` ([#246](https://github.com/level/abstract-leveldown/issues/246)) ([**@ralphtheninja**](https://github.com/ralphtheninja))
- Document API and test suite ([#251](https://github.com/level/abstract-leveldown/issues/251), [#290](https://github.com/level/abstract-leveldown/issues/290), [#295](https://github.com/level/abstract-leveldown/issues/295), [#296](https://github.com/level/abstract-leveldown/issues/296), [#305](https://github.com/level/abstract-leveldown/issues/305)) ([**@vweevers**](https://github.com/vweevers))
- Export test suite as a single function ([#271](https://github.com/level/abstract-leveldown/issues/271), [#293](https://github.com/level/abstract-leveldown/issues/293), [#297](https://github.com/level/abstract-leveldown/issues/297)) ([**@vweevers**](https://github.com/vweevers), [**@ralphtheninja**](https://github.com/ralphtheninja))
- Use factory function to create `db` instances in test suite ([#258](https://github.com/level/abstract-leveldown/issues/258), [#268](https://github.com/level/abstract-leveldown/issues/268), [#282](https://github.com/level/abstract-leveldown/issues/282)) ([**@ralphtheninja**](https://github.com/ralphtheninja), [**@vweevers**](https://github.com/vweevers))
- Isolate snapshot tests so that they can be skipped ([#239](https://github.com/level/abstract-leveldown/issues/239), [#274](https://github.com/level/abstract-leveldown/issues/274)) ([**@vweevers**](https://github.com/vweevers), [**@ralphtheninja**](https://github.com/ralphtheninja))
- Isolate openAdvanced tests so that they can be skipped ([#271](https://github.com/level/abstract-leveldown/issues/271)) ([**@vweevers**](https://github.com/vweevers))
- Rename `abstract/` to `test/` ([#253](https://github.com/level/abstract-leveldown/issues/253)) ([**@vweevers**](https://github.com/vweevers))
- Refactor internal test methods to have the same signature `(test, testCommon)` ([#268](https://github.com/level/abstract-leveldown/issues/268), [#275](https://github.com/level/abstract-leveldown/issues/275)) ([**@ralphtheninja**](https://github.com/ralphtheninja))
- Prefer `exports.*` over `module.exports.*` ([#276](https://github.com/level/abstract-leveldown/issues/276)) ([**@ralphtheninja**](https://github.com/ralphtheninja))
- Tweak copyright years for less maintenance ([`0b2949a`](https://github.com/level/abstract-leveldown/commit/0b2949a)) ([**@ralphtheninja**](https://github.com/ralphtheninja))
### Added
* Add node 10 to Travis (@ralphtheninja)
* Add `airtap` for browser tests (@vweevers)
- Add `iterator#seek()` ([#237](https://github.com/level/abstract-leveldown/issues/237), [#302](https://github.com/level/abstract-leveldown/issues/302), [#307](https://github.com/level/abstract-leveldown/issues/307)) ([**@vweevers**](https://github.com/vweevers), [**@ralphtheninja**](https://github.com/ralphtheninja))
- Add `nyc` and `coveralls` devDependencies for code coverage ([#253](https://github.com/level/abstract-leveldown/issues/253)) ([**@vweevers**](https://github.com/vweevers))
- Add `setUp` and `tearDown` to all sub tests ([#279](https://github.com/level/abstract-leveldown/issues/279), [#289](https://github.com/level/abstract-leveldown/issues/289)) ([**@ralphtheninja**](https://github.com/ralphtheninja))
- Add test for implementations that cannot support snapshots ([#239](https://github.com/level/abstract-leveldown/issues/239)) ([**@vweevers**](https://github.com/vweevers))
- Add `hallmark` devDependency for Markdown style and contributors ([#312](https://github.com/level/abstract-leveldown/issues/312)) ([**@vweevers**](https://github.com/vweevers))
### Removed
- Remove `location` ([#258](https://github.com/level/abstract-leveldown/issues/258)) ([**@ralphtheninja**](https://github.com/ralphtheninja))
- Remove `lastLocation`, `cleanup`, `rimraf` ([#249](https://github.com/level/abstract-leveldown/issues/249)) ([**@vweevers**](https://github.com/vweevers))
- Remove IE10 from Sauce Labs test matrix ([#312](https://github.com/level/abstract-leveldown/issues/312)) ([**@vweevers**](https://github.com/vweevers))
- Remove node 9 from Travis ([`0b52395`](https://github.com/level/abstract-leveldown/commit/0b52395)) ([**@ralphtheninja**](https://github.com/ralphtheninja))
- Remove tests that assumed support of boolean and NaN keys ([#277](https://github.com/level/abstract-leveldown/issues/277)) ([**@vweevers**](https://github.com/vweevers))
- Remove range tests that assumed `null` meant "not defined" ([#277](https://github.com/level/abstract-leveldown/issues/277)) ([**@vweevers**](https://github.com/vweevers))
- Remove sync test from `test/put-test.js` ([#300](https://github.com/level/abstract-leveldown/issues/300)) ([**@ralphtheninja**](https://github.com/ralphtheninja))
- Remove empty `errorValues()` test ([#273](https://github.com/level/abstract-leveldown/issues/273)) ([**@ralphtheninja**](https://github.com/ralphtheninja))
- Remove default `testCommon` parameter ([#264](https://github.com/level/abstract-leveldown/issues/264), [#271](https://github.com/level/abstract-leveldown/issues/271)) ([**@vweevers**](https://github.com/vweevers))
- Remove `contributors` from `package.json` ([`542f350`](https://github.com/level/abstract-leveldown/commit/542f350)) ([**@ralphtheninja**](https://github.com/ralphtheninja))
- Remove copyright headers from code ([`a36c04f`](https://github.com/level/abstract-leveldown/commit/a36c04f)) ([**@ralphtheninja**](https://github.com/ralphtheninja))
### Fixed
- Make sure all `t.throw` tests check error messages correctly ([#286](https://github.com/level/abstract-leveldown/issues/286)) ([**@ralphtheninja**](https://github.com/ralphtheninja))
- Check options objects properly for `null` ([#257](https://github.com/level/abstract-leveldown/issues/257), [#288](https://github.com/level/abstract-leveldown/issues/288)) ([**@ralphtheninja**](https://github.com/ralphtheninja), [**@vweevers**](https://github.com/vweevers))
- Serialize range options same as keys ([#277](https://github.com/level/abstract-leveldown/issues/277)) ([**@vweevers**](https://github.com/vweevers))
- Allow nullish and empty range options ([#277](https://github.com/level/abstract-leveldown/issues/277)) ([**@vweevers**](https://github.com/vweevers))
## [5.0.0] - 2018-05-22
### Changed
* Update `sinon` to `^5.0.0` (@ralphtheninja)
* Tweak README (@ralphtheninja)
* Replace `const` with `var` to support IE10 (@vweevers)
- Upgrade `sinon` to `^5.0.0` ([**@ralphtheninja**](https://github.com/ralphtheninja))
- Tweak README ([**@ralphtheninja**](https://github.com/ralphtheninja))
- Replace `const` with `var` to support IE10 ([**@vweevers**](https://github.com/vweevers))
### Added
- Add node 10 to Travis ([**@ralphtheninja**](https://github.com/ralphtheninja))
- Add `airtap` for browser tests ([**@vweevers**](https://github.com/vweevers))
### Removed
* Remove node 4, 5 and 7 from Travis (@ralphtheninja)
* Remove TypeScript tests (@vweevers)
* Remove TypeScript typings (@ralphtheninja)
- Remove node 4, 5 and 7 from Travis ([**@ralphtheninja**](https://github.com/ralphtheninja))
- Remove TypeScript tests ([**@vweevers**](https://github.com/vweevers))
- Remove TypeScript typings ([**@ralphtheninja**](https://github.com/ralphtheninja))
## [4.0.3] - 2018-02-21
### Changed
* Update `ts-node` to `^5.0.0` (@zixia)
* Update `standard` to `^11.0.0` (@ralphtheninja)
- Upgrade `ts-node` to `^5.0.0` ([**@zixia**](https://github.com/zixia))
- Upgrade `standard` to `^11.0.0` ([**@ralphtheninja**](https://github.com/ralphtheninja))
### Fixed
* Remove invalid TypeScript from `Batch` (@Tapppi)
* Add JSDoc to incorrectly inferred TypeScript types (@Tapppi)
- Remove invalid TypeScript from `Batch` ([**@Tapppi**](https://github.com/Tapppi))
- Add JSDoc to incorrectly inferred TypeScript types ([**@Tapppi**](https://github.com/Tapppi))
## [4.0.2] - 2018-02-09
### Fixed
* Fix `iterator#next` to return `this` (@vweevers)
- Fix `iterator#next` to return `this` ([**@vweevers**](https://github.com/vweevers))
## [4.0.1] - 2018-02-09
### Added
* Run test suite in TypeScript in addition to Node.js (@vweevers)
* Add TypeScript smoke test (@vweevers)
* Add TypeScript readme section with stability badge (@vweevers)
### Fixed
* Update TypeScript typings for v4 (@vweevers)
* Use ES6 classes in tests to please TypeScript (@vweevers)
* Define default methods on prototype to please TypeScript (@vweevers)
- Run test suite in TypeScript in addition to Node.js ([**@vweevers**](https://github.com/vweevers))
- Add TypeScript smoke test ([**@vweevers**](https://github.com/vweevers))
- Add TypeScript readme section with stability badge ([**@vweevers**](https://github.com/vweevers))
### Removed
* Remove obsolete parameters from tests (@vweevers)
- Remove obsolete parameters from tests ([**@vweevers**](https://github.com/vweevers))
### Fixed
- Update TypeScript typings for v4 ([**@vweevers**](https://github.com/vweevers))
- Use ES6 classes in tests to please TypeScript ([**@vweevers**](https://github.com/vweevers))
- Define default methods on prototype to please TypeScript ([**@vweevers**](https://github.com/vweevers))
**Historical Note** This was released as a patch because it only changed tests

@@ -57,31 +121,35 @@ and TypeScript typings (which are marked experimental and don't follow semver).

### Changed
- Ignore empty range options in `AbstractLevelDOWN#_setupIteratorOptions` ([**@ralphtheninja**](https://github.com/ralphtheninja))
- Make `testCommon.js` the default value for `testCommon` parameter ([**@ralphtheninja**](https://github.com/ralphtheninja))
- Use `Buffer.isBuffer()` instead of `AbstractLevelDOWN#isBuffer` ([**@ralphtheninja**](https://github.com/ralphtheninja))
- Cleanup iterator tests ([#161](https://github.com/level/abstract-leveldown/issues/161)) ([**@ralphtheninja**](https://github.com/ralphtheninja))
- Pass test function as a parameter instead of setting local global ([**@ralphtheninja**](https://github.com/ralphtheninja))
- Assert batch type is `'put'` or `'del'` ([**@vweevers**](https://github.com/vweevers))
- Assert batch array elements are objects ([**@vweevers**](https://github.com/vweevers))
### Added
* Add `standard` for linting (#150) (@ralphtheninja)
* Test that callbacks are called asynchronously (@vweevers)
* Test serialization extensibility (@vweevers)
* Add @vweevers to contributors (@ralphtheninja)
* Add upgrade guide in `UPGRADING.md` (@ralphtheninja)
* Add node 9 to Travis (@ralphtheninja)
### Changed
* Ignore empty range options in `AbstractLevelDOWN#_setupIteratorOptions` (@ralphtheninja)
* Make `testCommon.js` the default value for `testCommon` parameter (@ralphtheninja)
* Use `Buffer.isBuffer()` instead of `AbstractLevelDOWN#isBuffer` (@ralphtheninja)
* Cleanup iterator tests (#161) (@ralphtheninja)
* Pass test function as a parameter instead of setting local global (@ralphtheninja)
* Assert batch type is `'put'` or `'del'` (@vweevers)
* Assert batch array elements are objects (@vweevers)
- Add `standard` for linting ([#150](https://github.com/level/abstract-leveldown/issues/150)) ([**@ralphtheninja**](https://github.com/ralphtheninja))
- Test that callbacks are called asynchronously ([**@vweevers**](https://github.com/vweevers))
- Test serialization extensibility ([**@vweevers**](https://github.com/vweevers))
- Add [**@vweevers**](https://github.com/vweevers) to contributors ([**@ralphtheninja**](https://github.com/ralphtheninja))
- Add upgrade guide in `UPGRADING.md` ([**@ralphtheninja**](https://github.com/ralphtheninja))
- Add node 9 to Travis ([**@ralphtheninja**](https://github.com/ralphtheninja))
### Removed
- Remove `isLevelDOWN` function and corresponding tests ([**@ralphtheninja**](https://github.com/ralphtheninja))
- Remove `AbstractLevelDOWN#approximateSize` method and corresponding tests ([**@ralphtheninja**](https://github.com/ralphtheninja))
- Remove `testBuffer` in `abstract/put-get-del-test.js` ([**@ralphtheninja**](https://github.com/ralphtheninja))
- Remove object value test in `abstract/put-test.js` ([**@vweevers**](https://github.com/vweevers))
- Remove serialize buffer tests ([**@vweevers**](https://github.com/vweevers))
- Remove serialize object tests ([**@vweevers**](https://github.com/vweevers))
- Remove `BufferType` parameter in `abstract/put-get-del-test.js`, use `Buffer` ([**@ralphtheninja**](https://github.com/ralphtheninja))
### Fixed
* Ensure stores are closed properly (fixes problems on Windows) (@ralphtheninja)
* Call back errors on next tick to avoid `zalgo` (@vweevers)
### Removed
* Remove `isLevelDOWN` function and corresponding tests (@ralphtheninja)
* Remove `AbstractLevelDOWN#approximateSize` method and corresponding tests (@ralphtheninja)
* Remove `testBuffer` in `abstract/put-get-del-test.js` (@ralphtheninja)
* Remove object value test in `abstract/put-test.js` (@vweevers)
* Remove serialize buffer tests (@vweevers)
* Remove serialize object tests (@vweevers)
* Remove `BufferType` parameter in `abstract/put-get-del-test.js`, use `Buffer` (@ralphtheninja)
- Ensure stores are closed properly (fixes problems on Windows) ([**@ralphtheninja**](https://github.com/ralphtheninja))
- Call back errors on next tick to avoid `zalgo` ([**@vweevers**](https://github.com/vweevers))

@@ -91,95 +159,115 @@ ## [3.0.0] - 2017-11-04

### Added
* Add node version badge (@vweevers)
### Fixed
* Fix errors in `index.d.ts` (@sandersn)
- Add node version badge ([**@vweevers**](https://github.com/vweevers))
### Removed
* Drop support for `0.12`. Cause for new major version! (@vweevers)
- Drop support for `0.12`. Cause for new major version! ([**@vweevers**](https://github.com/vweevers))
### Fixed
- Fix errors in `index.d.ts` ([**@sandersn**](https://github.com/sandersn))
## [2.7.2] - 2017-10-11
### Changed
* Update `README` with new style (@ralphtheninja)
- Update `README` with new style ([**@ralphtheninja**](https://github.com/ralphtheninja))
## [2.7.1] - 2017-09-30
### Changed
* Refactor typings as ES2015 module (@MeirionHughes)
- Refactor typings as ES2015 module ([**@MeirionHughes**](https://github.com/MeirionHughes))
## [2.7.0] - 2017-09-12
### Added
* Add `TypeScript` definitions in `index.d.ts` (@MeirionHughes)
- Add `TypeScript` definitions in `index.d.ts` ([**@MeirionHughes**](https://github.com/MeirionHughes))
## [2.6.3] - 2017-09-05
### Changed
- Upgrade dependencies ([**@ralphtheninja**](https://github.com/ralphtheninja))
- Convert nullish values to empty strings ([**@bigeasy**](https://github.com/bigeasy))
- Use `t.equal(a, b)` instead of `t.ok(a === b)` ([**@bigeasy**](https://github.com/bigeasy))
- Relax tests for serializing object in `abstract/chained-batch-test.js` ([**@ralphtheninja**](https://github.com/ralphtheninja))
### Added
* Add `GreenKeeper` (@ralphtheninja)
* Test key/value serialization (@bigeasy)
* Test `undefined` value serializing to empty string (@ralphtheninja)
### Changed
* Update dependencies (@ralphtheninja)
* Convert nullish values to empty strings (@bigeasy)
* Use `t.equal(a, b)` instead of `t.ok(a === b)` (@bigeasy)
* Relax tests for serializing object in `abstract/chained-batch-test.js` (@ralphtheninja)
- Add `GreenKeeper` ([**@ralphtheninja**](https://github.com/ralphtheninja))
- Test key/value serialization ([**@bigeasy**](https://github.com/bigeasy))
- Test `undefined` value serializing to empty string ([**@ralphtheninja**](https://github.com/ralphtheninja))
### Fixed
* Document `.status` property (@ralphtheninja)
- Document `.status` property ([**@ralphtheninja**](https://github.com/ralphtheninja))
## [2.6.2] - 2017-07-30
### Changed
- Upgrade dependencies and float `devDependencies` ([**@ralphtheninja**](https://github.com/ralphtheninja))
- Update copyright years ([**@ralphtheninja**](https://github.com/ralphtheninja))
- Update node versions on Travis ([**@ralphtheninja**](https://github.com/ralphtheninja))
### Added
* Test serialization extensibility (@juliangruber)
### Changed
* Update dependencies and float `devDependencies` (@ralphtheninja)
* Update copyright years (@ralphtheninja)
* Update node versions on Travis (@ralphtheninja)
- Test serialization extensibility ([**@juliangruber**](https://github.com/juliangruber))
### Fixed
* Fix put test on object serialization (@juliangruber)
- Fix put test on object serialization ([**@juliangruber**](https://github.com/juliangruber))
## [2.6.1] - 2016-09-12
### Fixed
* Fix `null` case in default value serializer (fixes problems in `2.6.0`) (@juliangruber)
- Fix `null` case in default value serializer (fixes problems in `2.6.0`) ([**@juliangruber**](https://github.com/juliangruber))
## [2.6.0] - 2016-03-10
### Changed
- Use proto delegation to patch methods on db ([**@deanlandolt**](https://github.com/deanlandolt))
- Allow serialization functions to return buffers ([**@deanlandolt**](https://github.com/deanlandolt))
### Added
* Add `collectBatchOps` function to buffer `_put` and `_del` inputs in `abstract/chained-batch-test.js` (@deanlandolt)
### Changed
* Use proto delegation to patch methods on db (@deanlandolt)
* Allow serialization functions to return buffers (@deanlandolt)
- Add `collectBatchOps` function to buffer `_put` and `_del` inputs in `abstract/chained-batch-test.js` ([**@deanlandolt**](https://github.com/deanlandolt))
### Removed
* Remove unnecessary initialization hackery in `abstract/chained-batch-test.js` (@deanlandolt)
**Historical Note** This release was a breaking change. See @juliangruber's [comment](https://github.com/Level/abstract-leveldown/pull/85#issuecomment-246980978) for more information.
- Remove unnecessary initialization hackery in `abstract/chained-batch-test.js` ([**@deanlandolt**](https://github.com/deanlandolt))
**Historical Note** This release was a breaking change. See [**@juliangruber**](https://github.com/juliangruber)'s [comment](https://github.com/Level/abstract-leveldown/pull/85#issuecomment-246980978) for more information.
## [2.5.0] - 2016-05-01
### Changed
- Upgrade dependencies and add more node versions to Travis ([**@ralphtheninja**](https://github.com/ralphtheninja))
### Added
* Add dependency badge to `README` (@ralphtheninja)
* Add `AbstractLevelDOWN#_serializeKey` (@juliangruber)
* Add `AbstractLevelDOWN#_serializeValue` (@juliangruber)
* Add `AbstractChainedBatch#_serializeKey` (@juliangruber)
* Add `AbstractChainedBatch#_serializeValue` (@juliangruber)
* Test `_serialize` with object and buffer (@juliangruber)
### Changed
* Update dependencies and add more node versions to Travis (@ralphtheninja)
- Add dependency badge to `README` ([**@ralphtheninja**](https://github.com/ralphtheninja))
- Add `AbstractLevelDOWN#_serializeKey` ([**@juliangruber**](https://github.com/juliangruber))
- Add `AbstractLevelDOWN#_serializeValue` ([**@juliangruber**](https://github.com/juliangruber))
- Add `AbstractChainedBatch#_serializeKey` ([**@juliangruber**](https://github.com/juliangruber))
- Add `AbstractChainedBatch#_serializeValue` ([**@juliangruber**](https://github.com/juliangruber))
- Test `_serialize` with object and buffer ([**@juliangruber**](https://github.com/juliangruber))
### Removed
- Remove stringification of keys and values ([**@juliangruber**](https://github.com/juliangruber))
- Remove `.toBuffer` ([**@juliangruber**](https://github.com/juliangruber))
### Fixed
* Update `memdown` url (@ralphtheninja)
* `AbstractLevelDOWN#._checkKey` does not take three parameters (@ralphtheninja)
* Only show build status for the master branch (@watson)
* Fix minor typos in `README` (@timkuijsten)
### Removed
* Remove stringification of keys and values (@juliangruber)
* Remove `.toBuffer` (@juliangruber)
- Update `memdown` url ([**@ralphtheninja**](https://github.com/ralphtheninja))
- `AbstractLevelDOWN#._checkKey` does not take three parameters ([**@ralphtheninja**](https://github.com/ralphtheninja))
- Only show build status for the master branch ([**@watson**](https://github.com/watson))
- Fix minor typos in `README` ([**@timkuijsten**](https://github.com/timkuijsten))

@@ -189,28 +277,35 @@ ## [2.4.1] - 2015-08-29

### Fixed
* Remove use of `const` (@nolanlawson)
- Remove use of `const` ([**@nolanlawson**](https://github.com/nolanlawson))
## [2.4.0] - 2015-05-19
### Added
* Add `.status` property to `AbstractLevelDOWN` (@juliangruber)
- Add `.status` property to `AbstractLevelDOWN` ([**@juliangruber**](https://github.com/juliangruber))
## [2.3.1] - 2015-05-18
### Added
* Link to `level/community` (@ralphtheninja)
### Fixed
* Document `isLevelDown` function (@ralphtheninja)
- Link to `level/community` ([**@ralphtheninja**](https://github.com/ralphtheninja))
### Removed
* Extract `Contributors` section from `README` into `level/community` (@ralphtheninja)
- Extract `Contributors` section from `README` into `level/community` ([**@ralphtheninja**](https://github.com/ralphtheninja))
### Fixed
- Document `isLevelDown` function ([**@ralphtheninja**](https://github.com/ralphtheninja))
## [2.3.0] - 2015-05-18
### Changed
- Use `t.equal(a, b)` instead of `t.ok(a === b)` ([**@juliangruber**](https://github.com/juliangruber))
- Export API from `index.js` ([**@ralphtheninja**](https://github.com/ralphtheninja))
### Added
* Import `isLevelDOWN` function to `is-leveldown.js` (@ralphtheninja)
### Changed
* Use `t.equal(a, b)` instead of `t.ok(a === b)` (@juliangruber)
* Export API from `index.js` (@ralphtheninja)
- Import `isLevelDOWN` function to `is-leveldown.js` ([**@ralphtheninja**](https://github.com/ralphtheninja))

@@ -220,57 +315,69 @@ ## [2.2.2] - 2015-05-13

### Fixed
* Revert changes to `location` in `2.2.1` (@juliangruber)
- Revert changes to `location` in `2.2.1` ([**@juliangruber**](https://github.com/juliangruber))
## [2.2.1] - 2015-05-12
### Fixed
* Copy paste error gave wrong test description (@ralphtheninja)
* `t.throws()` is different for `tape` (@ralphtheninja)
* Assert `location` is not an empty string (@ralphtheninja)
- Copy paste error gave wrong test description ([**@ralphtheninja**](https://github.com/ralphtheninja))
- `t.throws()` is different for `tape` ([**@ralphtheninja**](https://github.com/ralphtheninja))
- Assert `location` is not an empty string ([**@ralphtheninja**](https://github.com/ralphtheninja))
## [2.2.0] - 2015-05-10
### Added
* Test `{ sync: true }` option in `abstract/put-test.js` (@juliangruber)
- Test `{ sync: true }` option in `abstract/put-test.js` ([**@juliangruber**](https://github.com/juliangruber))
## [2.1.4] - 2015-04-28
### Fixed
* Use `t.equal()` with `tape` (@ralphtheninja)
- Use `t.equal()` with `tape` ([**@ralphtheninja**](https://github.com/ralphtheninja))
## [2.1.3] - 2015-04-28
### Changed
* Change from `tap` to `tape` (@ralphtheninja)
- Change from `tap` to `tape` ([**@ralphtheninja**](https://github.com/ralphtheninja))
## [2.1.2] - 2015-04-27
### Changed
* Convert buffer to string so we can compare (@ralphtheninja)
- Convert buffer to string so we can compare ([**@ralphtheninja**](https://github.com/ralphtheninja))
## [2.1.1] - 2015-04-27
### Changed
- Update logo and copyright ([**@ralphtheninja**](https://github.com/ralphtheninja))
### Added
* Add @ralphtheninja to contributors (@ralphtheninja)
* Add `0.12` and `iojs` to Travis (@ralphtheninja)
### Changed
* Update logo and copyright (@ralphtheninja)
- Add [**@ralphtheninja**](https://github.com/ralphtheninja) to contributors ([**@ralphtheninja**](https://github.com/ralphtheninja))
- Add `0.12` and `iojs` to Travis ([**@ralphtheninja**](https://github.com/ralphtheninja))
### Fixed
* Include `.nonErrorValues()` test in `abstract/put-get-del-test.js` (@hden)
* `rvagg/node-abstract-leveldown` moved to `level/abstract-leveldown` (@ralphtheninja)
* Fix Travis for `0.8` (@ralphtheninja)
- Include `.nonErrorValues()` test in `abstract/put-get-del-test.js` ([**@hden**](https://github.com/hden))
- `rvagg/node-abstract-leveldown` moved to `level/abstract-leveldown` ([**@ralphtheninja**](https://github.com/ralphtheninja))
- Fix Travis for `0.8` ([**@ralphtheninja**](https://github.com/ralphtheninja))
## [2.1.0] - 2014-11-09
### Changed
- Use `setTimeout` instead of `process.nextTick` ([**@bigeasy**](https://github.com/bigeasy))
### Added
* Add @watson to contributors (@rvagg)
### Changed
* Use `setTimeout` instead of `process.nextTick` (@bigeasy)
- Add [**@watson**](https://github.com/watson) to contributors ([**@rvagg**](https://github.com/rvagg))
### Fixed
* Don't fail if no value is returned by `._get` (@watson)
* Use `error` test function when testing for errors (@watson)
- Don't fail if no value is returned by `._get` ([**@watson**](https://github.com/watson))
- Use `error` test function when testing for errors ([**@watson**](https://github.com/watson))
## [2.0.3] - 2014-10-02

@@ -283,44 +390,53 @@

### Added
* Test atomic batch operations (@calvinmetcalf)
- Test atomic batch operations ([**@calvinmetcalf**](https://github.com/calvinmetcalf))
## [2.0.1] - 2014-09-01
### Changed
* Set default values for options to `.open`, `.get`, `.put`, `.del` and `.batch` (@watson)
* Update pattern for setting default options for the iterator (@watson)
* Allow boolean options to be falsy/truthy (@watson)
- Set default values for options to `.open`, `.get`, `.put`, `.del` and `.batch` ([**@watson**](https://github.com/watson))
- Update pattern for setting default options for the iterator ([**@watson**](https://github.com/watson))
- Allow boolean options to be falsy/truthy ([**@watson**](https://github.com/watson))
### Removed
* Remove default options that are too `LevelDOWN` specific (@watson)
- Remove default options that are too `LevelDOWN` specific ([**@watson**](https://github.com/watson))
## [2.0.0] - 2014-08-26
### Changed
* Switch to allowing writes of empty values, `null`, `undefined`, `''`, `[]` and empty buffer (@juliangruber)
* Rename `AbstractLevelDOWN#_checkKeyValue` to `AbstractLevelDOWN#_checkKey` (@rvagg)
- Switch to allowing writes of empty values, `null`, `undefined`, `''`, `[]` and empty buffer ([**@juliangruber**](https://github.com/juliangruber))
- Rename `AbstractLevelDOWN#_checkKeyValue` to `AbstractLevelDOWN#_checkKey` ([**@rvagg**](https://github.com/rvagg))
## [1.0.0] - 2014-08-24
### Changed
- Ensure `Boolean` iterator options are `Boolean` ([**@watson**](https://github.com/watson))
### Added
* Test that an error is thrown when location isn't a string (@calvinmetcalf)
* Test opening and closing the store (@calvinmetcalf)
* Test iterator with `limit` set to `0` (@watson)
* Add more tests to `abstract/batch-test.js` (@calvinmetcalf)
* Set default values of iterator options (@watson)
* Account for batch options that are `null` (@calvinmetcalf)
### Changed
* Ensure `Boolean` iterator options are `Boolean` (@watson)
- Test that an error is thrown when location isn't a string ([**@calvinmetcalf**](https://github.com/calvinmetcalf))
- Test opening and closing the store ([**@calvinmetcalf**](https://github.com/calvinmetcalf))
- Test iterator with `limit` set to `0` ([**@watson**](https://github.com/watson))
- Add more tests to `abstract/batch-test.js` ([**@calvinmetcalf**](https://github.com/calvinmetcalf))
- Set default values of iterator options ([**@watson**](https://github.com/watson))
- Account for batch options that are `null` ([**@calvinmetcalf**](https://github.com/calvinmetcalf))
### Removed
* Remove options.start hackery (@rvagg)
- Remove options.start hackery ([**@rvagg**](https://github.com/rvagg))
## [0.12.4] - 2014-08-20
### Changed
- Change license to plain MIT ([**@andrewrk**](https://github.com/andrewrk))
### Added
* Test that `simple-iterator` returns buffers (@kesla)
* Test implicit snapshots (@kesla)
### Changed
* Change license to plain MIT (@andrewrk)
- Test that `simple-iterator` returns buffers ([**@kesla**](https://github.com/kesla))
- Test implicit snapshots ([**@kesla**](https://github.com/kesla))

@@ -330,60 +446,73 @@ ## [0.12.3] - 2014-06-27

### Changed
* Update `xtend` dependency (@andrewrk)
- Upgrade `xtend` dependency ([**@andrewrk**](https://github.com/andrewrk))
## [0.12.2] - 2014-04-26
### Changed
* Have `isTypedArray` check for existence of `ArrayBuffer` and `Uint8Array` constructors before usage (@rvagg)
- Have `isTypedArray` check for existence of `ArrayBuffer` and `Uint8Array` constructors before usage ([**@rvagg**](https://github.com/rvagg))
## [0.12.1] - 2014-04-26
### Changed
* Set default `BufferType` in `abstract/put-get-del-test.js` to `Buffer` instead of `ArrayBuffer` (@maxogden)
- Set default `BufferType` in `abstract/put-get-del-test.js` to `Buffer` instead of `ArrayBuffer` ([**@maxogden**](https://github.com/maxogden))
## [0.12.0] - 2014-03-12
### Changed
* Revert to pure `Buffer` and remove usage of `Uint16Array` (@rvagg)
- Revert to pure `Buffer` and remove usage of `Uint16Array` ([**@rvagg**](https://github.com/rvagg))
## [0.11.4] - 2014-03-11
### Removed
* Remove duplicate call to `t.end()` (@maxogden)
- Remove duplicate call to `t.end()` ([**@maxogden**](https://github.com/maxogden))
## [0.11.3] - 2014-01-26
### Changed
* Loosen the buffer type check (@rvagg)
- Loosen the buffer type check ([**@rvagg**](https://github.com/rvagg))
## [0.11.2] - 2013-12-05
### Added
* Add npm badges (@rvagg)
- Add npm badges ([**@rvagg**](https://github.com/rvagg))
### Fixed
* Fix iterator tests in `test.js` (@rvagg)
- Fix iterator tests in `test.js` ([**@rvagg**](https://github.com/rvagg))
## [0.11.1] - 2013-11-15
### Changed
* Adjust `abstract/approximate-size-test.js` to account for snappy compression (@rvagg)
- Adjust `abstract/approximate-size-test.js` to account for snappy compression ([**@rvagg**](https://github.com/rvagg))
## [0.11.0] - 2013-10-14
### Added
* Normalize `iterator()` options with `AbstractLevelDOWN#_setupIteratorOptions` (@rvagg)
- Normalize `iterator()` options with `AbstractLevelDOWN#_setupIteratorOptions` ([**@rvagg**](https://github.com/rvagg))
## [0.10.2] - 2013-09-06
### Changed
* Refactor duplicated versions of `isTypedArray` into `abstract/util.js` (@rvagg)
* Refactor duplicated versions of `'NotFound'` checks into `abstract/util.js`, fixed too-strict version in `get-test.js` (@rvagg)
- Refactor duplicated versions of `isTypedArray` into `abstract/util.js` ([**@rvagg**](https://github.com/rvagg))
- Refactor duplicated versions of `'NotFound'` checks into `abstract/util.js`, fixed too-strict version in `get-test.js` ([**@rvagg**](https://github.com/rvagg))
## [0.10.1] - 2013-08-29
### Changed
- Relax check for `Not Found` error message to be case insensitive in `get-test.js` ([**@rvagg**](https://github.com/rvagg))
### Added
* Add @substack to contributors (@rvagg)
### Changed
* Relax check for `Not Found` error message to be case insensitive in `get-test.js` (@rvagg)
- Add [**@substack**](https://github.com/substack) to contributors ([**@rvagg**](https://github.com/rvagg))

@@ -393,18 +522,22 @@ ## [0.10.0] - 2013-08-19

### Added
* Test `gt`, `gte`, `lt` and `lte` ranges (@dominictarr)
- Test `gt`, `gte`, `lt` and `lte` ranges ([**@dominictarr**](https://github.com/dominictarr))
## [0.9.0] - 2013-08-11
### Changed
- Make `AbstractChainedBatch` extensible ([**@kesla**](https://github.com/kesla))
- Export `AbstractChainedBatch` from `abstract-leveldown.js` ([**@kesla**](https://github.com/kesla))
### Added
* Test simultaneous get's (@kesla)
* Test `AbstractChainedBatch` extensibility (@kesla)
### Changed
* Make `AbstractChainedBatch` extensible (@kesla)
* Export `AbstractChainedBatch` from `abstract-leveldown.js` (@kesla)
- Test simultaneous get's ([**@kesla**](https://github.com/kesla))
- Test `AbstractChainedBatch` extensibility ([**@kesla**](https://github.com/kesla))
### Fixed
* Fix broken test assertion in `abstract/get-test.js` (@rvagg)
* Fix tests that weren't running properly (@kesla)
- Fix broken test assertion in `abstract/get-test.js` ([**@rvagg**](https://github.com/rvagg))
- Fix tests that weren't running properly ([**@kesla**](https://github.com/kesla))
## [0.8.2] - 2013-08-02

@@ -417,4 +550,5 @@

### Changed
* Remove use of `const` in `testCommon.js` (@rvagg)
- Remove use of `const` in `testCommon.js` ([**@rvagg**](https://github.com/rvagg))
**Historical Note** The version in `package.json` was changed from `0.7.4` to `0.8.1`. The `0.8.1` tag exists but this version was never published to npm.

@@ -424,12 +558,15 @@

### Changed
- Use `process.browser` check instead of `process.title == 'browser'` ([**@rvagg**](https://github.com/rvagg))
### Added
* Add `BufferType` parameter to `abstract/put-get-del-test.js` for `bops` support (@rvagg)
* Add `isTypedArray` function which checks `ArrayBuffer` or `Uint8Array` for `bops` support (@rvagg)
### Changed
* Use `process.browser` check instead of `process.title == 'browser'` (@rvagg)
- Add `BufferType` parameter to `abstract/put-get-del-test.js` for `bops` support ([**@rvagg**](https://github.com/rvagg))
- Add `isTypedArray` function which checks `ArrayBuffer` or `Uint8Array` for `bops` support ([**@rvagg**](https://github.com/rvagg))
### Fixed
* Fix `cleanup` function not calling back when browserified (@rvagg)
- Fix `cleanup` function not calling back when browserified ([**@rvagg**](https://github.com/rvagg))
**Historical Note** It seems the version in `package.json` was never changed to `0.8.0` in the git history, even though the `0.8.0` tag exists. Most likely `package.json` was modified locally during `npm publish` but was never committed.

@@ -440,77 +577,92 @@

### Fixed
* Fix problems related to `browserify` and `rimraf` (@rvagg)
- Fix problems related to `browserify` and `rimraf` ([**@rvagg**](https://github.com/rvagg))
## [0.7.3] - 2013-07-26
### Added
* Add @pgte to contributors (@rvagg)
* Test iterator with `limit` set to `-1` (@kesla)
- Add [**@pgte**](https://github.com/pgte) to contributors ([**@rvagg**](https://github.com/rvagg))
- Test iterator with `limit` set to `-1` ([**@kesla**](https://github.com/kesla))
## [0.7.2] - 2013-07-08
### Changed
- Freeze chained batch state after `.write()` has been called ([**@rvagg**](https://github.com/rvagg))
- Make `NotFound` error case insensitive ([**@rvagg**](https://github.com/rvagg))
- Use `self` rather than binding functions to `this` ([**@juliangruber**](https://github.com/juliangruber))
### Added
* Add `AbstractChainedBatch#_checkWritten` (@rvagg)
* Test delete on non-existent key (@rvagg)
* Test iterator with `start` after database `end` (@juliangruber)
### Changed
* Freeze chained batch state after `.write()` has been called (@rvagg)
* Make `NotFound` error case insensitive (@rvagg)
* Use `self` rather than binding functions to `this` (@juliangruber)
- Add `AbstractChainedBatch#_checkWritten` ([**@rvagg**](https://github.com/rvagg))
- Test delete on non-existent key ([**@rvagg**](https://github.com/rvagg))
- Test iterator with `start` after database `end` ([**@juliangruber**](https://github.com/juliangruber))
### Fixed
* Don't coerce values to strings in browser (@maxogden)
* Make tests work in node and browser (@maxogden)
- Don't coerce values to strings in browser ([**@maxogden**](https://github.com/maxogden))
- Make tests work in node and browser ([**@maxogden**](https://github.com/maxogden))
## [0.7.1] - 2013-05-15
### Changed
* Adjust tests to be browserable (@rvagg)
- Adjust tests to be browserable ([**@rvagg**](https://github.com/rvagg))
## [0.7.0] - 2013-05-14
### Added
* Add `AbstractChainedBatch#clear` (@rvagg)
- Add `AbstractChainedBatch#clear` ([**@rvagg**](https://github.com/rvagg))
## [0.6.1] - 2013-05-14
### Changed
* Make `AbstractIterator` call back with an error instead of throwing on nexting and ending (@mcollina)
- Make `AbstractIterator` call back with an error instead of throwing on nexting and ending ([**@mcollina**](https://github.com/mcollina))
## [0.6.0] - 2013-05-14
### Changed
* Split `t.deepEqual()` into multiple `t.equal()` in `abstract/iterator-test.js` (@rvagg)
* Make `AbstractIterator` call back with an error instead of throwing on nexting and ending (@mcollina)
- Split `t.deepEqual()` into multiple `t.equal()` in `abstract/iterator-test.js` ([**@rvagg**](https://github.com/rvagg))
- Make `AbstractIterator` call back with an error instead of throwing on nexting and ending ([**@mcollina**](https://github.com/mcollina))
## [0.5.0] - 2013-05-14
### Changed
* Make `iterator.end(cb)` and `iterator.next(cb)` call back with an error instead of throwing (@mcollina)
- Make `iterator.end(cb)` and `iterator.next(cb)` call back with an error instead of throwing ([**@mcollina**](https://github.com/mcollina))
## [0.4.0-1] - 2013-05-14
### Added
* Add @No9 and @mcollina to contributors (@rvagg)
- Add [**@No9**](https://github.com/No9) and [**@mcollina**](https://github.com/mcollina) to contributors ([**@rvagg**](https://github.com/rvagg))
## [0.4.0] - 2013-05-14
### Changed
- Move `AbstractIterator` from `abstract-leveldown.js` to `abstract-iterator.js` ([**@rvagg**](https://github.com/rvagg))
### Added
* Add `AbstractChainedBatch` (@rvagg)
* Add `AbstractLevelDOWN#_chainedBatch` (@rvagg)
* Add `abstract/batch-test.js` and `abstract/chained-batch-test.js` (@rvagg)
### Changed
* Move `AbstractIterator` from `abstract-leveldown.js` to `abstract-iterator.js` (@rvagg)
- Add `AbstractChainedBatch` ([**@rvagg**](https://github.com/rvagg))
- Add `AbstractLevelDOWN#_chainedBatch` ([**@rvagg**](https://github.com/rvagg))
- Add `abstract/batch-test.js` and `abstract/chained-batch-test.js` ([**@rvagg**](https://github.com/rvagg))
## [0.3.0] - 2013-05-04
### Changed
- Use `this._checkKeyValue()` instead of local function ([**@rvagg**](https://github.com/rvagg))
- Use `this._isBuffer()` instead of `Buffer.isBuffer()` ([**@rvagg**](https://github.com/rvagg))
### Added
* Restore test for opening the database without options (@rvagg)
* Add `AbstractLevelDOWN#_isBuffer` so it can be overridden (@rvagg)
* Add `AbstractLevelDOWN#_checkKeyValue` so it can be overridden (@rvagg)
### Changed
* Use `this._checkKeyValue()` instead of local function (@rvagg)
* Use `this._isBuffer()` instead of `Buffer.isBuffer()` (@rvagg)
- Restore test for opening the database without options ([**@rvagg**](https://github.com/rvagg))
- Add `AbstractLevelDOWN#_isBuffer` so it can be overridden ([**@rvagg**](https://github.com/rvagg))
- Add `AbstractLevelDOWN#_checkKeyValue` so it can be overridden ([**@rvagg**](https://github.com/rvagg))

@@ -520,43 +672,53 @@ ## [0.2.3] - 2013-05-04

### Removed
* Remove test for opening the database without options (@rvagg)
- Remove test for opening the database without options ([**@rvagg**](https://github.com/rvagg))
## [0.2.2] - 2013-05-04
### Changed
* Split `.open()` tests into `.open()` and `.openAdvanced()` (@rvagg)
- Split `.open()` tests into `.open()` and `.openAdvanced()` ([**@rvagg**](https://github.com/rvagg))
## [0.2.1] - 2013-05-04
### Changed
* Convert values to `string` in `abstract/put-get-del-test.js` if `Buffer` is `undefined` (@rvagg)
- Convert values to `string` in `abstract/put-get-del-test.js` if `Buffer` is `undefined` ([**@rvagg**](https://github.com/rvagg))
## [0.2.0] - 2013-05-04
### Changed
- Convert values to `string` in `abstract/get-test.js` if `Buffer` is `undefined` ([**@rvagg**](https://github.com/rvagg))
- Don't stringify keys and values in `abstract/iterator-test.js` ([**@maxogden**](https://github.com/maxogden))
### Added
* Add `process.browser` check for `start` and `end` keys in browser (@maxogden)
* Add `levelup` contributors (@rvagg)
### Changed
* Convert values to `string` in `abstract/get-test.js` if `Buffer` is `undefined` (@rvagg)
* Don't stringify keys and values in `abstract/iterator-test.js` (@maxogden)
- Add `process.browser` check for `start` and `end` keys in browser ([**@maxogden**](https://github.com/maxogden))
- Add `levelup` contributors ([**@rvagg**](https://github.com/rvagg))
### Fixed
* Fix `tape` compatibility issues (@maxogden)
- Fix `tape` compatibility issues ([**@maxogden**](https://github.com/maxogden))
## [0.1.0] - 2013-04-23
### Added
* Import abstract tests from `leveldown` (@maxogden)
- Import abstract tests from `leveldown` ([**@maxogden**](https://github.com/maxogden))
### Fixed
* Clarify `README` (@rvagg)
- Clarify `README` ([**@rvagg**](https://github.com/rvagg))
## [0.0.2] - 2013-03-18
### Changed
- Export `checkKeyValue` ([**@rvagg**](https://github.com/rvagg))
### Added
* Add node 0.10 to Travis (@rvagg)
* Add `Buffer.isBuffer()` checks to keys and values (@rvagg)
### Changed
* Export `checkKeyValue` (@rvagg)
- Add node 0.10 to Travis ([**@rvagg**](https://github.com/rvagg))
- Add `Buffer.isBuffer()` checks to keys and values ([**@rvagg**](https://github.com/rvagg))

@@ -566,4 +728,5 @@ ## [0.0.1] - 2013-03-18

### Added
* Add `checkKeyValue` function for more complete error checking (@rvagg)
- Add `checkKeyValue` function for more complete error checking ([**@rvagg**](https://github.com/rvagg))
## 0.0.0 - 2013-03-15

@@ -573,68 +736,136 @@

[Unreleased]: https://github.com/level/abstract-leveldown/compare/v5.0.0...HEAD
[unreleased]: https://github.com/level/abstract-leveldown/compare/v6.0.0...HEAD
[6.0.0]: https://github.com/level/abstract-leveldown/compare/v5.0.0...v6.0.0
[5.0.0]: https://github.com/level/abstract-leveldown/compare/v4.0.3...v5.0.0
[4.0.3]: https://github.com/level/abstract-leveldown/compare/v4.0.2...v4.0.3
[4.0.2]: https://github.com/level/abstract-leveldown/compare/v4.0.1...v4.0.2
[4.0.1]: https://github.com/level/abstract-leveldown/compare/v4.0.0...v4.0.1
[4.0.0]: https://github.com/level/abstract-leveldown/compare/v3.0.0...v4.0.0
[3.0.0]: https://github.com/level/abstract-leveldown/compare/v2.7.2...v3.0.0
[2.7.2]: https://github.com/level/abstract-leveldown/compare/v2.7.1...v2.7.2
[2.7.1]: https://github.com/level/abstract-leveldown/compare/v2.7.0...v2.7.1
[2.7.0]: https://github.com/level/abstract-leveldown/compare/v2.6.3...v2.7.0
[2.6.3]: https://github.com/level/abstract-leveldown/compare/v2.6.2...v2.6.3
[2.6.2]: https://github.com/level/abstract-leveldown/compare/v2.6.1...v2.6.2
[2.6.1]: https://github.com/level/abstract-leveldown/compare/v2.6.0...v2.6.1
[2.6.0]: https://github.com/level/abstract-leveldown/compare/v2.5.0...v2.6.0
[2.5.0]: https://github.com/level/abstract-leveldown/compare/v2.4.1...v2.5.0
[2.4.1]: https://github.com/level/abstract-leveldown/compare/v2.4.0...v2.4.1
[2.4.0]: https://github.com/level/abstract-leveldown/compare/v2.3.1...v2.4.0
[2.3.1]: https://github.com/level/abstract-leveldown/compare/v2.3.0...v2.3.1
[2.3.0]: https://github.com/level/abstract-leveldown/compare/v2.2.2...v2.3.0
[2.2.2]: https://github.com/level/abstract-leveldown/compare/v2.2.1...v2.2.2
[2.2.1]: https://github.com/level/abstract-leveldown/compare/v2.2.0...v2.2.1
[2.2.0]: https://github.com/level/abstract-leveldown/compare/v2.1.4...v2.2.0
[2.1.4]: https://github.com/level/abstract-leveldown/compare/v2.1.3...v2.1.4
[2.1.3]: https://github.com/level/abstract-leveldown/compare/v2.1.2...v2.1.3
[2.1.2]: https://github.com/level/abstract-leveldown/compare/v2.1.1...v2.1.2
[2.1.1]: https://github.com/level/abstract-leveldown/compare/v2.1.0...v2.1.1
[2.1.0]: https://github.com/level/abstract-leveldown/compare/v2.0.3...v2.1.0
[2.0.3]: https://github.com/level/abstract-leveldown/compare/v2.0.2...v2.0.3
[2.0.2]: https://github.com/level/abstract-leveldown/compare/v2.0.1...v2.0.2
[2.0.1]: https://github.com/level/abstract-leveldown/compare/v2.0.0...v2.0.1
[2.0.0]: https://github.com/level/abstract-leveldown/compare/v1.0.0...v2.0.0
[1.0.0]: https://github.com/level/abstract-leveldown/compare/v0.12.4...v1.0.0
[0.12.4]: https://github.com/level/abstract-leveldown/compare/v0.12.3...v0.12.4
[0.12.3]: https://github.com/level/abstract-leveldown/compare/v0.12.2...v0.12.3
[0.12.2]: https://github.com/level/abstract-leveldown/compare/v0.12.1...v0.12.2
[0.12.1]: https://github.com/level/abstract-leveldown/compare/v0.12.0...v0.12.1
[0.12.0]: https://github.com/level/abstract-leveldown/compare/v0.11.4...v0.12.0
[0.11.4]: https://github.com/level/abstract-leveldown/compare/v0.11.3...v0.11.4
[0.11.3]: https://github.com/level/abstract-leveldown/compare/v0.11.2...v0.11.3
[0.11.2]: https://github.com/level/abstract-leveldown/compare/0.11.1...v0.11.2
[0.11.1]: https://github.com/level/abstract-leveldown/compare/0.11.0...0.11.1
[0.11.0]: https://github.com/level/abstract-leveldown/compare/0.10.2...0.11.0
[0.10.2]: https://github.com/level/abstract-leveldown/compare/0.10.1...0.10.2
[0.10.1]: https://github.com/level/abstract-leveldown/compare/0.10.0...0.10.1
[0.10.0]: https://github.com/level/abstract-leveldown/compare/0.9.0...0.10.0
[0.9.0]: https://github.com/level/abstract-leveldown/compare/0.8.2...0.9.0
[0.8.2]: https://github.com/level/abstract-leveldown/compare/0.8.1...0.8.2
[0.8.1]: https://github.com/level/abstract-leveldown/compare/0.8.0...0.8.1
[0.8.0]: https://github.com/level/abstract-leveldown/compare/0.7.4...0.8.0
[0.7.4]: https://github.com/level/abstract-leveldown/compare/0.7.3...0.7.4
[0.7.3]: https://github.com/level/abstract-leveldown/compare/0.7.2...0.7.3
[0.7.2]: https://github.com/level/abstract-leveldown/compare/0.7.1...0.7.2
[0.7.1]: https://github.com/level/abstract-leveldown/compare/0.7.0...0.7.1
[0.7.0]: https://github.com/level/abstract-leveldown/compare/0.6.1...0.7.0
[0.6.1]: https://github.com/level/abstract-leveldown/compare/0.6.0...0.6.1
[0.6.0]: https://github.com/level/abstract-leveldown/compare/0.5.0...0.6.0
[0.5.0]: https://github.com/level/abstract-leveldown/compare/0.4.0-1...0.5.0
[0.4.0-1]: https://github.com/level/abstract-leveldown/compare/0.4.0...0.4.0-1
[0.4.0]: https://github.com/level/abstract-leveldown/compare/0.3.0...0.4.0
[0.3.0]: https://github.com/level/abstract-leveldown/compare/0.2.1...0.3.0
[0.2.3]: https://github.com/level/abstract-leveldown/compare/0.2.2...0.2.3
[0.2.2]: https://github.com/level/abstract-leveldown/compare/0.2.1...0.2.2
[0.2.1]: https://github.com/level/abstract-leveldown/compare/0.2.0...0.2.1
[0.2.0]: https://github.com/level/abstract-leveldown/compare/0.1.0...0.2.0
[0.1.0]: https://github.com/level/abstract-leveldown/compare/0.0.2...0.1.0
[0.0.2]: https://github.com/level/abstract-leveldown/compare/0.0.1...0.0.2
[0.0.1]: https://github.com/level/abstract-leveldown/compare/0.0.0...0.0.1

@@ -1,6 +0,4 @@

The MIT License (MIT)
=====================
# The MIT License (MIT)
Copyright (c) 2013-2017 Rod Vagg
---------------------------
**Copyright © 2013-present Rod Vagg and [Contributors](CONTRIBUTORS.md).**

@@ -7,0 +5,0 @@ 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:

{
"name": "abstract-leveldown",
"description": "An abstract prototype matching the LevelDOWN API",
"version": "5.0.0",
"contributors": [
"Rod Vagg <r@va.gg> (https://github.com/rvagg)",
"John Chesley <john@chesl.es> (https://github.com/chesles/)",
"Jake Verbaten <raynos2@gmail.com> (https://github.com/raynos)",
"Dominic Tarr <dominic.tarr@gmail.com> (https://github.com/dominictarr)",
"Max Ogden <max@maxogden.com> (https://github.com/maxogden)",
"Lars-Magnus Skog <ralphtheninja@riseup.net> (https://github.com/ralphtheninja)",
"David Björklund <david.bjorklund@gmail.com> (https://github.com/kesla)",
"Julian Gruber <julian@juliangruber.com> (https://github.com/juliangruber)",
"Paolo Fragomeni <paolo@async.ly> (https://github.com/hij1nx)",
"Anton Whalley <anton.whalley@nearform.com> (https://github.com/No9)",
"Matteo Collina <matteo.collina@gmail.com> (https://github.com/mcollina)",
"Pedro Teixeira <pedro.teixeira@gmail.com> (https://github.com/pgte)",
"James Halliday <mail@substack.net> (https://github.com/substack)",
"Thomas Watson Steen <w@tson.dk> (https://github.com/watson)",
"Vincent Weevers <mail@vincentweevers.nl> (https://github.com/vweevers)"
],
"version": "6.0.0",
"license": "MIT",
"repository": {

@@ -34,20 +18,25 @@ "type": "git",

"dependencies": {
"level-concat-iterator": "~2.0.0",
"xtend": "~4.0.0"
},
"devDependencies": {
"airtap": "0.0.5",
"rimraf": "^2.6.1",
"sinon": "^5.0.0",
"standard": "^11.0.0",
"airtap": "0.1.0",
"coveralls": "~3.0.2",
"hallmark": "0.0.2",
"level-community": "~3.0.0",
"nyc": "~12.0.2",
"sinon": "^6.0.0",
"standard": "^12.0.0",
"tape": "^4.7.0"
},
"browser": {
"rimraf": false
},
"scripts": {
"test": "standard && node test.js",
"test-browsers": "airtap --sauce-connect --loopback airtap.local --no-coverage test.js",
"test-browser-local": "airtap --local --no-coverage test.js"
"test": "standard && hallmark && nyc node test/self.js",
"test-browsers": "airtap --coverage --loopback airtap.local test/self.js",
"test-browser-local": "airtap --coverage --local test/self.js",
"coverage": "nyc report --reporter=text-lcov | coveralls",
"hallmark": "hallmark --fix"
},
"license": "MIT",
"hallmark": {
"community": "level-community"
},
"engines": {

@@ -54,0 +43,0 @@ "node": ">=6"

# abstract-leveldown
> An abstract prototype matching the [`leveldown`](https://github.com/level/leveldown/) API. Useful for extending [`levelup`](https://github.com/level/levelup) functionality by providing a replacement to `leveldown`.
> An abstract prototype matching the [`leveldown`][leveldown] API. Useful for extending [`levelup`](https://github.com/level/levelup) functionality by providing a replacement to `leveldown`.

@@ -10,11 +10,32 @@ [![level badge][level-badge]](https://github.com/level/awesome)

[![david](https://david-dm.org/Level/abstract-leveldown.svg)](https://david-dm.org/level/abstract-leveldown)
[![Coverage Status](https://coveralls.io/repos/github/Level/abstract-leveldown/badge.svg)](https://coveralls.io/github/Level/abstract-leveldown)
[![JavaScript Style Guide](https://img.shields.io/badge/code_style-standard-brightgreen.svg)](https://standardjs.com)
[![npm](https://img.shields.io/npm/dm/abstract-leveldown.svg)](https://www.npmjs.com/package/abstract-leveldown)
`abstract-leveldown` provides a simple, operational *noop* base prototype that's ready for extending. By default, all operations have sensible "noops" (operations that essentially do nothing). For example, simple operations such as `.open(callback)` and `.close(callback)` will simply invoke the callback (on a *next tick*). More complex operations perform sensible actions, for example: `.get(key, callback)` will always return a `'NotFound'` `Error` on the callback.
## Table of Contents
You add functionality by implementing the underscore versions of the operations. For example, to implement a `put()` operation you add a `_put()` method to your object. Each of these underscore methods override the default *noop* operations and are always provided with **consistent arguments**, regardless of what is passed in by the client.
<details><summary>Click to expand</summary>
Additionally, all methods provide argument checking and sensible defaults for optional arguments. All bad-argument errors are compatible with `leveldown` (they pass the `leveldown` method arguments tests). For example, if you call `.open()` without a callback argument you'll get an `Error('open() requires a callback argument')`. Where optional arguments are involved, your underscore methods will receive sensible defaults. A `.get(key, callback)` will pass through to a `._get(key, options, callback)` where the `options` argument is an empty object.
- [Background](#background)
- [Example](#example)
- [Browser Support](#browser-support)
- [Public API For Consumers](#public-api-for-consumers)
- [Private API For Implementors](#private-api-for-implementors)
- [Test Suite](#test-suite)
- [Spread The Word](#spread-the-word)
- [Install](#install)
- [Contributing](#contributing)
- [Big Thanks](#big-thanks)
- [License](#license)
</details>
## Background
`abstract-leveldown` provides a simple, operational base prototype that's ready for extending. All operations have sensible _noop_ defaults (operations that essentially do nothing). For example, operations such as `.open(callback)` and `.close(callback)` will invoke `callback` on a next tick. Others perform sensible actions, like `.get(key, callback)` which will always yield a `'NotFound'` error.
You add functionality by implementing the "private" underscore versions of the operations. For example, to implement a public `put()` operation you add a private `_put()` method to your object. Each of these underscore methods override the default _noop_ operations and are always provided with consistent arguments, regardless of what is passed in through the public API. All methods provide argument checking and sensible defaults for optional arguments.
For example, if you call `.open()` without a callback argument you'll get an `Error('open() requires a callback argument')`. Where optional arguments are involved, your underscore methods will receive sensible defaults. A `.get(key, callback)` will pass through to a `._get(key, options, callback)` where the `options` argument is an empty object.
**If you are upgrading:** please see [UPGRADING.md](UPGRADING.md).

@@ -24,27 +45,31 @@

A simplistic in-memory `leveldown` replacement
Let's implement a simplistic in-memory [`leveldown`][leveldown] replacement:
```js
var AbstractLevelDOWN = require('abstract-leveldown').AbstractLevelDOWN
var util = require('util')
var AbstractLevelDOWN = require('./').AbstractLevelDOWN
// constructor, passes through the 'location' argument to the AbstractLevelDOWN constructor
function FakeLevelDOWN (location) {
AbstractLevelDOWN.call(this, location)
// Constructor
function FakeLevelDOWN () {
AbstractLevelDOWN.call(this)
}
// our new prototype inherits from AbstractLevelDOWN
// Our new prototype inherits from AbstractLevelDOWN
util.inherits(FakeLevelDOWN, AbstractLevelDOWN)
// implement some methods
FakeLevelDOWN.prototype._open = function (options, callback) {
// initialise a memory storage object
// Initialize a memory storage object
this._store = {}
// optional use of nextTick to be a nice async citizen
process.nextTick(function () { callback(null, this) }.bind(this))
// Use nextTick to be a nice async citizen
process.nextTick(callback, null, this)
}
FakeLevelDOWN.prototype._serializeKey = function (key) {
// Safety: avoid store['__proto__'] skullduggery.
// Below methods will receive serialized keys in their arguments.
return '!' + key
}
FakeLevelDOWN.prototype._put = function (key, value, options, callback) {
key = '_' + key // safety, to avoid key='__proto__'-type skullduggery
this._store[key] = value

@@ -55,28 +80,30 @@ process.nextTick(callback)

FakeLevelDOWN.prototype._get = function (key, options, callback) {
var value = this._store['_' + key]
if (value === undefined) {
// 'NotFound' error, consistent with LevelDOWN API
return process.nextTick(function () { callback(new Error('NotFound')) })
return process.nextTick(callback, new Error('NotFound'))
}
process.nextTick(function () {
callback(null, value)
})
process.nextTick(callback, null, value)
}
FakeLevelDOWN.prototype._del = function (key, options, callback) {
delete this._store['_' + key]
delete this._store[key]
process.nextTick(callback)
}
```
// Now use it with levelup
Now we can use our implementation with `levelup`:
```js
var levelup = require('levelup')
var db = levelup(new FakeLevelDOWN('/who/cares'))
var db = levelup(new FakeLevelDOWN())
db.put('foo', 'bar', function (err) {
if (err) throw err
db.get('foo', function (err, value) {
if (err) throw err
console.log('Got foo =', value)
console.log(value) // 'bar'
})

@@ -88,71 +115,405 @@ })

## Browser support
## Browser Support
[![Sauce Test Status](https://saucelabs.com/browser-matrix/abstract-leveldown.svg)](https://saucelabs.com/u/abstract-leveldown)
## Extensible API
## Public API For Consumers
Remember that each of these methods, if you implement them, will receive exactly the number and order of arguments described. Optional arguments will be converted to sensible defaults.
### `db = constructor(..)`
### `AbstractLevelDOWN(location)`
### `AbstractLevelDOWN#status`
Constructors typically take a `location` argument pointing to a location on disk where the data will be stored. Since not all implementations are disk-based and some are non-persistent, implementors are free to take zero or more arguments in their constructor.
An `AbstractLevelDOWN` based database can be in one of the following states:
### `db.status`
* `'new'` - newly created, not opened or closed
* `'opening'` - waiting for the database to be opened
* `'open'` - successfully opened the database, available for use
* `'closing'` - waiting for the database to be closed
* `'closed'` - database has been successfully closed, should not be used
A read-only property. An `abstract-leveldown` compliant store can be in one of the following states:
### `AbstractLevelDOWN#_open(options, callback)`
### `AbstractLevelDOWN#_close(callback)`
### `AbstractLevelDOWN#_get(key, options, callback)`
### `AbstractLevelDOWN#_put(key, value, options, callback)`
### `AbstractLevelDOWN#_del(key, options, callback)`
### `AbstractLevelDOWN#_batch(array, options, callback)`
- `'new'` - newly created, not opened or closed
- `'opening'` - waiting for the store to be opened
- `'open'` - successfully opened the store, available for use
- `'closing'` - waiting for the store to be closed
- `'closed'` - store has been successfully closed, should not be used.
If `batch()` is called without arguments or with only an options object then it should return a `Batch` object with chainable methods. Otherwise it will invoke a classic batch operation.
### `db.open([options, ]callback)`
### `AbstractLevelDOWN#_chainedBatch()`
Open the store. The `callback` function will be called with no arguments when the store has been successfully opened, or with a single error argument if the open operation failed for any reason.
By default a `batch()` operation without arguments returns a blank `AbstractChainedBatch` object. The prototype is available on the main exports for you to extend. If you want to implement chainable batch operations then you should extend the `AbstractChaindBatch` and return your object in the `_chainedBatch()` method.
The optional `options` argument may contain:
### `AbstractLevelDOWN#_serializeKey(key)`
### `AbstractLevelDOWN#_serializeValue(value)`
### `AbstractLevelDOWN#_iterator(options)`
- `createIfMissing` _(boolean, default: `true`)_: If `true` and the store doesn't exist it will be created. If `false` and the store doesn't exist, `callback` will receive an error.
- `errorIfExists` _(boolean, default: `false`)_: If `true` and the store exists, `callback` will receive an error.
By default an `iterator()` operation returns a blank `AbstractIterator` object. The prototype is available on the main exports for you to extend. If you want to implement iterator operations then you should extend the `AbstractIterator` and return your object in the `_iterator(options)` method.
Not all implementations support the above options.
The `iterator()` operation accepts the following range options:
### `db.close(callback)`
* `gt`
* `gte`
* `lt`
* `lte`
* `start` (legacy)
* `end` (legacy)
Close the store. The `callback` function will be called with no arguments if the operation is successful or with a single `error` argument if closing failed for any reason.
A range option that is either an empty buffer, an empty string or `null` will be ignored.
### `db.get(key[, options], callback)`
`AbstractIterator` implements the basic state management found in LevelDOWN. It keeps track of when a `next()` is in progress and when an `end()` has been called so it doesn't allow concurrent `next()` calls, it does allow `end()` while a `next()` is in progress and it doesn't allow either `next()` or `end()` after `end()` has been called.
Get a value from the store by `key`. The optional `options` object may contain:
### `AbstractIterator(db)`
- `asBuffer` _(boolean, default: `true`)_: Whether to return the `value` as a Buffer. If `false`, the returned type depends on the implementation.
Provided with the current instance of `AbstractLevelDOWN` by default.
The `callback` function will be called with an `Error` if the operation failed for any reason. If successful the first argument will be `null` and the second argument will be the value.
### `AbstractIterator#_next(callback)`
### `AbstractIterator#_end(callback)`
### `db.put(key, value[, options], callback)`
### `AbstractChainedBatch`
Provided with the current instance of `AbstractLevelDOWN` by default.
Store a new entry or overwrite an existing entry. There are no `options` by default but implementations may add theirs. The `callback` function will be called with no arguments if the operation is successful or with an `Error` if putting failed for any reason.
### `AbstractChainedBatch#_put(key, value)`
### `AbstractChainedBatch#_del(key)`
### `AbstractChainedBatch#_clear()`
### `AbstractChainedBatch#_write(options, callback)`
### `AbstractChainedBatch#_serializeKey(key)`
### `AbstractChainedBatch#_serializeValue(value)`
### `db.del(key[, options], callback)`
<a name="contributing"></a>
Delete an entry. There are no `options` by default but implementations may add theirs. The `callback` function will be called with no arguments if the operation is successful or with an `Error` if deletion failed for any reason.
### `db.batch(operations[, options], callback)`
Perform multiple _put_ and/or _del_ operations in bulk. The `operations` argument must be an `Array` containing a list of operations to be executed sequentially, although as a whole they are performed as an atomic operation.
Each operation is contained in an object having the following properties: `type`, `key`, `value`, where the `type` is either `'put'` or `'del'`. In the case of `'del'` the `value` property is ignored.
There are no `options` by default but implementations may add theirs. The `callback` function will be called with no arguments if the batch is successful or with an `Error` if the batch failed for any reason.
### `db.batch()`
Returns a [`chainedBatch`](#chainedbatch).
### `db.iterator([options])`
Returns an [`iterator`](#iterator). Accepts the following range options:
- `gt` (greater than), `gte` (greater than or equal) define the lower bound of the range to be iterated. Only entries where the key is greater than (or equal to) this option will be included in the range. When `reverse=true` the order will be reversed, but the entries iterated will be the same.
- `lt` (less than), `lte` (less than or equal) define the higher bound of the range to be iterated. Only entries where the key is less than (or equal to) this option will be included in the range. When `reverse=true` the order will be reversed, but the entries iterated will be the same.
- `reverse` _(boolean, default: `false`)_: iterate entries in reverse order. Beware that a reverse seek can be slower than a forward seek.
- `limit` _(number, default: `-1`)_: limit the number of entries collected by this iterator. This number represents a _maximum_ number of entries and may not be reached if you get to the end of the range first. A value of `-1` means there is no limit. When `reverse=true` the entries with the highest keys will be returned instead of the lowest keys.
Legacy options:
- `start`: instead use `gte`
- `end`: instead use `lte`.
**Note** Zero-length strings, buffers and arrays as well as `null` and `undefined` are invalid as keys, yet valid as range options. These types are significant in encodings like [`bytewise`](https://github.com/deanlandolt/bytewise) and [`charwise`](https://github.com/dominictarr/charwise). Consumers of an implementation should assume that `{ gt: undefined }` is _not_ the same as `{}`. An implementation can choose to:
- [_Serialize_](#db_serializekeykey) or [_encode_][encoding-down] these types to make them meaningful
- Have no defined behavior (moving the concern to a higher level)
- Delegate to an underlying store (moving the concern to a lower level).
In addition to range options, `iterator()` takes the following options:
- `keys` _(boolean, default: `true`)_: whether to return the key of each entry. If set to `false`, calls to `iterator.next(callback)` will yield keys with a value of `undefined`.
- `values` _(boolean, default: `true`)_: whether to return the value of each entry. If set to `false`, calls to `iterator.next(callback)` will yield values with a value of `undefined`.
- `keyAsBuffer` _(boolean, default: `true`)_: Whether to return the key of each entry as a Buffer. If `false`, the returned type depends on the implementation.
- `valueAsBuffer` _(boolean, default: `true`)_: Whether to return the value of each entry as a Buffer.
Lastly, an implementation is free to add its own options.
### `chainedBatch`
#### `chainedBatch.put(key, value)`
Queue a `put` operation on this batch. This may throw if `key` or `value` is invalid.
#### `chainedBatch.del(key)`
Queue a `del` operation on this batch. This may throw if `key` is invalid.
#### `chainedBatch.clear()`
Clear all queued operations on this batch.
#### `chainedBatch.write([options, ]callback)`
Commit the queued operations for this batch. All operations will be written atomically, that is, they will either all succeed or fail with no partial commits.
There are no `options` by default but implementations may add theirs. The `callback` function will be called with no arguments if the batch is successful or with an `Error` if the batch failed for any reason.
After `write` has been called, no further operations are allowed.
#### `chainedBatch.db`
A reference to the `db` that created this chained batch.
### `iterator`
An iterator allows you to _iterate_ the entire store or a range. It operates on a snapshot of the store, created at the time `db.iterator()` was called. This means reads on the iterator are unaffected by simultaneous writes. Most but not all implementations can offer this guarantee.
An iterator keeps track of when a `next()` is in progress and when an `end()` has been called so it doesn't allow concurrent `next()` calls, it does allow `end()` while a `next()` is in progress and it doesn't allow either `next()` or `end()` after `end()` has been called.
#### `iterator.next(callback)`
Advance the iterator and yield the entry at that key. If an error occurs, the `callback` function will be called with an `Error`. Otherwise, the `callback` receives `null`, a `key` and a `value`. The type of `key` and `value` depends on the options passed to `db.iterator()`.
If the iterator has reached its end, both `key` and `value` will be `undefined`. This happens in the following situations:
- The end of the store has been reached
- The end of the range has been reached
- The last `iterator.seek()` was out of range.
**Note:** Don't forget to call `iterator.end()`, even if you received an error.
#### `iterator.seek(target)`
Seek the iterator to a given key or the closest key. Subsequent calls to `iterator.next()` will yield entries with keys equal to or larger than `target`, or equal to or smaller than `target` if the `reverse` option passed to `db.iterator()` was true.
If range options like `gt` were passed to `db.iterator()` and `target` does not fall within that range, the iterator will reach its end.
**Note:** At the time of writing, [`leveldown`][leveldown] is the only known implementation to support `seek()`. In other implementations, it is a noop.
#### `iterator.end(callback)`
End iteration and free up underlying resources. The `callback` function will be called with no arguments on success or with an `Error` if ending failed for any reason.
#### `iterator.db`
A reference to the `db` that created this iterator.
### Type Support
The following applies to any method above that takes a `key` argument or option: all implementations _must_ support a `key` of type String and _should_ support a `key` of type Buffer. A `key` may not be `null`, `undefined`, a zero-length Buffer, zero-length string or zero-length array.
The following applies to any method above that takes a `value` argument or option: all implementations _must_ support a `value` of type String or Buffer. A `value` may not be `null` or `undefined` due to preexisting significance in streams and iterators.
Support of other key and value types depends on the implementation as well as its underlying storage. See also [`db._serializeKey`](#db_serializekeykey) and [`db._serializeValue`](#db_serializevaluevalue).
## Private API For Implementors
Each of these methods will receive exactly the number and order of arguments described. Optional arguments will receive sensible defaults. All callbacks are error-first and must be asynchronous. If an operation within your implementation is synchronous, be sure to call the callback in a next tick using `process.nextTick(callback, ..)`, `setImmediate` or some other means of micro- or macrotask scheduling.
### `db = AbstractLevelDOWN()`
The constructor takes no parameters. Sets the `.status` to `'new'`.
### `db._open(options, callback)`
Open the store. The `options` object will always have the following properties: `createIfMissing`, `errorIfExists`. If opening failed, call the `callback` function with an `Error`. Otherwise call `callback` without any arguments.
### `db._close(callback)`
Close the store. If closing failed, call the `callback` function with an `Error`. Otherwise call `callback` without any arguments.
### `db._serializeKey(key)`
Convert a `key` to a type supported by the underlying storage. All methods below that take a `key` argument or option - including `db._iterator()` with its range options and `iterator._seek()` with its `target` argument - will receive serialized keys. For example, if `_serializeKey` is implemented as:
```js
FakeLevelDOWN.prototype._serializeKey = function (key) {
return Buffer.isBuffer(key) ? key : String(key)
}
```
Then `db.get(2, callback)` translates into `db._get('2', options, callback)`. Similarly, `db.iterator({ gt: 2 })` translates into `db._iterator({ gt: '2', ... })` and `iterator.seek(2)` translates into `iterator._seek('2')`.
If the underlying storage supports any JavaScript type or if your implementation wraps another implementation, it is recommended to make `_serializeKey` an identity function. Serialization is irreversible, unlike _encoding_ as performed by implementations like [`encoding-down`][encoding-down]. This also applies to `_serializeValue`.
### `db._serializeValue(value)`
Convert a `value` to a type supported by the underlying storage. All methods below that take a `value` argument or option will receive serialized values. For example, if `_serializeValue` is implemented as:
```js
FakeLevelDOWN.prototype._serializeValue = function (value) {
return Buffer.isBuffer(value) ? value : String(value)
}
```
Then `db.put(key, 2, callback)` translates into `db._put(key, '2', options, callback)`.
### `db._get(key, options, callback)`
Get a value by `key`. The `options` object will always have the following properties: `asBuffer`. If the key does not exist, call the `callback` function with a `new Error('NotFound')`. Otherwise call `callback` with `null` as the first argument and the value as the second.
### `db._put(key, value, options, callback)`
Store a new entry or overwrite an existing entry. There are no default options but `options` will always be an object. If putting failed, call the `callback` function with an `Error`. Otherwise call `callback` without any arguments.
### `db._del(key, options, callback)`
Delete an entry. There are no default options but `options` will always be an object. If deletion failed, call the `callback` function with an `Error`. Otherwise call `callback` without any arguments.
### `db._batch(operations, options, callback)`
Perform multiple _put_ and/or _del_ operations in bulk. The `operations` argument is always an `Array` containing a list of operations to be executed sequentially, although as a whole they should be performed as an atomic operation. Each operation is guaranteed to have at least `type` and `key` properties. There are no default options but `options` will always be an object. If the batch failed, call the `callback` function with an `Error`. Otherwise call `callback` without any arguments.
### `db._chainedBatch()`
The default `_chainedBatch()` returns a functional `AbstractChainedBatch` instance that uses `db._batch(array, options, callback)` under the hood. The prototype is available on the main exports for you to extend. If you want to implement chainable batch operations in a different manner then you should extend `AbstractChainedBatch` and return an instance of this prototype in the `_chainedBatch()` method:
```js
var AbstractChainedBatch = require('abstract-leveldown').AbstractChainedBatch
var inherits = require('util').inherits
function ChainedBatch (db) {
AbstractChainedBatch.call(this, db)
}
inherits(ChainedBatch, AbstractChainedBatch)
FakeLevelDOWN.prototype._chainedBatch = function () {
return new ChainedBatch(this)
}
```
### `db._iterator(options)`
The default `_iterator()` returns a noop `AbstractIterator` instance. The prototype is available on the main exports for you to extend. To implement iterator operations you must extend `AbstractIterator` and return an instance of this prototype in the `_iterator(options)` method.
The `options` object will always have the following properties: `reverse`, `keys`, `values`, `limit`, `keyAsBuffer` and `valueAsBuffer`.
### `iterator = AbstractIterator(db)`
The first argument to this constructor must be an instance of your `AbstractLevelDOWN` implementation. The constructor will set `iterator.db` which is used to access `db._serialize*` and ensures that `db` will not be garbage collected in case there are no other references to it.
#### `iterator._next(callback)`
Advance the iterator and yield the entry at that key. If nexting failed, call the `callback` function with an `Error`. Otherwise, call `callback` with `null`, a `key` and a `value`.
#### `iterator._seek(target)`
Seek the iterator to a given key or the closest key.
#### `iterator._end(callback)`
Free up underlying resources. This method is guaranteed to only be called once. If ending failed, call the `callback` function with an `Error`. Otherwise call `callback` without any arguments.
### `chainedBatch = AbstractChainedBatch(db)`
The first argument to this constructor must be an instance of your `AbstractLevelDOWN` implementation. The constructor will set `chainedBatch.db` which is used to access `db._serialize*` and ensures that `db` will not be garbage collected in case there are no other references to it.
#### `chainedBatch._put(key, value)`
Queue a `put` operation on this batch.
#### `chainedBatch._del(key)`
Queue a `del` operation on this batch.
#### `chainedBatch._clear()`
Clear all queued operations on this batch.
#### `chainedBatch._write(options, callback)`
The default `_write` method uses `db._batch`. If the `_write` method is overridden it must atomically commit the queued operations. There are no default options but `options` will always be an object. If committing fails, call the `callback` function with an `Error`. Otherwise call `callback` without any arguments.
## Test Suite
To prove that your implementation is `abstract-leveldown` compliant, include the abstract test suite in your `test.js` (or similar):
```js
const test = require('tape')
const suite = require('abstract-leveldown/test')
const YourDOWN = require('.')
suite({
test: test,
factory: function () {
return new YourDOWN()
}
})
```
This is the most minimal setup. The `test` option _must_ be a function that is API-compatible with `tape`. The `factory` option _must_ be a function that returns a unique and isolated database instance. The factory will be called many times by the test suite.
If your implementation is disk-based we recommend using [`tempy`](https://github.com/sindresorhus/tempy) (or similar) to create unique temporary directories. Your setup could look something like:
```js
const test = require('tape')
const tempy = require('tempy')
const suite = require('abstract-leveldown/test')
const YourDOWN = require('.')
suite({
test: test,
factory: function () {
return new YourDOWN(tempy.directory())
}
})
```
### Excluding tests
As not every implementation can be fully compliant due to limitations of its underlying storage, some tests may be skipped. For example, to skip snapshot tests:
```js
suite({
// ..
snapshots: false
})
```
This also serves as a signal to users of your implementation. The following options are available:
- `bufferKeys`: set to `false` if binary keys are not supported by the underlying storage
- `seek`: set to `false` if your `iterator` does not implement `_seek`
- `snapshots`: set to `false` if any of the following is true:
- Reads don't operate on a [snapshot](#iterator)
- Snapshots are created asynchronously
- `createIfMissing` and `errorIfExists`: set to `false` if `db._open()` does not support these options.
### Setup and teardown
To perform (a)synchronous work before or after each test, you may define `setUp` and `tearDown` functions:
```js
suite({
// ..
setUp: function (t) {
t.end()
},
tearDown: function (t) {
t.end()
}
})
```
### Reusing `testCommon`
The input to the test suite is a `testCommon` object. Should you need to reuse `testCommon` for your own (additional) tests, use the included utility to create a `testCommon` with defaults:
```js
const test = require('tape')
const suite = require('abstract-leveldown/test')
const YourDOWN = require('.')
const testCommon = suite.common({
test: test,
factory: function () {
return new YourDOWN()
}
})
suite(testCommon)
```
The `testCommon` object will have all the properties describe above: `test`, `factory`, `setUp`, `tearDown` and the skip options. You might use it like so:
```js
test('setUp', testCommon.setUp)
test('custom test', function (t) {
var db = testCommon.factory()
// ..
})
test('another custom test', function (t) {
var db = testCommon.factory()
// ..
})
test('tearDown', testCommon.tearDown)
```
## Spread The Word
If you'd like to share your awesome implementation with the world, here's what you might want to do:
- Add an awesome badge to your `README`: `![level badge](http://leveldb.org/img/badge.svg)`
- Publish your awesome module to [npm](https://npmjs.org)
- Send a Pull Request to [Level/awesome](https://github.com/Level/awesome) to advertise your work!
## Install
With [npm](https://npmjs.org) do:
```
npm install abstract-leveldown
```
## Contributing

@@ -172,9 +533,10 @@

<a name="license"></a>
## License
Copyright &copy; 2013-2018 `abstract-leveldown` [contributors](https://github.com/level/community#contributors).
[MIT](LICENSE.md) © 2013-present Rod Vagg and [Contributors](CONTRIBUTORS.md).
`abstract-leveldown` 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
[encoding-down]: https://github.com/Level/encoding-down
[leveldown]: https://github.com/Level/leveldown
# 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.
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>
- [v6](#v6)
- [v5](#v5)
- [v4](#v4)
- [v3](#v3)
</details>
## v6
This release brings a major refactoring of the test suite, decouples `abstract-leveldown` from disk-based implementations and solves long-standing issues around serialization and type support.
### `location` was removed
`AbstractLevelDOWN` is no longer associated with a `location`. It's up to the implementation to handle it if it's required.
If your implementation has a `location` and you previously did:
```js
function YourDOWN (location) {
AbstractLevelDOWN.call(this, location)
}
```
You must now do:
```js
function YourDOWN (location) {
this.location = location
AbstractLevelDOWN.call(this)
}
```
Be sure to include appropriate type checks. If you relied on the default `AbstractLevelDOWN` behavior that would be:
```js
if (typeof location !== 'string') {
throw new Error('constructor requires a location string argument')
}
```
### Abstract test suite has moved to a single entry point
Instead of including test files individually, you can and should include the test suite with one `require()` statement. If you previously did:
```js
const test = require('tape')
const testCommon = require('abstract-leveldown/testCommon')
const YourDOWN = require('.')
require('abstract-leveldown/abstract/get-test').all(YourDOWN, test, testCommon)
require('abstract-leveldown/abstract/put-test').all(YourDOWN, test, testCommon)
// etc
```
You must now do:
```js
const test = require('tape')
const suite = require('abstract-leveldown/test')
const YourDOWN = require('.')
suite({
test: test,
factory: function () {
return new YourDOWN()
}
})
```
The input to the test suite is a new form of `testCommon`. Should you need to reuse `testCommon` for your own (additional) tests, use the included utility to create a `testCommon` with defaults:
```js
const test = require('tape')
const suite = require('abstract-leveldown/test')
const YourDOWN = require('.')
const testCommon = suite.common({
test: test,
factory: function () {
return new YourDOWN()
}
})
suite(testCommon)
```
As part of removing `location`, the abstract tests no longer use `testCommon.location()`. Instead an implementation _must_ implement `factory()` which _must_ return a unique and isolated database instance. This allows implementations to pass options to their constructor.
The `testCommon.cleanup` method has been removed. Because `factory()` returns a unique database instance, cleanup should no longer be necessary. The `testCommon.lastLocation` method has also been removed as there is no remaining use of it in abstract tests.
Previously, implementations using the default `testCommon` had to include `rimraf` in their `devDependencies` and browser-based implementations had to exclude `rimraf` from browserify builds. This is no longer the case.
If your implementation is disk-based we recommend using [`tempy`](https://github.com/sindresorhus/tempy) (or similar) to create unique temporary directories. Together with `factory()` your setup could now look something like:
```js
const test = require('tape')
const tempy = require('tempy')
const suite = require('abstract-leveldown/test')
const YourDOWN = require('.')
suite({
test: test,
factory: function () {
return new YourDOWN(tempy.directory())
}
})
```
### The `collectEntries` utility has moved
The `testCommon.collectEntries` method has moved to the npm package `level-concat-iterator`. If your (additional) tests depend on `collectEntries` and you previously did:
```js
testCommon.collectEntries(iterator, function (err, entries) {})
```
You must now do:
```js
const concat = require('level-concat-iterator')
concat(iterator, function (err, entries) {})
```
### Setup and teardown became noops
Because cleanup is no longer necessary, the `testCommon.setUp` and `testCommon.tearDown` methods are now noops by default. If you do need to perform (a)synchronous work before or after each test, `setUp` and `tearDown` can be overridden:
```js
suite({
// ..
setUp: function (t) {
t.end()
},
tearDown: function (t) {
t.end()
}
})
```
### Optional tests have been separated
If your implementation does not support snapshots or other optional features, the relevant tests may be skipped. For example:
```js
suite({
// ..
snapshots: false
})
```
Please see the [README](README.md) for a list of options. Note that some of these have replaced `process.browser` checks.
### Iterator must have a `db` reference
The `db` argument of the `AbstractIterator` constructor became mandatory, as well as a public `db` property on the instance. Its existence is not new; the test suite now asserts that your implementation also has it.
### Seeking became part of official API
If your implementation previously defined the public `iterator.seek(target)`, it must now define the private `iterator._seek(target)`. The new public API is equal to the reference implementation of `leveldown` except for two differences:
- The `target` argument is not type checked, this is up to the implementation.
- The `target` argument is passed through `db._serializeKey`.
Please see the [README](README.md) for details.
### Chained batch has been refactored
- The default `_clear` method is no longer a noop; instead it clears the operations queued by `_put` and/or `_del`
- The `_write` method now takes an `options` object as its first argument
- The `db` argument of the `AbstractChainedBatch` constructor became mandatory, as well as a public `db` property on the instance, which was previously named `_db`.
### Nullish values are rejected
In addition to rejecting `null` and `undefined` as _keys_, `abstract-leveldown` now also rejects these types as _values_, due to preexisting significance in streams and iterators.
Before this, the behavior of these types depended on a large number of factors: `_serializeValue` and type support of the underlying storage, whether `get()`, `iterator()` or a stream was used to retrieve values, the `keys` and `asBuffer` options of `iterator()` and finally, which encoding was selected.
### Default `_serializeKey` and `_serializeValue` became identity functions
They return whatever is given. Previously they were opinionated and mostly geared towards string- and Buffer-based storages. Implementations that didn't already define their own serialization should now do so, according to the types that they support. Please refer to the [README](README.md) for recommended behavior.
### Range options are serialized
Previously, range options like `lt` were passed through as-is, unlike keys.
### The rules for range options have been relaxed
Because `null`, `undefined`, zero-length strings and zero-length buffers are significant types in encodings like `bytewise` and `charwise`, they became valid as range options. In fact, any type is now valid. This means `db.iterator({ gt: undefined })` is not the same as `db.iterator({})`.
Furthermore, `abstract-leveldown` makes no assumptions about the meaning of these types. Range tests that assumed `null` meant "not defined" have been removed.
### Zero-length array keys are rejected
Though this was already the case because `_checkKey` stringified its input before checking the length, that behavior has been replaced with an explicit `Array.isArray()` check and a new error message.
### No longer assumes support of boolean and `NaN` keys
A test that asserted boolean and `NaN` keys were valid has been removed.
### Browser support
IE10 has been dropped.
## v5

@@ -6,0 +214,0 @@

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc