UNPKG

datastore-core

Version:
110 lines (92 loc) 2.98 kB
import { Key } from 'interface-datastore' import map from 'it-map' import { KeyTransformDatastore } from './keytransform.js' import type { Datastore, Query, Pair, KeyQuery } from 'interface-datastore' import type { AbortOptions } from 'interface-store' /** * Wraps a given datastore into a keytransform which * makes a given prefix transparent. * * For example, if the prefix is `new Key(/hello)` a call * to `store.put(new Key('/world'), mydata)` would store the data under * `/hello/world`. */ export class NamespaceDatastore extends KeyTransformDatastore { private readonly iChild: Datastore private readonly iKey: Key constructor (child: Datastore, prefix: Key) { super(child, { convert (key) { return prefix.child(key) }, invert (key) { if (prefix.toString() === '/') { return key } if (!prefix.isAncestorOf(key)) { throw new Error(`Expected prefix: (${prefix.toString()}) in key: ${key.toString()}`) } return new Key(key.toString().slice(prefix.toString().length), false) } }) this.iChild = child this.iKey = prefix } query (q: Query, options?: AbortOptions): AsyncIterable<Pair> { const query: Query = { ...q } query.filters = (query.filters ?? []).map(filter => { return ({ key, value }) => filter({ key: this.transform.invert(key), value }) }) const { prefix } = q if (prefix != null && prefix !== '/') { delete query.prefix query.filters.push(({ key }) => { return this.transform.invert(key).toString().startsWith(prefix) }) } if (query.orders != null) { query.orders = query.orders.map(order => { return (a, b) => order( { key: this.transform.invert(a.key), value: a.value }, { key: this.transform.invert(b.key), value: b.value } ) }) } query.filters.unshift(({ key }) => this.iKey.isAncestorOf(key)) return map(this.iChild.query(query, options), ({ key, value }) => { return { key: this.transform.invert(key), value } }) } queryKeys (q: KeyQuery, options?: AbortOptions): AsyncIterable<Key> { const query = { ...q } query.filters = (query.filters ?? []).map(filter => { return (key) => filter(this.transform.invert(key)) }) const { prefix } = q if (prefix != null && prefix !== '/') { delete query.prefix query.filters.push((key) => { return this.transform.invert(key).toString().startsWith(prefix) }) } if (query.orders != null) { query.orders = query.orders.map(order => { return (a, b) => order( this.transform.invert(a), this.transform.invert(b) ) }) } query.filters.unshift(key => this.iKey.isAncestorOf(key)) return map(this.iChild.queryKeys(query, options), key => { return this.transform.invert(key) }) } }