LogoPear Docs
ReferencesBuilding blocks

Hyperbee

Append-only B-tree on Hypercore for sorted key/value data.

stable

Hyperbee stores sorted key/value entries in an append-only B-tree backed by Hypercore. Use it when you need ordered lookups, range scans, atomic batches, namespaces, and point-in-time snapshots over one replicated log.

Install

npm i hyperbee

Quickstart

import Hypercore from 'hypercore'
import Hyperbee from 'hyperbee'

const core = new Hypercore('./bee-storage')
const db = new Hyperbee(core, {
  keyEncoding: 'utf-8',
  valueEncoding: 'json'
})

await db.ready()
await db.put('config', { theme: 'dark', retries: 3 })

const entry = await db.get('config')
console.log(entry.value.theme)

await db.close()

API Reference

Constructor and readiness

new Hyperbee(core, [options])

src

Make a new Hyperbee instance. core should be a Hypercore.

ParameterTypeDefault
coreHypercore
optionsHyperbeeOptions{}

Read and diff streams sort keys by their encoded byte values, so choose keyEncoding deliberately if lexicographic order matters.

await db.ready()

Waits until internal state is loaded.

Properties and identity

db.core

src

The underlying Hypercore backing this bee.

db.version

src

Number that indicates how many modifications were made, useful as a version identifier.

  • Returns: number

db.id

src

String containing the id (z-base-32 of the public key) identifying this bee.

  • Returns: string

db.key

src

Buffer containing the public key identifying this bee.

db.discoveryKey

src

Buffer containing a key derived from db.key.

db.writable

src

Boolean indicating if we can put or delete data in this bee.

  • Returns: boolean

db.readable

src

Boolean indicating if we can read from this bee. After closing the bee this will be false.

  • Returns: boolean

Writes and batches

await db.put(key, [value], [options])

src

Insert a new key. Value can be optional.

ParameterTypeDescription
key*The key to insert (encoded per keyEncoding).
value*The value to store; optional for key-only entries.
optionsPutOptions
  • Returns: Promise<void> — Resolves once the write is committed to the core.
{
  cas (prev, next) { return true }
}
await db.put('number', '123', { cas })
console.log(await db.get('number')) // => { seq: 1, key: 'number', value: '123' }

await db.put('number', '123', { cas })
console.log(await db.get('number')) // => { seq: 1, key: 'number', value: '123' }
// Without cas this would have been { seq: 2, ... }, and the next { seq: 3 }

await db.put('number', '456', { cas })
console.log(await db.get('number')) // => { seq: 2, key: 'number', value: '456' }

function cas(prev, next) {
  // You can use same-data or same-object lib, depending on the value complexity
  return prev.value !== next.value
}

The cas comparator receives the current node as prev and the potential new node as next. It runs only when the key already exists.

await db.del(key, [options])

src

Delete a key.

ParameterTypeDescription
key*The key to delete (encoded per keyEncoding).
optionsPutOptions
  • Returns: Promise<void> — Resolves once the deletion is committed to the core.
{
  cas (prev, next) { return true }
}
// This won't get deleted
await db.del('number', { cas })
console.log(await db.get('number')) // => { seq: 1, key: 'number', value: 'value' }

// Change the value so the next time we try to delete it then "cas" will return true
await db.put('number', 'can-be-deleted')

await db.del('number', { cas })
console.log(await db.get('number')) // => null

function cas(prev) {
  return prev.value === 'can-be-deleted'
}

The delete comparator runs only when the key exists. Deleting a missing key succeeds without calling cas.

db.batch()

src

Make a new atomic batch that is either fully processed or not processed at all.

ParameterTypeDescription
optsBatchOptionsBatch options.
  • Returns: Batch — A new batch; queue writes on it and call flush() to commit.
const batch = db.batch()
await batch.put('key', 'value')
await batch.flush()

Use batches when you need grouped writes or lower overhead for many updates.

await batch.put(key, [value], [options])

src

Insert a key into a batch.

ParameterTypeDescription
key*The key to insert (encoded per the batch's keyEncoding).
value*The value to store (encoded per the batch's valueEncoding); optional.
optionsPutOptionsoptions are the same as db.put method.
  • Returns: Promise<void> — Resolves after queuing the write inside the batch.
await batch.put('key', 'value')

await batch.get(key)

src

Get a key, value out of a batch.

ParameterTypeDescription
key*The key to look up (encoded per the batch's keyEncoding).
optsGetOptionsRead options.
  • Returns: Promise<Entry\|null> — The pending or committed entry visible within the batch, or null when missing.
const entry = await batch.get('key')

await batch.del(key, [options])

src

Delete a key into the batch.

ParameterTypeDescription
key*The key to delete (encoded per the batch's keyEncoding).
optionsPutOptionsoptions are the same as db.del method.
  • Returns: Promise<void> — Resolves after queuing the delete inside the batch.
await batch.del('key')

await batch.flush()

src

Commit the batch to the database, and releases any locks it has acquired.

  • Returns: Promise<void> — Resolves after committing the queued operations and releasing the batch lock.
await batch.flush()

await batch.close()

src

Destroy a batch, and releases any locks it has acquired on the db.

  • Returns: Promise<void> — Resolves after discarding the batch and releasing any lock it holds.
await batch.close()

Call batch.close() when you want to abort a batch without writing it.

Reads and iteration

await db.get(key)

src

Get a key's value. Returns null if key doesn't exists.

ParameterTypeDescription
key*The key to look up (encoded per keyEncoding).
optsGetOptionsRead options.
const entry = await db.get('key') // => { seq, key, value } or null

await db.getBySeq(seq, [options])

src

Get the key and value from a block number.

ParameterTypeDescription
seqnumberis the Hypercore index.
optionsGetOptionsRead options.
const { key, value } = await db.getBySeq(1)

db.createReadStream([range], [options])

src

Make a read stream. Sort order is based on the binary value of the keys.

ParameterTypeDescription
rangeRangeshould specify the range you want to read and looks like this
optionsReadStreamOptions
  • Returns: Readable — A stream of Entry objects.

await db.peek([range], [options])

src

Similar to doing a read stream and returning the first value, but a bit faster than that.

ParameterTypeDescription
rangeRangebounds to search within.
optionsReadStreamOptionsRead options (reverse selects the last entry instead of the first).
const first = await db.peek({ gte: 'a', lt: 'd' })

History and change tracking

db.createHistoryStream([options])

src

Create a stream of all entries ever inserted or deleted from the db.

ParameterType
optionsHistoryStreamOptions
  • Returns: Readable — A stream of Entry objects, each with an added type ('put' or 'del').

db.createDiffStream(otherVersion, [options])

src

Efficiently create a stream of the shallow changes between two versions of the db.

ParameterTypeDescription
rightnumber|HyperbeeThe other version to diff against: a version number, or another bee/snapshot.
rangeRangeoptions are the same as db.createReadStream, except for reverse.
optsReadStreamOptionsRead options.
  • Returns: Readable — A stream of { left, right } pairs, where each side is an Entry or null.
OptionDefaultDescription
leftObjectThe entry in the db
rightObjectThe entry in otherVersion

Causally equal entries are omitted from the diff, so the stream only yields actual changes between versions.

await db.getAndWatch(key, [options])

src

entryWatcher.node contains the current entry in the same format as the result of bee.get(key), and will be updated as it changes.

ParameterTypeDescription
key*The key to watch (encoded per keyEncoding).
optionsEntryWatchOptionsWatch options.
  • Returns: Promise<EntryWatcher> — a watcher which listens to changes on the given key.
  • Throws: if called on a non-main Hyperbee, or if the Hyperbee is closed.
const w = await db.getAndWatch('config')
w.on('update', () => console.log(w.node.value))

Listen to entryWatcher.on('update') when you need push-style notifications for a single key.

await entryWatcher.close()

Stop a single-key watcher.

  • Returns: Resolves after stopping the watcher created by db.getAndWatch(...).
await entryWatcher.close()

db.watch([range])

src

Listens to changes that are on the optional range.

ParameterTypeDescription
rangeRangebounds to narrow what changes are watched; same as db.createReadStream except reverse.
optsWatchOptionsWatch options.
  • Returns: Watcher — a new value after a change, current and previous are snapshots that are auto-closed before next value.
  • Throws: if called on a non-main Hyperbee (a sub, checkout, or snapshot).
for await (const [current, previous] of watcher) {
  console.log(current.version)
  console.log(previous.version)
}

Watchers are not supported on subs or checkouts. Use range to narrow the scope on the root bee instead.

await watcher.ready()

Wait for a range watcher to be tracking changes.

  • Returns: Resolves when a range watcher has loaded and is actively tracking changes.
await watcher.ready()

await watcher.close()

Stop a range watcher.

  • Returns: Resolves after stopping the range watcher. Breaking out of the async iterator also stops it.
await watcher.close()

Snapshots and sub-bees

db.checkout(version)

src

Get a read-only snapshot of a previous version.

ParameterTypeDefaultDescription
versionnumberThe version (see db.version) to check out.
optsCheckoutOptions{}Snapshot options.
  • Returns: Hyperbee — A read-only bee pinned to that version.
const old = db.checkout(5)
const entry = await old.get('key')

db.snapshot()

src

Shorthand for getting a checkout for the current version.

ParameterTypeDescription
optsCheckoutOptionsSnapshot options.
  • Returns: Hyperbee — A read-only bee pinned to the current version.
const snap = db.snapshot()

db.sub('sub-prefix', options = {})

src

Create a sub-database where all entries will be prefixed by a given value.

ParameterTypeDefaultDescription
prefixstring|BufferThe namespace prefix applied to every key.
optsSubOptions{}
  • Returns: Hyperbee — A bee scoped to the prefixed keyspace.
const root = new Hyperbee(core)
const sub = root.sub('a')

// In root, this will have the key ('a' + separator + 'b')
await sub.put('b', 'hello')

// Returns => { key: 'b', value: 'hello')
await sub.get('b')

Sub-bees are useful when one Hyperbee needs multiple logical keyspaces without creating extra cores.

await db.getHeader([options])

src

options are the same as the core.get method.

ParameterType
optionsGetOptions
  • Returns: Promise<object> — the header contained in the first block.
  • Throws: DECODING_ERROR if the stored header cannot be decoded.
const header = await db.getHeader()

Replication and lifecycle

db.replicate(isInitiatorOrStream)

src

See more about how replicate works at core.replicate.

ParameterTypeDescription
isInitiatorboolean|Streamtrue/false to open a fresh replication stream, or an existing stream to replicate over.
optsobjectReplication options, forwarded to core.replicate.
  • Returns: Stream — The replication stream.
const stream = db.replicate(true)
stream.pipe(remoteStream).pipe(stream)

In larger apps, replication is often handled through a shared Corestore rather than per-bee streams.

await db.close()

Fully close this bee, including its core.

Static helpers

await Hyperbee.isHyperbee(core, [options])

src

This requests the first block on the core, so it can throw depending on the options.

ParameterTypeDescription
coreHypercoreThe core to inspect.
optionsGetOptionsoptions are the same as the core.get method.
  • Returns: Promise<boolean>true if the core contains a Hyperbee, false otherwise.
if (await Hyperbee.isHyperbee(core)) {
  const db = new Hyperbee(core)
}

Types

Entry

A single entry as returned by reads such as db.get(), db.peek(), and the read stream. key and value are decoded with the bee's keyEncoding / valueEncoding (raw Buffers when no encoding is set).

PropertyTypeDefaultDescription
seqnumberHypercore index (block number) at which this entry was inserted.
key*The entry's key, decoded per keyEncoding.
value*The entry's value, decoded per valueEncoding (null for a deletion).

HyperbeeOptions

Options for new Hyperbee().

PropertyTypeDefaultDescription
keyEncodingstring|object'binary'Key encoding: "binary" (default), "utf-8", "ascii", "json", or an abstract-encoding instance.
valueEncodingstring|object'binary'Value encoding; same options as keyEncoding.

PutOptions

Options for db.put(), db.del() and their batch equivalents.

PropertyTypeDefaultDescription
casCASComparatorCompare-and-swap comparator; the write only proceeds when it returns true.

Range

Range bounds for read, diff, and watch streams. Keys are compared by their encoded byte value.

PropertyTypeDefaultDescription
gt*Only return keys greater than this.
gte*Only return keys greater than or equal to this.
lt*Only return keys less than this.
lte*Only return keys less than or equal to this.

ReadStreamOptions

Options for db.createReadStream() and db.peek().

PropertyTypeDefaultDescription
reversebooleanfalseYield entries in reverse (descending) order.
limitnumber-1Maximum number of entries to return (-1 for no limit).

HistoryStreamOptions

Options for db.createHistoryStream().

PropertyTypeDefaultDescription
livebooleanfalseKeep the stream open and wait for new data instead of ending.
reversebooleanfalseIterate from newest to oldest.
gtenumberStart at this seq (inclusive); negative values are added to the current version.
gtnumberStart after this seq.
ltenumberStop at this seq (inclusive).
ltnumberStop before this seq.
limitnumber-1Maximum number of entries to return (-1 for no limit).

SubOptions

Options for db.sub().

PropertyTypeDefaultDescription
sepBufferNamespace separator placed between the prefix and key (defaults to the parent's separator).
keyEncodingstring|objectKey encoding for the sub (defaults to the parent's).
valueEncodingstring|objectValue encoding for the sub (defaults to the parent's).

GetOptions

Options for point reads such as db.get() and db.getBySeq(). The encoding overrides apply to this call only; remaining options are forwarded to the underlying core.get().

PropertyTypeDefaultDescription
keyEncodingstring|objectOverride the key encoding for this read.
valueEncodingstring|objectOverride the value encoding for this read.
waitbooleantrueWait for the block to download from a peer if it isn't local.
timeoutnumber0Max milliseconds to wait for a block (0 = no timeout).

BatchOptions

Options for db.batch().

PropertyTypeDefaultDescription
keyEncodingstring|objectOverride the key encoding for this batch.
valueEncodingstring|objectOverride the value encoding for this batch.
updatebooleantrueUpdate the underlying core before the first operation resolves.

WatchOptions

Options for db.watch().

PropertyTypeDefaultDescription
keyEncodingstring|objectKey encoding for the yielded snapshots (defaults to the bee's).
valueEncodingstring|objectValue encoding for the yielded snapshots (defaults to the bee's).

EntryWatchOptions

Options for db.getAndWatch().

PropertyTypeDefaultDescription
keyEncodingstring|objectKey encoding for the watched entry (defaults to the bee's).
valueEncodingstring|objectValue encoding for the watched entry (defaults to the bee's).

CheckoutOptions

Options for db.checkout() and db.snapshot().

PropertyTypeDefaultDescription
keyEncodingstring|objectKey encoding for the snapshot (defaults to the bee's).
valueEncodingstring|objectValue encoding for the snapshot (defaults to the bee's).

Errors

Coded errors this module can throw — catch them via err.code.

ErrorThrown when
DECODING_ERRORif the stored header cannot be decoded.

See also

On this page