sub-encoder
Advanced tools
Comparing version 2.0.0 to 2.1.0
86
index.js
@@ -1,2 +0,1 @@ | ||
const isOptions = require('is-options') | ||
const codecs = require('codecs') | ||
@@ -9,58 +8,61 @@ const b = require('b4a') | ||
module.exports = class SubEncoder { | ||
constructor (prefix, opts) { | ||
if (!opts && isOptions(prefix)) { | ||
opts = prefix | ||
prefix = null | ||
} | ||
if (typeof prefix === 'string') { | ||
prefix = b.from(prefix) | ||
} | ||
this.userEncoding = codecs(opts && opts.keyEncoding) | ||
constructor (prefix, encoding) { | ||
this.userEncoding = codecs(encoding) | ||
this.prefix = typeof prefix === 'string' ? b.from(prefix) : (prefix || null) | ||
this.lt = this.prefix && b.concat([this.prefix.subarray(0, this.prefix.byteLength - 1), SEP_BUMPED]) | ||
} | ||
const parent = opts && opts._parent | ||
const sub = opts && opts._sub | ||
if (prefix && parent) { | ||
this.prefix = b.concat([parent, prefix, SEP]) | ||
} else if (prefix) { | ||
this.prefix = b.concat([prefix, SEP]) | ||
} else if (parent) { | ||
this.prefix = b.concat([parent, SEP]) | ||
} else if (sub) { | ||
this.prefix = SEP | ||
} else { | ||
this.prefix = null | ||
_encodeRangeUser (r) { | ||
if (this.userEncoding.encodeRange) return this.userEncoding.encodeRange(r) | ||
return { | ||
gt: r.gt && this.userEncoding.encode(r.gt), | ||
gte: r.gte && this.userEncoding.encode(r.gte), | ||
lte: r.lte && this.userEncoding.encode(r.lte), | ||
lt: r.lt && this.userEncoding.encode(r.lt) | ||
} | ||
} | ||
_addPrefix (key) { | ||
return this.prefix ? b.concat([this.prefix, key]) : key | ||
} | ||
encode (key) { | ||
if (this.userEncoding) key = this.userEncoding.encode(key) | ||
if (this.prefix) key = b.concat([this.prefix, key]) | ||
return key | ||
return this._addPrefix(this.userEncoding.encode(key)) | ||
} | ||
encodeRange ({ gt, gte, lte, lt }) { | ||
if (gt) gt = this.encode(gt) | ||
else if (gte) gte = this.encode(gte) | ||
else if (this.prefix) gte = this.prefix | ||
encodeRange (range) { | ||
const r = this._encodeRangeUser(range) | ||
if (lt) lt = this.encode(lt) | ||
else if (lte) lte = this.encode(lte) | ||
else if (this.prefix) lt = b.concat([this.prefix.subarray(0, this.prefix.byteLength - 1), SEP_BUMPED]) | ||
if (r.gt) r.gt = this._addPrefix(r.gt) | ||
else if (r.gte) r.gte = this._addPrefix(r.gte) | ||
else if (this.prefix) r.gte = this.prefix | ||
return { gt, gte, lte, lt } | ||
if (r.lt) r.lt = this._addPrefix(r.lt) | ||
else if (r.lte) r.lte = this._addPrefix(r.lte) | ||
else if (this.prefix) r.lt = this.lt | ||
return r | ||
} | ||
decode (key) { | ||
if (this.prefix) key = key.subarray(this.prefix.byteLength) | ||
if (this.userEncoding) key = this.userEncoding.decode(key) | ||
return key | ||
return this.userEncoding.decode(this.prefix ? key.subarray(this.prefix.byteLength) : key) | ||
} | ||
sub (prefix, opts) { | ||
return new SubEncoder(prefix, { | ||
...opts, | ||
_parent: this.prefix, | ||
_sub: true | ||
}) | ||
sub (prefix, encoding) { | ||
const prefixBuf = typeof prefix === 'string' ? b.from(prefix) : prefix | ||
return new SubEncoder(createPrefix(prefixBuf, this.prefix), compat(encoding)) | ||
} | ||
} | ||
function createPrefix (prefix, parent) { | ||
if (prefix && parent) return b.concat([parent, prefix, SEP]) | ||
if (prefix) return b.concat([prefix, SEP]) | ||
if (parent) return b.concat([parent, SEP]) | ||
return SEP | ||
} | ||
function compat (enc) { | ||
if (enc && enc.keyEncoding) return enc.keyEncoding | ||
return enc | ||
} |
{ | ||
"name": "sub-encoder", | ||
"version": "2.0.0", | ||
"version": "2.1.0", | ||
"description": "Generate sub encodings for key/value stores", | ||
@@ -28,2 +28,3 @@ "main": "index.js", | ||
"hypercore": "^10.3.2", | ||
"index-encoder": "^3.0.0", | ||
"random-access-memory": "^6.0.0", | ||
@@ -34,5 +35,4 @@ "standard": "^17.0.0" | ||
"b4a": "^1.6.0", | ||
"codecs": "^3.1.0", | ||
"is-options": "^1.0.2" | ||
"codecs": "^3.1.0" | ||
} | ||
} |
@@ -6,17 +6,17 @@ # sub-encoder | ||
```js | ||
const enc = new SubEncoder({ keyEncoding: 'utf-8' }) | ||
const enc = new SubEncoder() | ||
const subA = enc.sub('sub-a') | ||
const subB = enc.sub('sub-b', { keyEncoding: 'binary' }) // subs support custom key encodings | ||
const subB = enc.sub('sub-b', 'binary') // subs support custom key encodings | ||
await bee.put('k1', 'b', { keyEncoding: enc }) | ||
await bee.put('k1', 'b') | ||
await bee.put('a1', 'a1', { keyEncoding: subA }) | ||
await bee.put('b1', 'b1', { keyEncoding: subB }) | ||
// k1 | ||
await bee.get('k1', { keyEncoding: enc }) | ||
// a1 | ||
// k1 as normal | ||
await bee.get('k1') | ||
// a1 from the sub | ||
await bee.get('a1', { keyEncoding: subA }) | ||
// also supports read streams | ||
for await (const node of bee.createReadStream(subA.range())) { | ||
for await (const node of bee.createReadStream({ keyEncoding: subA })) { | ||
// Iterates everything in the A sub | ||
@@ -26,7 +26,29 @@ } | ||
// The range options will be encoded properly too | ||
for await (const node of bee.createReadStream(subB.range({ lt: 'b2' })) { | ||
for await (const node of bee.createReadStream({ lt: 'b2' }, { keyEncoding: subB })) { | ||
} | ||
``` | ||
### API | ||
#### `const enc = new SubEncoder([prefix, encoding])` | ||
Create a new SubEncoder. Optionally set the initial prefix and encoding. | ||
#### `subEnc = enc.sub(prefix, [encoding])` | ||
Make a new sub. Returns a SubEncoder. | ||
#### `buf = enc.encode(key)` | ||
Encode a key. | ||
#### `key = enc.decode(buf)` | ||
Decode a key. | ||
#### `encodedRange = enc.encodeRange(range)` | ||
Encode a range. | ||
### License | ||
MIT |
@@ -5,2 +5,3 @@ const test = require('brittle') | ||
const Hyperbee = require('hyperbee') | ||
const IndexEncoder = require('index-encoder') | ||
const ram = require('random-access-memory') | ||
@@ -54,6 +55,6 @@ const b = require('b4a') | ||
const enc = new SubEncoder({ keyEncoding: 'utf-8' }) | ||
const subA = enc.sub('sub-a', { keyEncoding: 'utf-8' }) | ||
const subB = enc.sub('sub-b', { keyEncoding: 'utf-8' }) | ||
const subC = enc.sub('sub-c', { keyEncoding: 'utf-8' }) | ||
const enc = new SubEncoder(null, 'utf-8') | ||
const subA = enc.sub('sub-a', 'utf-8') | ||
const subB = enc.sub('sub-b', 'utf-8') | ||
const subC = enc.sub('sub-c', 'utf-8') | ||
@@ -92,6 +93,6 @@ await bee.put(enc.encode('d1'), 'd2') | ||
const enc = new SubEncoder({ keyEncoding: 'utf-8' }) | ||
const subA = enc.sub('sub-a', { keyEncoding: 'utf-8' }) | ||
const subB = enc.sub('sub-b', { keyEncoding: 'utf-8' }) | ||
const subC = enc.sub('sub-c', { keyEncoding: 'utf-8' }) | ||
const enc = new SubEncoder(null, 'utf-8') | ||
const subA = enc.sub('sub-a', 'utf-8') | ||
const subB = enc.sub('sub-b', 'utf-8') | ||
const subC = enc.sub('sub-c', 'utf-8') | ||
@@ -131,4 +132,4 @@ await bee.put(enc.encode('d1'), 'd2') | ||
const sub1 = enc.sub('1', { keyEncoding: 'utf-8' }) | ||
const sub2 = enc.sub('2', { keyEncoding: 'utf-8' }) | ||
const sub1 = enc.sub('1', 'utf-8') | ||
const sub2 = enc.sub('2', 'utf-8') | ||
const sub3 = enc.sub() | ||
@@ -150,5 +151,5 @@ | ||
const sub1 = enc.sub('1', { keyEncoding: 'utf-8' }) | ||
const sub2 = enc.sub('2', { keyEncoding: 'utf-8' }) | ||
const sub3 = enc.sub('3', { keyEncoding: 'binary' }) | ||
const sub1 = enc.sub('1', 'utf-8') | ||
const sub2 = enc.sub('2', 'utf-8') | ||
const sub3 = enc.sub('3', 'binary') | ||
@@ -168,2 +169,29 @@ await bee.put('', b.from('a'), { keyEncoding: sub1 }) | ||
test('sub + index + hyperbee combo', async t => { | ||
const root = new SubEncoder() | ||
const enc = { | ||
keyEncoding: root.sub(b.from([1]), { | ||
keyEncoding: new IndexEncoder([ | ||
IndexEncoder.UINT, | ||
IndexEncoder.STRING | ||
]) | ||
}), | ||
valueEncoding: 'utf-8' | ||
} | ||
const bee = new Hyperbee(new Hypercore(ram)) | ||
await bee.put([1, 'a'], 'a', enc) | ||
await bee.put([1, 'b'], 'b', enc) | ||
await bee.put([2, 'aa'], 'aa', enc) | ||
await bee.put([2, 'bb'], 'bb', enc) | ||
await bee.put([3, 'aaa'], 'aaa', enc) | ||
await bee.put([3, 'bbb'], 'bbb', enc) | ||
const expectedKeys = [[2, 'aa'], [2, 'bb']] | ||
for await (const node of bee.createReadStream({ gt: [1], lt: [3] }, enc)) { | ||
t.alike(node.key, expectedKeys.shift()) | ||
} | ||
t.is(expectedKeys.length, 0) | ||
}) | ||
async function collect (ite) { | ||
@@ -170,0 +198,0 @@ const res = [] |
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
10030
2
212
53
6
- Removedis-options@^1.0.2
- Removedis-options@1.0.2(transitive)