New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

levelup

Package Overview
Dependencies
Maintainers
1
Versions
101
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

levelup - npm Package Compare versions

Comparing version 0.8.0 to 0.9.0

bulk2ssd_pop.config

15

CHANGELOG.md

@@ -0,1 +1,16 @@

0.9.0 @ 21 May 2013
===================
* Use LevelDOWN@0.5.0, see https://github.com/rvagg/node-leveldown/blob/master/CHANGELOG.md for details
* Race-condition(ish) fixed in ReadStream--createReadStream() does not start immediately and therefore allowed put()s to happen before the stream starts (@dominictarr)
* ReadStream doesn't emit "ready" event (@dominictarr)
* Allow separate encodings per operation in db.batch() (@juliangruber)
* Allow separate encodings per write() in WriteStream (@juliangruber)
* WriteStream supports "type" option ("put" [default] or "del") on constructor and individual write()s (@mcollina)
* Remove "leveldown" from dependencies (see http://r.va.gg/2013/05/levelup-v0.9-some-major-changes.html) (@rvagg)
* Expose LevelDOWN (or LevelDOWN substitute) as `db` property on LevelUP instance (e.g. db.db.approximateSize())
* Chained batch exposed from LevelDOWN, invoked with argument-less db.batch() (@juliangruber, @rvagg)
* Significantly improve ReadStream performance by replacing .bind() and .apply() (@mcollina, @kesla)
* Better Browserify support (@rvagg, @juliangruber, @maxogden, etc.)
* Deprecate secondary LevelDB-specific operations on LevelUP, prefer direct LevelDOWN access (approximateSize(), repair(), destroy(), getProperty()--new in LevelDOWN@0.5.0) (@rvagg)
0.8.0 @ 17 Apr 2013

@@ -2,0 +17,0 @@ ===================

267

lib/levelup.js

@@ -7,25 +7,19 @@ /* Copyright (c) 2012-2013 LevelUP contributors

var leveldown = require('leveldown')
, EventEmitter = require('events').EventEmitter
, inherits = require('util').inherits
, extend = require('xtend')
, prr = require('prr')
var EventEmitter = require('events').EventEmitter
, inherits = require('util').inherits
, extend = require('xtend')
, prr = require('prr')
, errors = require('./errors')
, readStream = require('./read-stream')
, writeStream = require('./write-stream')
, util = require('./util')
, toEncoding = util.toEncoding
, toSlice = util.toSlice
, encodingOpts = util.encodingOpts
, errors = require('./errors')
, readStream = require('./read-stream')
, writeStream = require('./write-stream')
, util = require('./util')
, defaultOptions = {
createIfMissing : true
, errorIfExists : false
, keyEncoding : 'utf8'
, valueEncoding : 'utf8'
, compression : true
, db : leveldown
}
, toEncoding = util.toEncoding
, toSlice = util.toSlice
, getOptions = util.getOptions
, defaultOptions = util.defaultOptions
, getLevelDOWN = util.getLevelDOWN
, createLevelUP = function (location, options, callback) {

@@ -58,12 +52,12 @@

, getOptions = function (options) {
var s = typeof options == 'string' // just an encoding
if (!s && options && options.encoding && !options.valueEncoding)
options.valueEncoding = options.encoding
return extend(
(levelup && levelup.options) || {}
, s ? encodingOpts[options] || encodingOpts[defaultOptions.valueEncoding]
: options
)
}
, deferred = [ 'get', 'put', 'batch', 'del', 'approximateSize' ]
.reduce(function (o, method) {
o[method] = function () {
var args = Array.prototype.slice.call(arguments)
levelup.once('ready', function () {
levelup.db[method].apply(levelup.db, args)
})
}
return o
}, {})

@@ -74,4 +68,5 @@ if (typeof options == 'function') {

}
options = getOptions(options)
options = getOptions(levelup, options)
if (typeof location != 'string') {

@@ -103,3 +98,3 @@ error = new errors.InitializationError(

if (isOpening())
if (isOpening()) {
return callback && levelup.once(

@@ -109,38 +104,25 @@ 'open'

)
}
levelup.emit('opening')
status = 'opening'
this.db = deferred
var execute = function () {
var db = levelup.options.db(levelup.location)
var dbFactory = levelup.options.db || getLevelDOWN()
, db = dbFactory(levelup.location)
db.open(levelup.options, function (err) {
if (err) {
err = new errors.OpenError(err)
return dispatchError(err, callback)
} else {
levelup._db = db
status = 'open'
if (callback)
callback(null, levelup)
levelup.emit('open')
levelup.emit('ready')
}
})
}
, deferred = {}
;['get', 'put', 'batch', 'del', 'approximateSize']
.forEach(function (name) {
deferred[name] = function () {
var args = Array.prototype.slice.call(arguments)
levelup.once('ready', function () {
levelup._db[name].apply(levelup._db, args)
})
}
})
this._db = deferred
execute()
levelup.emit('opening')
db.open(levelup.options, function (err) {
if (err) {
err = new errors.OpenError(err)
return dispatchError(err, callback)
} else {
levelup.db = db
status = 'open'
if (callback)
callback(null, levelup)
levelup.emit('open')
levelup.emit('ready')
}
})
}

@@ -151,3 +133,3 @@

status = 'closing'
this._db.close(function () {
this.db.close(function () {
status = 'closed'

@@ -159,3 +141,3 @@ levelup.emit('closed')

levelup.emit('closing')
this._db = null
this.db = null
} else if (status == 'closed' && callback) {

@@ -193,3 +175,3 @@ callback()

options = getOptions(options)
options = getOptions(levelup, options)
key = toSlice[options.keyEncoding](key_)

@@ -199,3 +181,3 @@ valueEnc = options.valueEncoding

this._db.get(key, options, function (err, value) {
this.db.get(key, options, function (err, value) {
if (err) {

@@ -239,7 +221,7 @@ if ((/notfound/i).test(err)) {

options = getOptions(options)
options = getOptions(levelup, options)
key = toSlice[options.keyEncoding](key_)
value = toSlice[options.valueEncoding](value_)
this._db.put(key, value, options, function (err) {
this.db.put(key, value, options, function (err) {
if (err) {

@@ -272,6 +254,6 @@ err = new errors.WriteError(err)

options = getOptions(options)
options = getOptions(levelup, options)
key = toSlice[options.keyEncoding](key_)
this._db.del(key, options, function (err) {
this.db.del(key, options, function (err) {
if (err) {

@@ -288,11 +270,78 @@ err = new errors.WriteError(err)

LevelUP.prototype.batch = function (arr_, options, callback) {
function Batch (db) {
this.batch = db.batch()
this.ops = []
}
Batch.prototype.put = function (key, value, options) {
options = getOptions(levelup, options)
if (key)
key = toSlice[options.keyEncoding](key)
if (value)
value = toSlice[options.valueEncoding](value)
try {
this.batch.put(key, value)
} catch (e) {
throw new errors.WriteError(e)
}
this.ops.push({ type : 'put', key : key, value : value })
return this
}
Batch.prototype.del = function (key, options) {
options = getOptions(levelup, options)
if (key)
key = toSlice[options.keyEncoding](key)
try {
this.batch.del(key)
} catch (err) {
throw new errors.WriteError(err)
}
this.ops.push({ type : 'del', key : key })
return this
}
Batch.prototype.clear = function () {
try {
this.batch.clear()
} catch (err) {
throw new errors.WriteError(err)
}
this.ops = []
return this
}
Batch.prototype.write = function (callback) {
var ops = this.ops
try {
this.batch.write(function (err) {
if (err)
return dispatchError(new errors.WriteError(err), callback)
levelup.emit('batch', ops)
if (callback)
callback()
})
} catch (err) {
throw new errors.WriteError(err)
}
}
LevelUP.prototype.batch = function (arr, options, callback) {
var keyEnc
, valueEnc
, err
, arr
if (!arguments.length)
return new Batch(this.db)
callback = getCallback(options, callback)
if (!Array.isArray(arr_)) {
if (!Array.isArray(arr)) {
err = new errors.WriteError('batch() requires an array argument')

@@ -307,28 +356,33 @@ return dispatchError(err, callback)

options = getOptions(options)
options = getOptions(levelup, options)
keyEnc = options.keyEncoding
valueEnc = options.valueEncoding
// If we're not dealing with plain utf8 strings or plain
// Buffers then we have to do some work on the array to
// encode the keys and/or values. This includes JSON types.
if ((keyEnc != 'utf8' && keyEnc != 'binary')
|| (valueEnc != 'utf8' && valueEnc != 'binary')) {
arr = arr.map(function (e) {
if (e.type === undefined || e.key === undefined) {
return {}
}
arr = arr_.map(function (e) {
if (e.type !== undefined && e.key !== undefined) {
var o = { type: e.type, key: toSlice[keyEnc](e.key) }
// inherit encoding
var kEnc = e.keyEncoding || keyEnc
, vEnc = e.valueEncoding || e.encoding || valueEnc
, o
if (e.value !== undefined)
o.value = toSlice[valueEnc](e.value)
// If we're not dealing with plain utf8 strings or plain
// Buffers then we have to do some work on the array to
// encode the keys and/or values. This includes JSON types.
if (kEnc != 'utf8' && kEnc != 'binary'
|| vEnc != 'utf8' && vEnc != 'binary') {
o = { type: e.type, key: toSlice[kEnc](e.key) }
return o
}
return {}
})
} else {
arr = arr_
}
if (e.value !== undefined)
o.value = toSlice[vEnc](e.value)
this._db.batch(arr, options, function (err) {
return o
} else {
return e
}
})
this.db.batch(arr, options, function (err) {
if (err) {

@@ -338,3 +392,3 @@ err = new errors.WriteError(err)

} else {
levelup.emit('batch', arr_)
levelup.emit('batch', arr)
if (callback)

@@ -346,3 +400,4 @@ callback()

LevelUP.prototype.approximateSize = function(start, end, callback) {
// DEPRECATED: prefer accessing LevelDOWN for this: db.db.approximateSize()
LevelUP.prototype.approximateSize = function (start, end, callback) {
var err

@@ -362,3 +417,3 @@

this._db.approximateSize(start, end, function(err, size) {
this.db.approximateSize(start, end, function (err, size) {
if (err) {

@@ -379,3 +434,3 @@ err = new errors.OpenError(err)

, function (options) {
return levelup._db.iterator(options)
return levelup.db.iterator(options)
}

@@ -409,13 +464,13 @@ )

, destroy = function (location, callback) {
leveldown.destroy(location, callback || function () {})
, utilStatic = function (name) {
return function (location, callback) {
getLevelDOWN()[name](location, callback || function () {})
}
}
, repair = function (location, callback) {
leveldown.repair(location, callback || function () {})
}
module.exports = createLevelUP
module.exports.copy = util.copy
module.exports.destroy = destroy
module.exports.repair = repair
// DEPRECATED: prefer accessing LevelDOWN for this: require('leveldown').destroy()
module.exports.destroy = utilStatic('destroy')
// DEPRECATED: prefer accessing LevelDOWN for this: require('leveldown').repair()
module.exports.repair = utilStatic('repair')

@@ -15,3 +15,2 @@ /* Copyright (c) 2012-2013 LevelUP contributors

, toSlice = require('./util').toSlice
, setImmediate = require('./util').setImmediate

@@ -70,3 +69,2 @@ , defaultOptions = { keys: true, values: true }

this._iterator = iteratorFactory(this._options)
this.emit('ready')
this._read()

@@ -76,3 +74,3 @@ }.bind(this)

if (db.isOpen())
setImmediate(ready)
ready()
else

@@ -125,5 +123,8 @@ db.once('ready', ready)

ReadStream.prototype._read = function () {
var that = this
if (this._state.canRead()) {
this._state.read()
this._iterator.next(this._onData.bind(this))
this._iterator.next(function(err, key, value) {
that._onData(err, key, value)
})
}

@@ -134,3 +135,3 @@ }

this._state.endRead()
if (err || !arguments.length /* end */ || !this._state.canEmitData())
if (err || (key === undefined && value === undefined) || !this._state.canEmitData())
return this._cleanup(err)

@@ -156,2 +157,4 @@ this._read() // queue another read even tho we may not need it

this.emit('end')
if (this._iterator) {

@@ -164,4 +167,2 @@ this._iterator.end(function () {

this.emit('close')
this.emit('end')
}

@@ -168,0 +169,0 @@

@@ -7,3 +7,6 @@ /* Copyright (c) 2012-2013 LevelUP contributors

var encodings = [
var extend = require('xtend')
, errors = require('./errors')
, encodings = [
'hex'

@@ -21,2 +24,12 @@ , 'utf8'

, defaultOptions = {
createIfMissing : true
, errorIfExists : false
, keyEncoding : 'utf8'
, valueEncoding : 'utf8'
, compression : true
}
, leveldown
, toSlice = (function () {

@@ -69,8 +82,52 @@ var slicers = {}

, getOptions = function (levelup, options) {
var s = typeof options == 'string' // just an encoding
if (!s && options && options.encoding && !options.valueEncoding)
options.valueEncoding = options.encoding
return extend(
(levelup && levelup.options) || {}
, s ? encodingOpts[options] || encodingOpts[defaultOptions.valueEncoding]
: options
)
}
, getLevelDOWN = function () {
if (leveldown)
return leveldown
var requiredVersion = require('../package.json').devDependencies.leveldown
, missingLevelDOWNError = 'Could not locate LevelDOWN, try `npm install leveldown`'
, leveldownVersion
try {
leveldownVersion = require('leveldown/package').version
} catch (e) {
throw new errors.LevelUPError(missingLevelDOWNError)
}
if (!require('semver').satisfies(leveldownVersion, requiredVersion)) {
throw new errors.LevelUPError(
'Installed version of LevelDOWN ('
+ leveldownVersion
+ ') does not match required version ('
+ requiredVersion
+ ')'
)
}
try {
return leveldown = require('leveldown')
} catch (e) {
throw new errors.LevelUPError(missingLevelDOWNError)
}
}
module.exports = {
toSlice : toSlice
, toEncoding : toEncoding
, copy : copy
, setImmediate : setImmediate
, encodingOpts : encodingOpts
}
defaultOptions : defaultOptions
, toSlice : toSlice
, toEncoding : toEncoding
, copy : copy
, setImmediate : setImmediate
, getOptions : getOptions
, getLevelDOWN : getLevelDOWN
}

@@ -14,7 +14,9 @@ /* Copyright (c) 2012-2013 LevelUP contributors

, defaultOptions = {}
, getOptions = require('./util').getOptions
, defaultOptions = { type: 'put' }
function WriteStream (options, db) {
Stream.call(this)
this._options = extend(defaultOptions, options)
this._options = extend(defaultOptions, getOptions(db, options))
this._db = db

@@ -89,3 +91,3 @@ this._buffer = []

var buffer
, entry
, self = this

@@ -112,14 +114,16 @@ , cb = function (err) {

this._status = 'writing'
buffer = this._buffer
buffer = this._buffer
this._buffer = []
if (buffer.length == 1) {
entry = buffer.pop()
if (entry.key !== undefined && entry.value !== undefined)
this._db.put(entry.key, entry.value, cb)
} else {
this._db.batch(buffer.map(function (d) {
return { type: 'put', key: d.key, value: d.value }
}), cb)
}
this._db.batch(buffer.map(function (d) {
return {
type : d.type || self._options.type
, key : d.key
, value : d.value
, keyEncoding : d.keyEncoding || self._options.keyEncoding
, valueEncoding : d.valueEncoding
|| d.encoding
|| self._options.valueEncoding
}
}), cb)

@@ -136,3 +140,3 @@ if (this._writeBlock) {

if (this._end && this._status != 'closed') {
this._status = 'closed'
this._status = 'closed'
this.writable = false

@@ -145,4 +149,6 @@ this.emit('close')

var key = entry.path || entry.props.path
if (!key)
return
entry.pipe(concatStream(function (err, data) {

@@ -153,5 +159,7 @@ if (err) {

}
if (this._options.fstreamRoot &&
key.indexOf(this._options.fstreamRoot) > -1)
key = key.substr(this._options.fstreamRoot.length + 1)
this.write({ key: key, value: data })

@@ -167,2 +175,2 @@ }.bind(this)))

return new WriteStream(options, db)
}
}

@@ -14,2 +14,4 @@ {

, "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)"
]

@@ -25,7 +27,6 @@ , "keywords": [

]
, "version" : "0.8.0"
, "version" : "0.9.0"
, "main" : "lib/levelup.js"
, "dependencies" : {
"leveldown" : "~0.2.1"
, "errno" : "~0.0.3"
"errno" : "~0.0.3"
, "concat-stream" : "~0.1.1"

@@ -35,5 +36,7 @@ , "simple-bufferstream" : "~0.0.2"

, "prr" : "~0.0.0"
, "semver" : "~1.1.4"
}
, "devDependencies" : {
"bustermove" : "*"
"leveldown" : "~0.5.0"
, "bustermove" : "*"
, "tap" : "*"

@@ -53,2 +56,7 @@ , "referee" : "*"

}
, "browser" : {
"leveldown" : false
, "leveldown/package" : false
, "semver" : false
}
, "repository" : {

@@ -59,3 +67,3 @@ "type" : "git"

, "scripts" : {
"test" : "tap test/*-test.js"
"test" : "tap test/*-test.js --stderr"
, "functionaltests" : "node ./test/functional/fstream-test.js && node ./test/functional/binary-data-test.js && node ./test/functional/compat-test.js"

@@ -65,2 +73,2 @@ , "alltests" : "npm test && npm run-script functionaltests"

, "license" : "MIT"
}
}

@@ -11,23 +11,51 @@ LevelUP

**[LevelDB](http://code.google.com/p/leveldb/)** is a simple key/value data store built by Google, inspired by BigTable. It's used in Google Chrome and many other products. LevelDB supports arbitrary byte arrays as both keys and values, singular *get*, *put* and *delete* operations, *batched put and delete*, forward and reverse iteration and simple compression using the [Snappy](http://code.google.com/p/snappy/) algorithm which is optimised for speed over compression.
* <a href="#news">News</a>
* <a href="#intro">Introduction</a>
* <a href="#leveldown">Relationship to LevelDOWN</a>
* <a href="#platforms">Tested &amp; supported platforms</a>
* <a href="#basic">Basic usage</a>
* <a href="#api">API</a>
* <a href="#events">Events</a>
* <a href="#json">JSON data</a>
* <a href="#extending">Extending LevelUP</a>
* <a href="#multiproc">Multi-process access</a>
* <a href="#support">Getting support</a>
* <a href="#contributing">Contributing</a>
* <a href="#licence">Licence &amp; copyright</a>
**LevelUP** aims to expose the features of LevelDB in a Node.js-friendly way. Both keys and values are treated as `Buffer` objects and are automatically converted using a specified `'encoding'`. LevelDB's iterators are exposed as a Node.js style object-`ReadStream` and writing can be peformed via an object-`WriteStream`.
An important feature of LevelDB is that it stores entries sorted by keys. This makes LevelUP's <a href="#createReadStream"><code>ReadStream</code></a> interface is a very powerful way to look up items, particularly when combined with the `start` option.
<a name="news"></a>
News
----
The native LevelDB binding is now provided by a separate package, [LevelDOWN](https://github.com/rvagg/node-leveldown/).
* *2013-05-21* **[LevelUP v0.9 Released](http://r.va.gg/2013/05/levelup-v0.9-released.html)** &mdash; explains the main items in the [CHANGELOG](https://raw.github.com/rvagg/node-levelup/master/CHANGELOG.md) for 0.9 and who you should thank for the hard work.
* *2013-05-20* **[LevelUP v0.9 - Some Major Changes](http://r.va.gg/2013/05/levelup-v0.9-some-major-changes.html)** &mdash; discussing why we've removed [LevelDOWN](https://github.com/rvagg/node-leveldown/) as a dependency and the growing collection of LevelDOWN-compatible back-ends for LevelUP.
<a name="intro"></a>
Introduction
------------
**[LevelDB](http://code.google.com/p/leveldb/)** is a simple key/value data store built by Google, inspired by BigTable. It's used in Google Chrome and many other products. LevelDB supports arbitrary byte arrays as both keys and values, singular *get*, *put* and *delete* operations, *batched put and delete*, bi-directional iterators and simple compression using the very fast [Snappy](http://code.google.com/p/snappy/) algorithm.
**LevelUP** aims to expose the features of LevelDB in a **Node.js-friendly way**. All standard `Buffer` encoding types are supported, as is a special JSON encoding. LevelDB's iterators are exposed as a Node.js-style **readable stream** a matching **writeable stream* converts writes to *batch* operations.
LevelDB stores entries **sorted lexicographically by keys**. This makes LevelUP's <a href="#createReadStream"><code>ReadStream</code></a> interface is a very powerful query mechanism.
**LevelUP** is an **OPEN Open Source Project**, see the <a href="#contributing">Contributing</a> section to find out what this means.
* <a href="#platforms">Tested & supported platforms</a>
* <a href="#basic">Basic usage</a>
* <a href="#api">API</a>
* <a href="#events">Events</a>
* <a href="#json">JSON data</a>
* <a href="#considerations">Important considerations</a>
* <a href="#contributing">Contributing</a>
* <a href="#licence">Licence & copyright</a>
<a name="leveldown"></a>
Relationship to LevelDOWN
-------------------------
See also a list of <a href="https://github.com/rvagg/node-levelup/wiki/Modules"><b>Node.js LevelDB modules and projects</b></a> in the wiki.
LevelUP is designed to be backed by **[LevelDOWN](https://github.com/rvagg/node-leveldown/)** which provides a pure C++ binding to LevelDB and can be used as a stand-along package if required.
**As of version 0.9, LevelUP no longer requires LevelDOWN as a dependency so you must `npm install leveldown` when you install LevelUP.**
LevelDOWN is now optional because LevelUP can be used with alternative backends, such as **[level.js](https://github.com/maxogden/level.js)** in the browser or [MemDOWN](https://github.com/rvagg/node-memdown) for a pure in-memory store.
LevelUP will look for LevelDOWN and throw an error if it can't find it in its Node `require()` path. It will also tell you if the installed version of LevelDOWN is incompatible.
**The [level](https://github.com/level/level) package is available as an alternative installation mechanism.** Install it instead to automatically get both LevelUP & LevelDOWN. It exposes LevelUP on its export (i.e. you can `var leveldb = require('level')`).
<a name="platforms"></a>

@@ -37,8 +65,6 @@ Tested & supported platforms

* **Linux** (including ARM platforms such as Raspberry Pi *and Kindle!*)
* **Linux**: including ARM platforms such as Raspberry Pi *and Kindle!*
* **Mac OS**
* **Solaris** (SmartOS & Nodejitsu)
* **Windows**
* Node 0.10 and above only, see [issue #5](https://github.com/rvagg/node-levelup/issues/5) for more info
* See installation instructions for *node-gyp* dependencies [here](https://github.com/TooTallNate/node-gyp#installation), you'll need these (free) components from Microsoft to compile and run any native Node add-on in Windows.
* **Solaris**: including Joyent's SmartOS & Nodejitsu
* **Windows**: Node 0.10 and above only. See installation instructions for *node-gyp's* dependencies [here](https://github.com/TooTallNate/node-gyp#installation), you'll need these (free) components from Microsoft to compile and run any native Node add-on in Windows.

@@ -49,2 +75,17 @@ <a name="basic"></a>

First you need to install LevelUP!
```sh
$ npm install levelup leveldown
```
Or
```sh
$ npm install level
```
*(this second option requires you to use LevelUP by calling `var levelup = require('level')`)*
All operations are asynchronous although they don't necessarily require a callback if you don't need to know when the operation was performed.

@@ -82,4 +123,4 @@

* <a href="#del"><code>db.<b>del()</b></code></a>
* <a href="#batch"><code>db.<b>batch()</b></code></a>
* <a href="#approximateSize"><code>db.<b>approximateSize()</b></code></a>
* <a href="#batch"><code>db.<b>batch()</b></code> *(array form)*</a>
* <a href="#batch_chained"><code>db.<b>batch()</b></code> *(chained form)*</a>
* <a href="#isOpen"><code>db.<b>isOpen()</b></code></a>

@@ -91,6 +132,11 @@ * <a href="#isClosed"><code>db.<b>isClosed()</b></code></a>

* <a href="#createWriteStream"><code>db.<b>createWriteStream()</b></code></a>
* <a href="#destroy"><code><b>levelup.destroy()</b></code></a>
* <a href="#repair"><code><b>levelup.repair()</b></code></a>
### Special operations exposed by LevelDOWN
* <a href="#approximateSize"><code>db.db.<b>approximateSize()</b></code></a>
* <a href="#getProperty"><code>db.db.<b>getProperty()</b></code></a>
* <a href="#destroy"><code><b>leveldown.destroy()</b></code></a>
* <a href="#repair"><code><b>leveldown.repair()</b></code></a>
--------------------------------------------------------

@@ -137,3 +183,3 @@ <a name="ctor"></a>

* `'keyEncoding'` and `'valueEncoding'` *(string, default: `'utf8'`)*: The encoding of the keys and values passed through Node.js' `Buffer` implementation (see [Buffer#toString()](http://nodejs.org/docs/latest/api/buffer.html#buffer_buf_tostring_encoding_start_end)). You may also use `'encoding'` as an alias for `'valueEncoding'`.
* `'keyEncoding'` and `'valueEncoding'` *(string, default: `'utf8'`)*: The encoding of the keys and values passed through Node.js' `Buffer` implementation (see [Buffer#toString()](http://nodejs.org/docs/latest/api/buffer.html#buffer_buf_tostring_encoding_start_end)).
<p><code>'utf8'</code> is the default encoding for both keys and values so you can simply pass in strings and expect strings from your <code>get()</code> operations. You can also pass <code>Buffer</code> objects as keys and/or values and conversion will be performed.</p>

@@ -198,3 +244,3 @@ <p>Supported encodings are: hex, utf8, ascii, binary, base64, ucs2, utf16le.</p>

<a name="batch"></a>
### db.batch(array[, options][, callback])
### db.batch(array[, options][, callback]) *(array form)*
<code>batch()</code> can be used for very fast bulk-write operations (both *put* and *delete*). The `array` argument should contain a list of operations to be executed sequentially, although as a whole they are performed as an atomic operation inside LevelDB. 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. Any entries with a `'key'` of `null` or `undefined` will cause an error to be returned on the `callback` and any `'type': 'put'` entry with a `'value'` of `null` or `undefined` will return an error.

@@ -217,3 +263,2 @@

#### `options`

@@ -223,14 +268,52 @@

In addition to encoding options for the whole batch you can also overwrite the encoding per operation, like:
```js
var ops = [
{
type: 'put',
key: new Buffer([1, 2, 3]),
value: { some: 'json' },
keyEncoding: 'binary',
valueEncoding: 'json'
}
]
```
--------------------------------------------------------
<a name='approximateSize'></a>
### db.approximateSize(start, end, callback)
<code>approximateSize()</code> can used to get the approximate number of bytes of file system space used by the range `[start..end)`. The result may not include recently written data.
<a name="batch_chained"></a>
### db.batch() *(chained form)*
<code>batch()</code>, when called with no arguments will return a `Batch` object which can be used to build, and eventually commit, an atomic LevelDB batch operation. Depending on how it's used, it is possible to obtain greater performance when using the chained form of `batch()` over the array form.
```js
db.approximateSize('a', 'c', function (err, size) {
if (err) return console.error('Ooops!', err)
console.log('Approximate size of range is %d', size)
})
db.batch()
.del('father')
.put('name', 'Yuri Irsenovich Kim')
.put('dob', '16 February 1941')
.put('spouse', 'Kim Young-sook')
.put('occupation', 'Clown')
.write(function () { console.log('Done!') })
```
<b><code>batch.put(key, value[, options])</code></b>
Queue a *put* operation on the current batch, not committed until a `write()` is called on the batch.
The optional `options` argument can be used to override the default `'keyEncoding'` and/or `'valueEncoding'`.
<b><code>batch.del(key[, options])</code></b>
Queue a *del* operation on the current batch, not committed until a `write()` is called on the batch.
The optional `options` argument can be used to override the default `'keyEncoding'`.
<b><code>batch.clear()</code></b>
Clear all queued operations on the current batch, any previous operations will be discarded.
<b><code>batch.write([callback])</code></b>
Commit the queued operations for this batch. All operations not *cleared* will be written to the database atomically, that is, they will either all succeed or fail with no partial commits. The optional `callback` will be called when the operation has completed with an *error* argument if an error has occurred.
--------------------------------------------------------

@@ -298,2 +381,4 @@ <a name="isOpen"></a>

* `'keyEncoding'` / `'valueEncoding'` *(string)*: the encoding applied to each read piece of data.
--------------------------------------------------------

@@ -345,17 +430,21 @@ <a name="createKeyStream"></a>

A **WriteStream** can be obtained by calling the `createWriteStream()` method. The resulting stream is a complete Node.js-style [Writable Stream](http://nodejs.org/docs/latest/api/stream.html#stream_writable_stream) which accepts objects with `'key'` and `'value'` pairs on its `write()` method. The WriteStream will buffer writes and submit them as a `batch()` operation where the writes occur on the same event loop tick, otherwise they are treated as simple `put()` operations.
A **WriteStream** can be obtained by calling the `createWriteStream()` method. The resulting stream is a complete Node.js-style [Writable Stream](http://nodejs.org/docs/latest/api/stream.html#stream_writable_stream) which accepts objects with `'key'` and `'value'` pairs on its `write()` method.
The WriteStream will buffer writes and submit them as a `batch()` operations where writes occur *within the same tick*.
```js
db.createWriteStream()
.on('error', function (err) {
console.log('Oh my!', err)
})
.on('close', function () {
console.log('Stream closed')
})
.write({ key: 'name', value: 'Yuri Irsenovich Kim' })
.write({ key: 'dob', value: '16 February 1941' })
.write({ key: 'spouse', value: 'Kim Young-sook' })
.write({ key: 'occupation', value: 'Clown' })
.end()
var ws = db.createWriteStream()
ws.on('error', function (err) {
console.log('Oh my!', err)
})
ws.on('close', function () {
console.log('Stream closed')
})
ws.write({ key: 'name', value: 'Yuri Irsenovich Kim' })
ws.write({ key: 'dob', value: '16 February 1941' })
ws.write({ key: 'spouse', value: 'Kim Young-sook' })
ws.write({ key: 'occupation', value: 'Clown' })
ws.end()
```

@@ -365,2 +454,60 @@

You can specify encodings both for the whole stream and individual entries:
To set the encoding for the whole stream, provide an options object as the first parameter to `createWriteStream()` with `'keyEncoding'` and/or `'valueEncoding'`.
To set the encoding for an individual entry:
```js
writeStream.write({
key: new Buffer([1, 2, 3]),
value: { some: 'json' },
keyEncoding: 'binary',
valueEncoding: 'json'
})
```
#### write({ type: 'put' })
If individual `write()` operations are performed with a `'type'` property of `'del'`, they will be passed on as `'del'` operations to the batch.
```js
var ws = db.createWriteStream()
ws.on('error', function (err) {
console.log('Oh my!', err)
})
ws.on('close', function () {
console.log('Stream closed')
})
ws.write({ type: 'del', key: 'name' })
ws.write({ type: 'del', key: 'dob' })
ws.write({ type: 'put', key: 'spouse' })
ws.write({ type: 'del', key: 'occupation' })
ws.end()
```
#### db.createWriteStream({ type: 'put' })
If the *WriteStream* is created a `'type'` option of `'del'`, all `write()` operations will be interpreted as `'del'`, unless explicitly specified as `'put'`.
```js
var ws = db.createWriteStream({ type: 'del' })
ws.on('error', function (err) {
console.log('Oh my!', err)
})
ws.on('close', function () {
console.log('Stream closed')
})
ws.write({ key: 'name' })
ws.write({ key: 'dob' })
// but it can be overridden
ws.write({ type: 'put', key: 'spouse', value: 'Ri Sol-ju' })
ws.write({ key: 'occupation' })
ws.end()
```
#### Pipes and Node Stream compatibility

@@ -380,11 +527,59 @@

--------------------------------------------------------
<a name='approximateSize'></a>
### db.db.approximateSize(start, end, callback)
<code>approximateSize()</code> can used to get the approximate number of bytes of file system space used by the range `[start..end)`. The result may not include recently written data.
```js
var db = require('level')('./huge.db')
db.db.approximateSize('a', 'c', function (err, size) {
if (err) return console.error('Ooops!', err)
console.log('Approximate size of range is %d', size)
})
```
**Note:** `approximateSize()` is available via [LevelDOWN](https://github.com/rvagg/node-leveldown/), which by default is accessible as the `db` property of your LevelUP instance. This is a specific LevelDB operation and is not likely to be available where you replace LevelDOWN with an alternative back-end via the `'db'` option.
--------------------------------------------------------
<a name='getProperty'></a>
### db.db.getProperty(property)
<code>getProperty</code> can be used to get internal details from LevelDB. When issued with a valid property string, a readable string will be returned (this method is synchronous).
Currently, the only valid properties are:
* <b><code>'leveldb.num-files-at-levelN'</code></b>: returns the number of files at level *N*, where N is an integer representing a valid level (e.g. "0").
* <b><code>'leveldb.stats'</code></b>: returns a multi-line string describing statistics about LevelDB's internal operation.
* <b><code>'leveldb.sstables'</code></b>: returns a multi-line string describing all of the *sstables* that make up contents of the current database.
```js
var db = require('level')('./huge.db')
console.log(db.db.getProperty('leveldb.num-files-at-level3'))
// → '243'
```
**Note:** `getProperty()` is available via [LevelDOWN](https://github.com/rvagg/node-leveldown/), which by default is accessible as the `db` property of your LevelUP instance. This is a specific LevelDB operation and is not likely to be available where you replace LevelDOWN with an alternative back-end via the `'db'` option.
--------------------------------------------------------
<a name="destroy"></a>
### levelup.destroy(location[, callback])
### leveldown.destroy(location, callback)
<code>destroy()</code> is used to completely remove an existing LevelDB database directory. You can use this function in place of a full directory *rm* if you want to be sure to only remove LevelDB-related files. If the directory only contains LevelDB files, the directory itself will be removed as well. If there are additional, non-LevelDB files in the directory, those files, and the directory, will be left alone.
The optional callback will be called when the destroy operation is complete, with a possible `error` argument.
The callback will be called when the destroy operation is complete, with a possible `error` argument.
**Note:** `destroy()` is available via [LevelDOWN](https://github.com/rvagg/node-leveldown/) which you will have to have available to `require()`, e.g.:
```js
require('leveldown').destroy('./huge.db', function () { console.log('done!') })
```
--------------------------------------------------------
<a name="repair"></a>
### levelup.repair(location[, callback])
### leveldown.repair(location, callback)
<code>repair()</code> can be used to attempt a restoration of a damaged LevelDB store. From the LevelDB documentation:

@@ -398,4 +593,12 @@

The optional callback will be called when the repair operation is complete, with a possible `error` argument.
The callback will be called when the repair operation is complete, with a possible `error` argument.
**Note:** `destroy()` is available via [LevelDOWN](https://github.com/rvagg/node-leveldown/) which you will have to have available to `require()`, e.g.:
```js
require('leveldown').repair('./huge.db', function () { console.log('done!') })
```
--------------------------------------------------------
<a name="events"></a>

@@ -423,8 +626,28 @@ Events

<a name="considerations"></a>
Important considerations
------------------------
<a name="extending"></a>
Extending LevelUP
-----------------
* LevelDB is thread-safe but is **not** suitable for accessing with multiple processes. You should only ever have a LevelDB database open from a single Node.js process.
A list of <a href="https://github.com/rvagg/node-levelup/wiki/Modules"><b>Node.js LevelDB modules and projects</b></a> can be found in the wiki.
When attempting to extend the functionality of LevelUP, it is recommended that you consider using [level-hooks](https://github.com/dominictarr/level-hooks) and/or [level-sublevel](https://github.com/dominictarr/level-sublevel). **level-sublevel** is particularly helpful for keeping additional, extension-specific, data in a LevelDB store. It allows you to partition a LevelUP instance into multiple sub-instances that each correspond to discrete namespaced key ranges.
<a name="multiproc"></a>
Multi-process access
--------------------
LevelDB is thread-safe but is **not** suitable for accessing with multiple processes. You should only ever have a LevelDB database open from a single Node.js process. Node.js clusters are made up of multiple processes so a LevelUP instance cannot be shared between them either.
See the <a href="https://github.com/rvagg/node-levelup/wiki/Modules"><b>wiki</b></a> for some LevelUP extensions, including [multilevel](https://github.com/juliangruber/multilevel), that may help if you require a single data store to be shared across processes.
<a name="support"></a>
Getting support
---------------
There are multiple ways you can find help in using LevelDB in Node.js:
* **IRC:** you'll find an active group of LevelUP users in the **##leveldb** channel on Freenode, including most of the contributors to this project.
* **Mailing list:** there is an active [Node.js LevelDB](https://groups.google.com/forum/#!forum/node-levelup) Google Group.
* **GitHub:** you're welcome to open an issue here on this GitHub repository if you have a question.
<a name="contributing"></a>

@@ -454,2 +677,4 @@ Contributing

<tr><th align="left">Paolo Fragomeni</th><td><a href="https://github.com/hij1nx">GitHub/hij1nx</a></td><td><a href="http://twitter.com/hij1nx">Twitter/@hij1nx</a></td></tr>
<tr><th align="left">Anton Whalley</th><td><a href="https://github.com/No9">GitHub/No9</a></td><td><a href="https://twitter.com/antonwhalley">Twitter/@antonwhalley</a></td></tr>
<tr><th align="left">Matteo Collina</th><td><a href="https://github.com/mcollina">GitHub/mcollina</a></td><td><a href="https://twitter.com/matteocollina">Twitter/@matteocollina</a></td></tr>
</tbody></table>

@@ -456,0 +681,0 @@

@@ -108,3 +108,3 @@ /* Copyright (c) 2012-2013 LevelUP contributors

assert.exception(
db.batch.bind(db)
db.batch.bind(db, null, {})
, { name: 'WriteError', message: 'batch() requires an array argument' }

@@ -123,2 +123,2 @@ , 'no-arg batch() throws'

}
})
})

@@ -105,2 +105,37 @@ /* Copyright (c) 2012-2013 LevelUP contributors

, 'batch() with chained interface': function (done) {
this.openTestDatabase(function (db) {
db.put('1', 'one', function (err) {
refute(err)
db.batch()
.put('one', '1')
.del('two')
.put('three', '3')
.clear()
.del('1')
.put('2', 'two')
.put('3', 'three')
.del('3')
.write(function (err) {
refute(err)
async.forEach(
[ 'one', 'three', '1', '2', '3']
, function (key, callback) {
db.get(key, function (err) {
if ([ 'one', 'three', '1', '3' ].indexOf(key) > -1)
assert(err)
else
refute(err)
callback()
})
}
, done
)
})
})
})
}
, 'batch() with can manipulate data from put()': function (done) {

@@ -204,2 +239,136 @@ // checks encoding and whatnot

}
, 'chained batch() arguments': {
'setUp': function (done) {
this.openTestDatabase(function (db) {
this.db = db
this.batch = db.batch()
done()
}.bind(this))
}
, 'test batch#put() with missing `value`': function () {
// value = undefined
assert.exception(this.batch.put.bind(this.batch, 'foo1'), function (err) {
console.log('err.name', err.name, 'err.message', err.message)
if (err.name != 'WriteError')
return false
if ('value cannot be `null` or `undefined`' != err.message)
return false
return true
})
// value = null
assert.exception(this.batch.put.bind(this.batch, 'foo1', null), function (err) {
if (err.name != 'WriteError')
return false
if ('value cannot be `null` or `undefined`' != err.message)
return false
return true
})
}
, 'test batch#put() with missing `key`': function () {
// key = undefined
assert.exception(this.batch.put.bind(this.batch, undefined, 'foo1'), function (err) {
if (err.name != 'WriteError')
return false
if ('key cannot be `null` or `undefined`' != err.message)
return false
return true
})
// key = null
assert.exception(this.batch.put.bind(this.batch, null, 'foo1'), function (err) {
if (err.name != 'WriteError')
return false
if ('key cannot be `null` or `undefined`' != err.message)
return false
return true
})
}
, 'test batch#put() with missing `key` and `value`': function () {
// undefined
assert.exception(this.batch.put.bind(this.batch), function (err) {
if (err.name != 'WriteError')
return false
if ('key cannot be `null` or `undefined`' != err.message)
return false
return true
})
// null
assert.exception(this.batch.put.bind(this.batch, null, null), function (err) {
if (err.name != 'WriteError')
return false
if ('key cannot be `null` or `undefined`' != err.message)
return false
return true
})
}
, 'test batch#del() with missing `key`': function () {
// key = undefined
assert.exception(this.batch.del.bind(this.batch, undefined, 'foo1'), function (err) {
if (err.name != 'WriteError')
return false
if ('key cannot be `null` or `undefined`' != err.message)
return false
return true
})
// key = null
assert.exception(this.batch.del.bind(this.batch, null, 'foo1'), function (err) {
if (err.name != 'WriteError')
return false
if ('key cannot be `null` or `undefined`' != err.message)
return false
return true
})
}
, 'test batch#write() with no callback': function () {
this.batch.write() // should not cause an error with no cb
}
, 'test batch operations after write()': {
'setUp': function (done) {
this.batch.put('foo', 'bar').put('boom', 'bang').del('foo').write(done)
this.verify = function (cb) {
assert.exception(cb, function (err) {
if (err.name != 'WriteError')
return false
if ('write() already called on this batch' != err.message)
return false
return true
})
}
}
, 'test put()': function () {
this.verify(function () {
this.batch.put('whoa', 'dude')
}.bind(this))
}
, 'test del()': function () {
this.verify(function () {
this.batch.del('foo')
}.bind(this))
}
, 'test clear()': function () {
this.verify(function () {
this.batch.clear()
}.bind(this))
}
, 'test write()': function () {
this.verify(function () {
this.batch.write()
}.bind(this))
}
}
}
})

@@ -119,3 +119,2 @@ /* Copyright (c) 2012-2013 LevelUP contributors

this.readySpy = this.spy()
this.dataSpy = this.spy()

@@ -138,3 +137,2 @@ this.endSpy = this.spy()

assert.isFalse(rs.readable)
assert.equals(this.readySpy.callCount, 1, 'ReadStream emitted single "ready" event')
assert.equals(this.endSpy.callCount, 1, 'ReadStream emitted single "end" event')

@@ -157,3 +155,4 @@ assert.equals(this.dataSpy.callCount, data.length, 'ReadStream emitted correct number of "data" events')

done()
}.bind(this))
}
}

@@ -81,2 +81,81 @@ /* Copyright (c) 2012-2013 LevelUP contributors

}
})
, 'test write-stream encoding': function (done) {
this.openTestDatabase({ encoding: 'json' }, function (db) {
var ws = db.createWriteStream({
keyEncoding : 'utf8',
valueEncoding : 'binary'
})
ws.on('close', function () {
db.get('foo', {
keyEncoding : 'utf8',
valueEncoding : 'binary'
}, function (err, val) {
refute(err)
assert.equals(val.toString(), '\u0001\u0002\u0003')
db.close(done)
})
})
ws.write({ key : 'foo', value : new Buffer([1, 2, 3]) })
ws.end()
})
}
, 'test write-stream chunk encoding': function (done) {
this.openTestDatabase({ encoding: 'json' }, function (db) {
var ws = db.createWriteStream({
keyEncoding : 'utf8',
valueEncoding : 'binary'
})
ws.on('close', function () {
db.get(new Buffer([1, 2, 3]), {
keyEncoding : 'binary',
valueEncoding : 'json'
}, function (err, val) {
refute(err)
assert.equals(val.some, 'json')
db.close(done)
})
})
ws.write({
key : new Buffer([1, 2, 3]),
value : { some : 'json' },
keyEncoding : 'binary',
valueEncoding : 'json'
})
ws.end()
})
}
, 'test batch op encoding': function (done) {
this.openTestDatabase({ encoding: 'json' }, function (db) {
db.batch([
{
type : 'put',
key : new Buffer([1, 2, 3]),
value : new Buffer([4, 5, 6]),
keyEncoding : 'binary',
valueEncoding : 'binary'
}
, {
type : 'put',
key : 'string',
value : 'string'
}
], { keyEncoding : 'utf8', valueEncoding : 'utf8' },
function (err) {
refute(err)
db.get(new Buffer([1, 2, 3]), {
keyEncoding : 'binary',
valueEncoding : 'binary'
}, function (err, val) {
refute(err)
assert.equals(val.toString(), '\u0004\u0005\u0006')
db.get('string', { valueEncoding : 'utf8' }, function (err, val) {
refute(err)
assert.equals(val, 'string')
db.close(done)
})
})
})
})
}
})

@@ -15,3 +15,2 @@ /* Copyright (c) 2012-2013 LevelUP contributors

common.commonSetUp.call(this, function () {
this.readySpy = this.spy()
this.dataSpy = this.spy()

@@ -38,3 +37,2 @@ this.endSpy = this.spy()

assert.isFalse(rs.readable)
assert.equals(this.readySpy.callCount, 1, 'Stream emitted single "ready" event')
assert.equals(this.endSpy.callCount, 1, 'Stream emitted single "end" event')

@@ -68,3 +66,2 @@ assert.equals(this.dataSpy.callCount, data.length, 'Stream emitted correct number of "data" events')

assert.isTrue(rs.readable)
rs.on('ready', this.readySpy)
rs.on('data', this.dataSpy)

@@ -86,3 +83,2 @@ rs.on('end', this.endSpy)

assert.isTrue(rs.readable)
rs.on('ready', this.readySpy)
rs.on('data', this.dataSpy)

@@ -104,3 +100,2 @@ rs.on('end', this.endSpy)

assert.isTrue(rs.readable)
rs.on('ready', this.readySpy)
rs.on('data', this.dataSpy)

@@ -122,3 +117,2 @@ rs.on('end', this.endSpy)

assert.isTrue(rs.readable)
rs.on('ready', this.readySpy)
rs.on('data', this.dataSpy)

@@ -130,2 +124,2 @@ rs.on('end', this.endSpy)

}
})
})

@@ -35,3 +35,2 @@ /* Copyright (c) 2012-2013 LevelUP contributors

assert.isTrue(rs.readable)
rs.on('ready', this.readySpy)
rs.on('data' , this.dataSpy)

@@ -75,3 +74,2 @@ rs.on('end' , this.endSpy)

assert.isTrue(rs.readable)
rs.on('ready', this.readySpy)
rs.on('data' , this.dataSpy)

@@ -93,3 +91,2 @@ rs.on('end' , this.endSpy)

assert.isTrue(rs.readable)
rs.on('ready', this.readySpy)
rs.on('data' , this.dataSpy)

@@ -100,5 +97,4 @@ rs.on('end' , this.endSpy)

assert.isFalse(rs.readable)
assert.equals(this.readySpy.callCount, 0, '"ready" event was not fired')
assert.equals(this.dataSpy.callCount , 0, '"data" event was not fired')
assert.equals(this.endSpy.callCount , 0, '"end" event was not fired')
assert.equals(this.endSpy.callCount , 1, '"end" event was not fired')
done()

@@ -125,3 +121,2 @@ }.bind(this))

assert.isTrue(rs.readable)
rs.on('ready', this.readySpy)
rs.on('data' , this.dataSpy)

@@ -132,3 +127,3 @@ rs.on('end' , endSpy)

assert.isFalse(rs.readable)
assert.equals(this.readySpy.callCount, 1, 'ReadStream emitted single "ready" event')
// assert.equals(this.readySpy.callCount, 1, 'ReadStream emitted single "ready" event')
// should do "data" 5 times ONLY

@@ -162,3 +157,2 @@ assert.equals(this.dataSpy.callCount, 5, 'ReadStream emitted correct number of "data" events (5)')

assert.isTrue(rs.readable)
rs.on('ready', this.readySpy)
rs.on('data' , this.dataSpy)

@@ -181,3 +175,2 @@ rs.on('end' , this.endSpy)

assert.isTrue(rs.readable)
rs.on('ready', this.readySpy)
rs.on('data' , this.dataSpy)

@@ -201,3 +194,2 @@ rs.on('end' , this.endSpy)

assert.isTrue(rs.readable)
rs.on('ready', this.readySpy)
rs.on('data' , this.dataSpy)

@@ -223,3 +215,2 @@ rs.on('end' , this.endSpy)

assert.isTrue(rs.readable)
rs.on('ready', this.readySpy)
rs.on('data' , this.dataSpy)

@@ -243,3 +234,2 @@ rs.on('end' , this.endSpy)

assert.isTrue(rs.readable)
rs.on('ready', this.readySpy)
rs.on('data' , this.dataSpy)

@@ -266,3 +256,2 @@ rs.on('end' , this.endSpy)

assert.isTrue(rs.readable)
rs.on('ready', this.readySpy)
rs.on('data' , this.dataSpy)

@@ -286,3 +275,2 @@ rs.on('end' , this.endSpy)

assert.isTrue(rs.readable)
rs.on('ready', this.readySpy)
rs.on('data' , this.dataSpy)

@@ -306,3 +294,2 @@ rs.on('end' , this.endSpy)

assert.isTrue(rs.readable)
rs.on('ready', this.readySpy)
rs.on('data' , this.dataSpy)

@@ -326,3 +313,2 @@ rs.on('end' , this.endSpy)

assert.isTrue(rs.readable)
rs.on('ready', this.readySpy)
rs.on('data' , this.dataSpy)

@@ -346,3 +332,2 @@ rs.on('end' , this.endSpy)

assert.isTrue(rs.readable)
rs.on('ready', this.readySpy)
rs.on('data' , this.dataSpy)

@@ -366,3 +351,2 @@ rs.on('end' , this.endSpy)

assert.isTrue(rs.readable)
rs.on('ready', this.readySpy)
rs.on('data' , this.dataSpy)

@@ -386,3 +370,2 @@ rs.on('end' , this.endSpy)

assert.isTrue(rs.readable)
rs.on('ready', this.readySpy)
rs.on('data' , this.dataSpy)

@@ -420,3 +403,2 @@ rs.on('end' , this.endSpy)

assert.isTrue(rs.readable)
rs.on('ready', this.readySpy)
rs.on('data' , this.dataSpy)

@@ -441,3 +423,2 @@ rs.on('end' , this.endSpy)

assert.isTrue(rs.readable)
rs.on('ready', this.readySpy)
rs.on('data' , this.dataSpy)

@@ -460,3 +441,2 @@ rs.on('end' , this.endSpy)

assert.isTrue(rs.readable)
rs.on('ready', this.readySpy)
rs.on('data' , this.dataSpy)

@@ -480,3 +460,2 @@ rs.on('end' , this.endSpy)

assert.isTrue(rs.readable)
rs.on('ready', this.readySpy)
rs.on('data' , this.dataSpy)

@@ -566,3 +545,2 @@ rs.on('end' , this.endSpy)

assert.isTrue(rs.readable)
rs.on('ready', this.readySpy)
rs.on('data' , this.dataSpy)

@@ -594,3 +572,2 @@ rs.on('end' , this.endSpy)

assert.isTrue(rs.readable)
rs.on('ready', this.readySpy)
rs.on('data' , this.dataSpy)

@@ -613,3 +590,3 @@ rs.on('end' , this.endSpy)

assert.isTrue(rs.readable)
rs.on('ready', this.readySpy)
//rs.on('ready', this.readySpy)
rs.on('data' , this.dataSpy)

@@ -632,3 +609,2 @@ rs.on('end' , this.endSpy)

assert.isTrue(rs.readable)
rs.on('ready', this.readySpy)
rs.on('data' , this.dataSpy)

@@ -651,3 +627,2 @@ rs.on('end' , this.endSpy)

assert.isTrue(rs.readable)
rs.on('ready', this.readySpy)
rs.on('data' , this.dataSpy)

@@ -700,2 +675,2 @@ rs.on('end' , this.endSpy)

}
})
})

@@ -34,3 +34,2 @@ /* Copyright (c) 2012-2013 LevelUP contributors

rs = rs.pipe(new SlowStream({ maxWriteInterval: 5 }))
this.readySpy()
rs.on('data' , this.dataSpy)

@@ -71,2 +70,2 @@ rs.once('end' , this.endSpy)

}
})
})

@@ -210,2 +210,249 @@ /* Copyright (c) 2012-2013 LevelUP contributors

}
})
, 'test del capabilities for each key/value': function (done) {
var options = { createIfMissing: true, errorIfExists: true, keyEncoding: 'utf8', valueEncoding: 'json' }
, data = [
{ type: 'put', key: 'aa', value: { a: 'complex', obj: 100 } }
, { type: 'put', key: 'ab', value: { b: 'foo', bar: [ 1, 2, 3 ] } }
, { type: 'put', key: 'ac', value: { c: 'w00t', d: { e: [ 0, 10, 20, 30 ], f: 1, g: 'wow' } } }
, { type: 'put', key: 'ba', value: { a: 'complex', obj: 100 } }
, { type: 'put', key: 'bb', value: { b: 'foo', bar: [ 1, 2, 3 ] } }
, { type: 'put', key: 'bc', value: { c: 'w00t', d: { e: [ 0, 10, 20, 30 ], f: 1, g: 'wow' } } }
, { type: 'put', key: 'ca', value: { a: 'complex', obj: 100 } }
, { type: 'put', key: 'cb', value: { b: 'foo', bar: [ 1, 2, 3 ] } }
, { type: 'put', key: 'cc', value: { c: 'w00t', d: { e: [ 0, 10, 20, 30 ], f: 1, g: 'wow' } } }
]
async.waterfall([
function(cb) {
this.openTestDatabase(options, function (db) {
cb(null, db);
});
}.bind(this),
function(db, cb) {
var ws = db.createWriteStream()
ws.on('error', function (err) {
refute(err)
})
ws.on('close', function() {
cb(null, db);
})
data.forEach(function (d) {
ws.write(d)
})
// end after it's ready, nextTick makes this work OK
ws.once('ready', ws.end)
},
function(db, cb) {
var delStream = db.createWriteStream()
delStream.on('error', function (err) {
refute(err)
})
delStream.on('close', function() {
cb(null, db);
})
data.forEach(function (d) {
d.type = 'del'
delStream.write(d)
})
// end after it's ready, nextTick makes this work OK
delStream.once('ready', delStream.end)
},
function(db, cb) {
async.forEach(
data
, function (data, callback) {
db.get(data.key, function (err, value) {
// none of them should exist
assert(err)
refute(value)
callback()
})
}
, cb
)
}
], done)
}
, 'test del capabilities as constructor option': function (done) {
var options = { createIfMissing: true, errorIfExists: true, keyEncoding: 'utf8', valueEncoding: 'json' }
, data = [
{ key: 'aa', value: { a: 'complex', obj: 100 } }
, { key: 'ab', value: { b: 'foo', bar: [ 1, 2, 3 ] } }
, { key: 'ac', value: { c: 'w00t', d: { e: [ 0, 10, 20, 30 ], f: 1, g: 'wow' } } }
, { key: 'ba', value: { a: 'complex', obj: 100 } }
, { key: 'bb', value: { b: 'foo', bar: [ 1, 2, 3 ] } }
, { key: 'bc', value: { c: 'w00t', d: { e: [ 0, 10, 20, 30 ], f: 1, g: 'wow' } } }
, { key: 'ca', value: { a: 'complex', obj: 100 } }
, { key: 'cb', value: { b: 'foo', bar: [ 1, 2, 3 ] } }
, { key: 'cc', value: { c: 'w00t', d: { e: [ 0, 10, 20, 30 ], f: 1, g: 'wow' } } }
]
async.waterfall([
function(cb) {
this.openTestDatabase(options, function (db) {
cb(null, db);
});
}.bind(this),
function(db, cb) {
var ws = db.createWriteStream()
ws.on('error', function (err) {
refute(err)
})
ws.on('close', function() {
cb(null, db);
})
data.forEach(function (d) {
ws.write(d)
})
// end after it's ready, nextTick makes this work OK
ws.once('ready', ws.end)
},
function(db, cb) {
var delStream = db.createWriteStream({ type: 'del' })
delStream.on('error', function (err) {
refute(err)
})
delStream.on('close', function() {
cb(null, db);
})
data.forEach(function (d) {
delStream.write(d)
})
// end after it's ready, nextTick makes this work OK
delStream.once('ready', delStream.end)
},
function(db, cb) {
async.forEach(
data
, function (data, callback) {
db.get(data.key, function (err, value) {
// none of them should exist
assert(err)
refute(value)
callback()
})
}
, cb
)
}
], done)
}
, 'test type at key/value level must take precedence on the constructor': function (done) {
var options = { createIfMissing: true, errorIfExists: true, keyEncoding: 'utf8', valueEncoding: 'json' }
, data = [
{ key: 'aa', value: { a: 'complex', obj: 100 } }
, { key: 'ab', value: { b: 'foo', bar: [ 1, 2, 3 ] } }
, { key: 'ac', value: { c: 'w00t', d: { e: [ 0, 10, 20, 30 ], f: 1, g: 'wow' } } }
, { key: 'ba', value: { a: 'complex', obj: 100 } }
, { key: 'bb', value: { b: 'foo', bar: [ 1, 2, 3 ] } }
, { key: 'bc', value: { c: 'w00t', d: { e: [ 0, 10, 20, 30 ], f: 1, g: 'wow' } } }
, { key: 'ca', value: { a: 'complex', obj: 100 } }
, { key: 'cb', value: { b: 'foo', bar: [ 1, 2, 3 ] } }
, { key: 'cc', value: { c: 'w00t', d: { e: [ 0, 10, 20, 30 ], f: 1, g: 'wow' } } }
]
, exception = data[0]
exception['type'] = 'put'
async.waterfall([
function(cb) {
this.openTestDatabase(options, function (db) {
cb(null, db);
});
}.bind(this),
function(db, cb) {
var ws = db.createWriteStream()
ws.on('error', function (err) {
refute(err)
})
ws.on('close', function() {
cb(null, db);
})
data.forEach(function (d) {
ws.write(d)
})
// end after it's ready, nextTick makes this work OK
ws.once('ready', ws.end)
},
function(db, cb) {
var delStream = db.createWriteStream({ type: 'del' })
delStream.on('error', function (err) {
refute(err)
})
delStream.on('close', function() {
cb(null, db);
})
data.forEach(function (d) {
delStream.write(d)
})
// end after it's ready, nextTick makes this work OK
delStream.once('ready', delStream.end)
},
function(db, cb) {
async.forEach(
data
, function (data, callback) {
db.get(data.key, function (err, value) {
if (data.type === 'put') {
assert(value)
callback()
} else {
assert(err)
refute(value)
callback()
}
})
}
, cb
)
}
], done)
}
, 'test ignoring pairs with the wrong type': function (done) {
async.waterfall([
function(cb) {
this.openTestDatabase(cb.bind(null, null))
}.bind(this),
function(db, cb) {
var ws = db.createWriteStream()
ws.on('error', function (err) {
refute(err)
})
ws.on('close', cb.bind(null, db))
this.sourceData.forEach(function (d) {
d.type = "x" + Math.random()
ws.write(d)
})
ws.once('ready', ws.end) // end after it's ready, nextTick makes this work OK
}.bind(this),
function(db, cb) {
async.forEach(
this.sourceData
, function (data, callback) {
db.get(data.key, function (err, value) {
assert(err)
refute(value)
callback()
})
}
, cb
)
}.bind(this)
], done)
}
})

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