Comparing version 0.0.18 to 1.0.0
34
index.js
@@ -14,2 +14,5 @@ const codecs = require('codecs') | ||
const SEP = Buffer.alloc(1) | ||
const MAX = Buffer.from([255]) | ||
class Key { | ||
@@ -273,3 +276,5 @@ constructor (seq, value) { | ||
this.lock = opts.lock || mutexify() | ||
this.sep = opts.sep || SEP | ||
this._sub = !!opts._sub | ||
this._checkout = opts.checkout || 0 | ||
@@ -416,2 +421,3 @@ this._ready = null | ||
return new HyperBee(this.feed, { | ||
sep: this.sep, | ||
checkout: version, | ||
@@ -427,2 +433,27 @@ extension: this.extension, | ||
} | ||
sub (prefix, opts = {}) { | ||
let sep = opts.sep || this.sep | ||
if (!Buffer.isBuffer(sep)) sep = Buffer.from(sep) | ||
prefix = Buffer.concat([Buffer.from(prefix), sep]) | ||
return new HyperBee(this.feed, { | ||
_sub: true, | ||
sep: this.sep, | ||
lock: this.lock, | ||
checkout: this._checkout, | ||
extension: this.extension, | ||
valueEncoding: this.valueEncoding, | ||
keyEncoding: { | ||
encode: key => { | ||
if (!Buffer.isBuffer(key)) key = Buffer.from(key) | ||
return enc(this.keyEncoding, Buffer.concat([prefix, key])) | ||
}, | ||
decode: key => { | ||
const sliced = key.slice(prefix.length, key.length) | ||
return this.keyEncoding ? this.keyEncoding.decode(sliced) : sliced | ||
} | ||
} | ||
}) | ||
} | ||
} | ||
@@ -488,2 +519,3 @@ | ||
async get (key) { | ||
if (this.keyEncoding) key = enc(this.keyEncoding, key) | ||
if (this.options.extension !== false) this.options.onwait = this._onwait.bind(this, key) | ||
@@ -810,2 +842,4 @@ | ||
if (opts.lte !== undefined) opts.lte = enc(e, opts.lte) | ||
if (opts.sub && !opts.gt && !opts.gte) opts.gt = enc(e, SEP) | ||
if (opts.sub && !opts.lt && !opts.lte) opts.lt = enc(e, MAX) | ||
return opts | ||
@@ -812,0 +846,0 @@ } |
{ | ||
"name": "hyperbee", | ||
"version": "0.0.18", | ||
"version": "1.0.0", | ||
"description": "An append-only Btree running on a Hypercore.", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
@@ -171,2 +171,27 @@ # Hyperbee 🐝 | ||
#### `const sub = db.sub('sub-prefix', opts = {})` | ||
Create a sub-database where all entries will be prefixed by a given value. | ||
This makes it easy to create namespaces within a single Hyperbee. | ||
Options include: | ||
```js | ||
{ | ||
sep: Buffer.alloc(1) // A namespace separator | ||
} | ||
``` | ||
For example: | ||
```js | ||
const rootDb = new Hyperbee(core) | ||
const subDb = rootDb.sub('a') | ||
// In rootDb, this will have the key ('a' + separator + 'b') | ||
await subDb.put('b', 'hello') | ||
// Returns { key: 'b', value: 'hello') | ||
await subDb.get('b') | ||
``` | ||
#### `db.version` | ||
@@ -173,0 +198,0 @@ |
@@ -161,1 +161,79 @@ const tape = require('tape') | ||
}) | ||
tape('test all short iterators, sub database', async function (t) { | ||
const parent = create({ keyEncoding: 'utf8' }) | ||
const db = parent.sub('sub1') | ||
const MAX = 25 | ||
for (let size = 1; size <= MAX; size++) { | ||
const reference = [] | ||
for (let i = 0; i < size; i++) { | ||
const key = '' + i | ||
await db.put(key, 'hello world') | ||
reference.push(key) | ||
} | ||
reference.sort() | ||
for (let i = 0; i < size; i++) { | ||
for (let j = 0; j <= i; j++) { | ||
for (let k = 0; k < 8; k++) { | ||
const greater = (k & 1) ? 'gte' : 'gt' | ||
const lesser = (k >> 1 & 1) ? 'lte' : 'lt' | ||
const reverse = !!(k >> 2 & 1) | ||
const opts = { | ||
[greater]: '' + j, | ||
[lesser]: '' + i, | ||
reverse | ||
} | ||
const entries = await collect(db.createReadStream(opts)) | ||
if (!validate(size, reference, opts, entries)) { | ||
return t.end() | ||
} | ||
} | ||
} | ||
} | ||
} | ||
t.pass('all iterations passed') | ||
t.end() | ||
function validate (size, reference, opts, entries) { | ||
const start = opts.gt ? reference.indexOf(opts.gt) + 1 : reference.indexOf(opts.gte) | ||
const end = opts.lt ? reference.indexOf(opts.lt) : reference.indexOf(opts.lte) + 1 | ||
const range = reference.slice(start, end) | ||
if (opts.reverse) range.reverse() | ||
for (let i = 0; i < range.length; i++) { | ||
if (!entries[i] || range[i] !== entries[i].key) { | ||
console.log('========') | ||
console.log('SIZE:', size) | ||
console.log('FAILED WITH OPTS:', opts) | ||
console.log(' expected:', range, 'start:', start, 'end:', end) | ||
console.log(' actual:', entries.map(e => e.key)) | ||
t.fail('ranges did not match') | ||
return false | ||
} | ||
} | ||
return true | ||
} | ||
}) | ||
tape('simple sub put/get', async t => { | ||
const db = create() | ||
const sub = db.sub('hello') | ||
await sub.put('world', 'hello world') | ||
const node = await sub.get('world') | ||
t.same(node && node.key, 'world') | ||
t.same(node && node.value, 'hello world') | ||
t.end() | ||
}) | ||
tape('multiple levels of sub', async t => { | ||
const db = create({ sep: '!' }) | ||
const sub = db.sub('hello').sub('world') | ||
await sub.put('a', 'b') | ||
const node = await sub.get('a') | ||
t.same(node && node.key, 'a') | ||
t.same(node && node.value, 'b') | ||
t.end() | ||
}) |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
92403
2749
0
203