Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

subleveldown

Package Overview
Dependencies
Maintainers
4
Versions
23
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

subleveldown - npm Package Compare versions

Comparing version 2.1.0 to 3.0.0-rc1

CHANGELOG.md

7

index.js
var subdown = require('./leveldown')
var levelup = require('levelup')
var encoding = require('encoding-down')

@@ -8,7 +9,3 @@ module.exports = function (db, prefix, opts) {

opts.db = function () {
return subdown(db, prefix, opts)
}
return levelup(opts)
return levelup(encoding(subdown(db, prefix, opts), opts), opts)
}

@@ -1,21 +0,27 @@

var util = require('util')
var inherits = require('inherits')
var abstract = require('abstract-leveldown')
var wrap = require('level-option-wrap')
var END = new Buffer([0xff])
var END = Buffer.from([0xff])
var concat = function (prefix, key, force) {
function concat (prefix, key, force) {
if (typeof key === 'string' && (force || key.length)) return prefix + key
if (Buffer.isBuffer(key) && (force || key.length)) return Buffer.concat([new Buffer(prefix), key])
if (Buffer.isBuffer(key) && (force || key.length)) {
return Buffer.concat([Buffer.from(prefix), key])
}
return key
}
var SubIterator = function (ite, prefix) {
function SubIterator (ite, prefix) {
this.iterator = ite
this.prefix = prefix
abstract.AbstractIterator.call(this)
}
SubIterator.prototype.next = function (cb) {
inherits(SubIterator, abstract.AbstractIterator)
SubIterator.prototype._next = function (cb) {
var self = this
this.iterator.next(cb && function (err, key, value) {
this.iterator.next(function (err, key, value) {
if (err) return cb(err)

@@ -27,7 +33,7 @@ if (key) key = key.slice(self.prefix.length)

SubIterator.prototype.end = function (cb) {
SubIterator.prototype._end = function (cb) {
this.iterator.end(cb)
}
var SubDown = function (db, prefix, opts) {
function SubDown (db, prefix, opts) {
if (!(this instanceof SubDown)) return new SubDown(db, prefix, opts)

@@ -64,5 +70,5 @@ if (typeof opts === 'string') opts = {separator: opts}

util.inherits(SubDown, abstract.AbstractLevelDOWN)
inherits(SubDown, abstract.AbstractLevelDOWN)
SubDown.prototype.type = 'subdown'
SubDown.prototype.type = 'subleveldown'

@@ -72,41 +78,35 @@ SubDown.prototype._open = function (opts, cb) {

if (this.db.isOpen()) {
if (this.db.db.type === 'subdown' && this.db.db.prefix) {
this.prefix = this.db.db.prefix + this.prefix
this.leveldown = this.db.db.leveldown
this.db.open(function (err) {
if (err) return cb(err)
var subdb = down(self.db, 'subleveldown')
if (subdb && subdb.prefix) {
self.prefix = subdb.prefix + self.prefix
self.leveldown = down(subdb.db)
} else {
this.leveldown = this.db.db
self.leveldown = down(self.db)
}
return done()
}
this.db.on('open', this.open.bind(this, opts, done))
function done (err) {
if (err || !self._beforeOpen) return cb(err)
self._beforeOpen(cb)
}
if (self._beforeOpen) self._beforeOpen(cb)
else cb()
})
}
SubDown.prototype.close = function () {
this.leveldown.close.apply(this.leveldown, arguments)
SubDown.prototype._close = function (cb) {
this.leveldown.close(cb)
}
SubDown.prototype.setDb = function () {
this.leveldown.setDb.apply(this.leveldown, arguments)
}
SubDown.prototype.put = function (key, value, opts, cb) {
SubDown.prototype._put = function (key, value, opts, cb) {
this.leveldown.put(concat(this.prefix, key), value, opts, cb)
}
SubDown.prototype.get = function (key, opts, cb) {
SubDown.prototype._get = function (key, opts, cb) {
this.leveldown.get(concat(this.prefix, key), opts, cb)
}
SubDown.prototype.del = function (key, opts, cb) {
SubDown.prototype._del = function (key, opts, cb) {
this.leveldown.del(concat(this.prefix, key), opts, cb)
}
SubDown.prototype.batch =
SubDown.prototype._batch = function (operations, opts, cb) {

@@ -125,19 +125,3 @@ if (arguments.length === 0) return new abstract.AbstractChainedBatch(this)

SubDown.prototype.approximateSize = function (start, end, cb) {
this.leveldown.approximateSize.apply(this.leveldown, arguments)
}
SubDown.prototype.getProperty = function () {
return this.leveldown.getProperty.apply(this.leveldown, arguments)
}
SubDown.prototype.destroy = function () {
return this.leveldown.destroy.apply(this.leveldown, arguments)
}
SubDown.prototype.repair = function () {
return this.leveldown.repair.apply(this.leveldown, arguments)
}
var extend = function (xopts, opts) {
function extend (xopts, opts) {
xopts.keys = opts.keys

@@ -158,8 +142,7 @@ xopts.values = opts.values

var fixRange = function (opts) {
function fixRange (opts) {
return (!opts.reverse || (!opts.end && !opts.start)) ? opts : {start: opts.end, end: opts.start}
}
SubDown.prototype.iterator = function (opts) {
if (!opts) opts = {}
SubDown.prototype._iterator = function (opts) {
var xopts = extend(wrap(fixRange(opts), this._wrap), opts)

@@ -170,1 +153,18 @@ return new SubIterator(this.leveldown.iterator(xopts), this.prefix)

module.exports = SubDown
function down (db, type) {
if (typeof db.down === 'function') return db.down(type)
if (type && db.type === type) return db
if (isAbstract(db.db)) return down(db.db, type)
if (isAbstract(db._db)) return down(db._db, type)
return type ? null : db
}
function isAbstract (db) {
if (!db || typeof db !== 'object') { return false }
return Object.keys(abstract.AbstractLevelDOWN.prototype).filter(function (name) {
return name[0] !== '_'
}).every(function (name) {
return typeof db[name] === 'function'
})
}
{
"name": "subleveldown",
"version": "2.1.0",
"version": "3.0.0-rc1",
"description": "sublevels implemented using leveldowns",
"main": "index.js",
"dependencies": {
"abstract-leveldown": "^2.4.1",
"abstract-leveldown": "^5.0.0",
"encoding-down": "^5.0.3",
"inherits": "^2.0.3",
"level-option-wrap": "^1.1.0",
"levelup": "^1.2.1"
"levelup": "^3.0.1"
},
"devDependencies": {
"memdown": "^1.1.0",
"standard": "^5.3.1",
"tape": "^4.2.2"
"memdown": "^3.0.0",
"standard": "^11.0.1",
"tape": "^4.9.0"
},
"repository": {
"type": "git",
"url": "https://github.com/mafintosh/subleveldown.git"
"url": "https://github.com/level/subleveldown.git"
},

@@ -23,5 +25,5 @@ "author": "Mathias Buus (@mafintosh)",

"bugs": {
"url": "https://github.com/mafintosh/subleveldown/issues"
"url": "https://github.com/level/subleveldown/issues"
},
"homepage": "https://github.com/mafintosh/subleveldown",
"homepage": "https://github.com/level/subleveldown",
"directories": {

@@ -32,3 +34,6 @@ "test": "test"

"test": "standard && node test"
},
"engines": {
"node": ">=6"
}
}
# subleveldown
Sublevels implemented using leveldowns
> Sublevels on top of [`levelup`][levelup] with different encodings for each sublevel.
```
npm install subleveldown
```
[![level badge][level-badge]](https://github.com/level/awesome)
[![npm](https://img.shields.io/npm/v/subleveldown.svg)](https://www.npmjs.com/package/subleveldown)
![Node version](https://img.shields.io/node/v/subleveldown.svg)
[![Travis](https://img.shields.io/travis/Level/subleveldown.svg?style=flat)](http://travis-ci.org/Level/subleveldown)
[![dependencies](https://img.shields.io/david/Level/subleveldown.svg)](https://david-dm.org/level/subleveldown)
[![npm](https://img.shields.io/npm/dm/subleveldown.svg)](https://www.npmjs.com/package/subleveldown)
[![JavaScript Style Guide](https://img.shields.io/badge/code_style-standard-brightgreen.svg)](https://standardjs.com)
[![build status](http://img.shields.io/travis/mafintosh/subleveldown.svg?style=flat)](http://travis-ci.org/mafintosh/subleveldown)
## Table of Contents
<details><summary>Click to expand</summary>
- [Usage](#usage)
- [Background](#background)
- [API](#api)
- [Install](#install)
- [License](#license)
</details>
## Usage
**If you are upgrading:** please see [UPGRADING.md](UPGRADING.md).
``` js

@@ -31,11 +47,49 @@ var sub = require('subleveldown')

## Background
`subleveldown` separates a [`levelup`][levelup] database into sections - or *sublevels* from here on out. Think SQL tables, but evented, ranged and realtime!
Each sublevel is a `levelup` of its own. This means it has the exact same interface as its parent database, but its own keyspace and [events](https://github.com/Level/levelup#events). In addition, sublevels are individually wrapped with [`encoding-down`][encoding-down], giving us per-sublevel encodings. For example, it's possible to have one sublevel with Buffer keys and another with `'utf8'` encoded keys. The same goes for values. Like so:
```js
sub(db, 'one', { valueEncoding: 'json' })
sub(db, 'two', { keyEncoding: 'binary' })
```
There is one limitation, however: keys must *encode to* either strings or Buffers. This is not likely to affect you, unless you use custom encodings or the `id` encoding (which bypasses encodings and thus makes it your responsibility to ensure keys are either strings or Buffers).
Authored by [@mafintosh](https://github.com/mafintosh) and inspired by [`level-sublevel`][level-sublevel] by [@dominictarr](https://github.com/dominictarr), `subleveldown` has become an official part of [Level][level-org]. As `level-sublevel` is no longer under active development, we recommend switching to `subleveldown` to get the latest and greatest of the Level ecosystem. These two modules largely offer the same functionality, except for [hooks](https://github.com/dominictarr/level-sublevel#hooks) and [per-batch prefixes](https://github.com/dominictarr/level-sublevel#batches).
## API
#### `subdb = sub(db, [prefix], [options])`
### `subdb = sub(db[, prefix][, options])`
Returns a levelup instance that uses the subleveldown with `prefix`.
The `options` argument is passed to the [levelup](https://github.com/rvagg/node-levelup) constructor
Returns a `levelup` instance that uses subleveldown to prefix the keys of the underlying store of `db`. The required `db` parameter must be a `levelup` instance. Any layers that this instance may have (like `encoding-down` or `subleveldown` itself) are peeled off to get to the innermost [`abstract-leveldown`][abstract-leveldown] compliant store (like `leveldown`). This ensures there is no double encoding step.
The `prefix` must be a string. If omitted, the effective prefix is two separators, e.g. `'!!'`. If `db` is already a subleveldown-powered instance, the effective prefix is a combined prefix, e.g. `'!one!!two!'`.
The optional `options` parameter has the following `subleveldown` specific properties:
* `separator` *(string, default: `'!'`)* Character for separating sublevel prefixes from user keys and each other. Should be outside the character (or byte) range of user keys.
* `open` *(function)* Optional open hook called when the underlying `levelup` instance has been opened. The hook receives a callback which must be called to finish opening.
Any other `options` are passed along to the underlying [`levelup`][levelup] and [`encoding-down`][encoding-down] constructors. See their documentation for further details.
## Install
With [npm](https://npmjs.org) do:
```
npm i subleveldown -S
```
## License
MIT
MIT © 2014-present [Mathias Buus](https://github.com/mafintosh) and [contributors](https://github.com/Level/subleveldown/graphs/contributors). See the included [LICENSE](./LICENSE.md) file for more details.
[level-badge]: http://leveldb.org/img/badge.svg
[levelup]: https://github.com/level/levelup
[encoding-down]: https://github.com/level/encoding-down
[abstract-leveldown]: https://github.com/level/abstract-leveldown
[level-sublevel]: https://github.com/dominictarr/level-sublevel
[level-org]: https://github.com/Level
var test = require('tape')
var memdown = require('memdown')
var encoding = require('encoding-down')
var subdown = require('../leveldown')
var subdb = require('..')
var levelup = require('levelup')
var testCommon = require('./common')
var testBuffer = new Buffer('this-is-test-data')

@@ -13,3 +14,3 @@ require('abstract-leveldown/abstract/open-test').args(down, test, testCommon)

require('abstract-leveldown/abstract/put-test').all(down, test, testCommon)
require('abstract-leveldown/abstract/put-get-del-test').all(down, test, testCommon, testBuffer)
require('abstract-leveldown/abstract/put-get-del-test').all(down, test, testCommon)
require('abstract-leveldown/abstract/batch-test').all(down, test, testCommon)

@@ -19,6 +20,128 @@ require('abstract-leveldown/abstract/chained-batch-test').all(down, test, testCommon)

require('abstract-leveldown/abstract/iterator-test').all(down, test, testCommon)
require('abstract-leveldown/abstract/ranges-test').all(down, test, testCommon)
require('abstract-leveldown/abstract/iterator-range-test').all(down, test, testCommon)
test('SubDown constructor', function (t) {
t.test('can be called without new', function (t) {
var sub = subdown()
t.is(sub instanceof subdown, true, 'instanceof subdown')
t.end()
})
t.test('missing prefix and missing separator', function (t) {
var sub = subdown()
t.is(sub.prefix, '!!')
t.end()
})
t.test('prefix and missing separator', function (t) {
var sub = subdown({}, 'prefix')
t.is(sub.prefix, '!prefix!')
t.end()
})
t.test('prefix and separator (as string)', function (t) {
var sub = subdown({}, 'prefix', '%')
t.is(sub.prefix, '%prefix%')
t.end()
})
t.test('prefix and separator (as options)', function (t) {
var sub = subdown({}, 'prefix', { separator: '%' })
t.is(sub.prefix, '%prefix%')
t.end()
})
t.test('prefix with same initial character as separator is sliced', function (t) {
var sub = subdown({}, '!prefix')
t.is(sub.prefix, '!prefix!')
t.end()
})
t.test('prefix with same ending character as separator is sliced', function (t) {
var sub = subdown({}, 'prefix!')
t.is(sub.prefix, '!prefix!')
t.end()
})
// TODO we're currently not guarded by multiple separators in the prefix
// t.test('repeated separator is slices off from prefix parameter', function (t) {
// var sub = subdown({}, '!!prefix!!')
// t.is(sub.prefix, '!prefix!')
// t.end()
// })
})
test('SubDb main function', function (t) {
t.test('opts.open hook', function (t) {
t.plan(1)
subdb(levelup(memdown()), 'test', {
open: function (cb) {
t.pass('opts.open called')
}
})
})
t.test('levelup *down is set to subdown which has correct storage', function (t) {
var db = levelup(memdown())
var sub = subdb(db, 'test')
sub.once('open', function () {
t.is(sub.db instanceof encoding, true, 'is encoding-down instance')
t.is(sub.db.db instanceof subdown, true, 'is subdown instance')
t.is(sub.db.db.type, 'subleveldown', '.type is subleveldown')
t.is(sub.db.db.leveldown instanceof memdown, true, 'memdown')
t.end()
})
})
t.test('different sub levels can have different encodings', function (t) {
t.plan(6)
var db = levelup(memdown())
var sub1 = subdb(db, 'test1', {
valueEncoding: 'json'
})
var sub2 = subdb(db, 'test2', {
keyEncoding: 'binary',
valueEncoding: 'binary'
})
sub1.put('foo', { some: 'json' }, function (err) {
t.error(err, 'no error')
sub1.get('foo', function (err, value) {
t.error(err, 'no error')
t.same(value, { some: 'json' })
})
})
sub2.put(Buffer.from([1, 2]), Buffer.from([2, 3]), function (err) {
t.error(err, 'no error')
sub2.get(Buffer.from([1, 2]), function (err, value) {
t.error(err, 'no error')
t.deepEqual(value, Buffer.from([2, 3]))
})
})
})
t.test('wrap a closed levelup and re-open levelup', function (t) {
t.plan(3)
var db = levelup(memdown())
db.once('open', function () {
db.close(function (err) {
t.error(err, 'no error')
var sub = subdb(db, 'test')
sub.once('open', function () {
t.pass('subdb openen')
})
db.open(function (err) {
t.error(err, 'no error')
})
})
})
})
t.test('wrapping a sub level', function (t) {
var db = levelup(memdown())
var sub1 = subdb(db, 'test1')
var sub2 = subdb(sub1, 'test2')
sub2.once('open', function () {
t.is(sub1.db instanceof encoding, true, 'sub1 encoding-down')
t.is(sub1.db.db.prefix, '!test1!', 'sub1 prefix ok')
t.is(sub1.db.db.leveldown instanceof memdown, true, 'memdown')
t.is(sub2.db instanceof encoding, true, 'sub2 encoding-down')
t.is(sub2.db.db.prefix, '!test1!!test2!', 'sub2 prefix ok')
t.is(sub2.db.db.type, 'subleveldown', '.type is subleveldown')
t.is(sub2.db.db.leveldown instanceof memdown, true, 'memdown')
t.end()
})
})
})
function down (loc) {
return subdown(levelup(loc, {db: memdown}), 'test')
return subdown(levelup(memdown()), 'test')
}

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