Skip to content
This repository was archived by the owner on Dec 1, 2024. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 19 additions & 72 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,12 @@ LevelUP

**Fast & simple storage - a Node.js-style LevelDB wrapper**

[![Build Status](https://secure.travis-ci.org/Level/levelup.svg?branch=master)](http://travis-ci.org/Level/levelup) [![dependencies](https://david-dm.org/Level/levelup.svg)](https://david-dm.org/level/levelup) [![Greenkeeper badge](https://badges.greenkeeper.io/Level/levelup.svg)](https://greenkeeper.io/)
[![Build Status](https://secure.travis-ci.org/Level/levelup.svg?branch=master)](http://travis-ci.org/Level/levelup)
[![dependencies](https://david-dm.org/Level/levelup.svg)](https://david-dm.org/level/levelup)
[![Greenkeeper badge](https://badges.greenkeeper.io/Level/levelup.svg)](https://greenkeeper.io/)

[![NPM](https://nodei.co/npm/levelup.png?stars&downloads&downloadRank)](https://nodei.co/npm/levelup/) [![NPM](https://nodei.co/npm-dl/levelup.png?months=6&height=3)](https://nodei.co/npm/levelup/)
[![NPM](https://nodei.co/npm/levelup.png?stars&downloads&downloadRank)](https://nodei.co/npm/levelup/)
[![NPM](https://nodei.co/npm-dl/levelup.png?months=6&height=3)](https://nodei.co/npm/levelup/)


* <a href="#intro">Introduction</a>
Expand All @@ -17,8 +20,6 @@ LevelUP
* <a href="#api">API</a>
* <a href="#promises">Promise Support</a>
* <a href="#events">Events</a>
* <a href="#json">JSON data</a>
* <a href="#custom_encodings">Custom encodings</a>
* <a href="#extending">Extending LevelUP</a>
* <a href="#multiproc">Multi-process access</a>
* <a href="#support">Getting support</a>
Expand All @@ -31,7 +32,7 @@ Introduction

**[LevelDB](https://github.com/google/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://google.github.io/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**.
**LevelUP** aims to expose the features of LevelDB in a **Node.js-friendly way**. LevelDB's iterators are exposed as a Node.js-style **readable stream**.

LevelDB stores entries **sorted lexicographically by keys**. This makes LevelUP's <a href="#createReadStream"><code>ReadStream</code></a> interface a very powerful query mechanism.

Expand Down Expand Up @@ -129,6 +130,8 @@ db.put('name', 'LevelUP', function (err) {
### levelup(db[, options[, callback]])
<code>levelup()</code> is the main entry point for creating a new LevelUP instance and opening the underlying store with LevelDB.

`db` is an [`abstract-leveldown`](https://github.com/level/abstract-leveldown) compliant object.

This function returns a new instance of LevelUP and will also initiate an <a href="#open"><code>open()</code></a> operation. Opening the database is an asynchronous operation which will trigger your callback if you provide one. The callback should take the form: `function (err, db) {}` where the `db` is the LevelUP instance. If you don't provide a callback, any read & write operations are simply queued internally until the database is fully opened.

This leads to two alternative ways of managing a new LevelUP instance:
Expand All @@ -151,16 +154,7 @@ db.get('foo', function (err, value) {
})
```

#### `options`

`levelup()` takes an optional options object as its second argument; the following properties are accepted:

* `'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>
<p>Supported encodings are: hex, utf8, ascii, binary, base64, ucs2, utf16le.</p>
<p><code>'json'</code> encoding is also supported, see below.</p>

Additionally, each of the main interface methods accept an optional options object that can be used to override `'keyEncoding'` and `'valueEncoding'`.
`options` is passed on to the underlying store when it's opened.

--------------------------------------------------------
<a name="open"></a>
Expand All @@ -185,11 +179,9 @@ If no callback is passed, a promise is returned.
### db.put(key, value[, options][, callback])
<code>put()</code> is the primary method for inserting data into the store. Both the `key` and `value` can be arbitrary data objects.

If no callback is passed, a promise is returned.

#### `options`
`options` is passed on to the underlying store.

Encoding of the `key` and `value` objects will adhere to `'keyEncoding'` and `'valueEncoding'` options provided to <a href="#ctor"><code>levelup()</code></a>, although you can provide alternative encoding settings in the options for `put()` (it's recommended that you stay consistent in your encoding of keys and values in a single store).
If no callback is passed, a promise is returned.

--------------------------------------------------------
<a name="get"></a>
Expand All @@ -211,11 +203,9 @@ db.get('foo', function (err, value) {
})
```

If no callback is passed, a promise is returned.

#### `options`
`options` is passed on to the underlying store.

Encoding of the `key` and `value` objects is the same as in <a href="#put"><code>put</code></a>.
If no callback is passed, a promise is returned.

--------------------------------------------------------
<a name="del"></a>
Expand All @@ -228,11 +218,9 @@ db.del('foo', function (err) {
});
```

If no callback is passed, a promise is returned.

#### `options`
`options` is passed on to the underlying store.

Encoding of the `key` object will adhere to the `'keyEncoding'` option provided to <a href="#ctor"><code>levelup()</code></a>, although you can provide alternative encoding settings in the options for `del()` (it's recommended that you stay consistent in your encoding of keys and values in a single store).
If no callback is passed, a promise is returned.

--------------------------------------------------------
<a name="batch"></a>
Expand All @@ -258,23 +246,9 @@ db.batch(ops, function (err) {
})
```

If no callback is passed, a promise is returned.

#### `options`

See <a href="#put"><code>put()</code></a> for a discussion on the `options` object. You can overwrite default `'keyEncoding'` and `'valueEncoding'`.
`options` is passed on to the underlying store.

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'
}]
```
If no callback is passed, a promise is returned.

--------------------------------------------------------
<a name="batch_chained"></a>
Expand All @@ -291,20 +265,16 @@ db.batch()
.write(function () { console.log('Done!') })
```

<b><code>batch.put(key, value[, options])</code></b>
<b><code>batch.put(key, value)</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'`.

This method may `throw` a `WriteError` if there is a problem with your put (such as the `value` being `null` or `undefined`).

<b><code>batch.del(key[, options])</code></b>
<b><code>batch.del(key)</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'`.

This method may `throw` a `WriteError` if there is a problem with your delete.

<b><code>batch.clear()</code></b>
Expand Down Expand Up @@ -383,8 +353,6 @@ Additionally, you can supply an options object as the first parameter to `create

* `'limit'` *(number, default: `-1`)*: limit the number of results collected by this stream. This number represents a *maximum* number of results and may not be reached if you get to the end of the data first. A value of `-1` means there is no limit. When `reverse=true` the highest keys will be returned instead of the lowest keys.

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

--------------------------------------------------------
<a name="createKeyStream"></a>
### db.createKeyStream([options])
Expand Down Expand Up @@ -495,27 +463,6 @@ LevelUP emits events when the callbacks to the corresponding methods are called.

If you do not pass a callback to an async function, and there is an error, LevelUP will `emit('error', err)` instead.

<a name="json"></a>
JSON data
---------

You specify `'json'` encoding for both keys and/or values, you can then supply JavaScript objects to LevelUP and receive them from all fetch operations, including ReadStreams. LevelUP will automatically *stringify* your objects and store them as *utf8* and parse the strings back into objects before passing them back to you.

<a name="custom_encodings"></a>
Custom encodings
----------------

A custom encoding may be provided by passing in an object as a value for `keyEncoding` or `valueEncoding` (wherever accepted), it must have the following properties:

```js
{
encode: function (val) { ... },
decode: function (val) { ... },
buffer: boolean, // encode returns a buffer and decode accepts a buffer
type: String // name of this encoding type.
}
```

<a name="extending"></a>
Extending LevelUP
-----------------
Expand Down
25 changes: 6 additions & 19 deletions lib/batch.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,17 @@
* <https://github.com/level/levelup/blob/master/LICENSE.md>
*/

var util = require('./util')
var WriteError = require('level-errors').WriteError
var getOptions = util.getOptions
var dispatchError = util.dispatchError
var promisify = util.promisify
var promisify = require('./promisify')

function Batch (levelup, codec) {
function Batch (levelup) {
this._levelup = levelup
this._codec = codec
this.batch = levelup.db.batch()
this.ops = []
this.length = 0
}

Batch.prototype.put = function (key_, value_, options) {
options = getOptions(options)

var key = this._codec.encodeKey(key_, options)
var value = this._codec.encodeValue(value_, options)

Batch.prototype.put = function (key, value) {
try {
this.batch.put(key, value)
} catch (e) {
Expand All @@ -36,11 +27,7 @@ Batch.prototype.put = function (key_, value_, options) {
return this
}

Batch.prototype.del = function (key_, options) {
options = getOptions(options)

var key = this._codec.encodeKey(key_, options)

Batch.prototype.del = function (key) {
try {
this.batch.del(key)
} catch (err) {
Expand Down Expand Up @@ -75,9 +62,9 @@ Batch.prototype.write = function (callback) {

try {
this.batch.write(function (err) {
if (err) { return dispatchError(levelup, new WriteError(err), callback) }
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moar complexity gone! 🕺 💃

if (err) { return callback(new WriteError(err)) }
levelup.emit('batch', ops)
if (callback) { callback() }
callback()
})
} catch (err) {
throw new WriteError(err)
Expand Down
Loading