Part of the LibreDB guides. See also: document · relational · catalog.
The first lens is kv: a durable, ordered, string-keyed map over the kernel. You open a kernel
database and put a kv lens over it.
import { open, kv } from "@libredb/libredb";
// In-memory: the natural fit for tests and ephemeral use.
const db = open();
// Or file-backed and durable. Every write is appended to a write-ahead
// log and fsync'd before it returns, so a committed write survives a
// crash; reopening the same path reconstructs exactly the committed state:
//
// const db = open({ path: "data.libredb" });
const store = kv(db);
store.set("user:1", "Ada");
store.set("user:2", "Grace");
store.get("user:1"); // "Ada"
store.get("missing"); // undefined
db.close();Every write returns a WriteResult ({ changed }), so a caller can always see what the write
actually did:
store.set("user:1", "Ada Lovelace").changed; // 1 (overwrote the existing value)
store.delete("user:2").changed; // 1 (it existed)
store.delete("user:2").changed; // 0 (already gone)Keys are ordered by byte order, so reads come back in ascending key order. range(start, end) scans
the half-open interval [start, end) — start included, end excluded:
store.set("a", "1");
store.set("b", "2");
store.set("c", "3");
store.range("a", "c").toArray();
// [{ key: "a", value: "1" }, { key: "b", value: "2" }] — "c" is excludedprefix(p) scans every key beginning with p — the canonical ordered-KV query:
store.prefix("user:").toArray();
// [{ key: "user:1", value: "Ada Lovelace" }]A read returns a Result, which is lazy and re-iterable: nothing runs until you iterate it (or
call toArray()), and each pass re-runs the scan against the current state. Iterate it directly or
materialize it:
for (const { key, value } of store.prefix("user:")) {
console.log(key, value);
}Each kv operation auto-commits in its own transaction. When you need several writes to apply
atomically, drop to the kernel's transact directly — it commits all of the body's writes together,
or nothing if the body throws:
const encode = new TextEncoder();
db.transact((tx) => {
tx.set(encode.encode("from"), encode.encode("90"));
tx.set(encode.encode("to"), encode.encode("110"));
}); // both writes commit together, or neither doesThe kernel speaks raw bytes on purpose; the kv lens is the string-ergonomic face over it.