Skip to content

bunostrdb docs ​

bunostrdb logo

Bun FFI bindings for nostrdb — the embedded nostr database backed by LMDB. Linux x86_64 + Bun only.

Snippets import from "bunostrdb" — the library workspace (packages/bunostrdb), linked automatically by bun install at the repo root. The CLI ships separately as bunostrdb-cli.

Quick overview ​

BunNdb ​

The database handle. Opens (creating) an LMDB directory, ingests events, queries, subscribes, and searches.

ts
// @ts-nocheck
import { buildDraftNote, BunNdb } from "bunostrdb";

{
	using ndb = new BunNdb("./data");
	const { event } = buildDraftNote("hello local world");
	ndb.processEvent(JSON.stringify(["EVENT", "sub1", event]));
	await ndb.waitForNoteById(event.id); // ingestion is async — wait for commit
	const note = ndb.getNoteById(event.id);
	console.log(note?.content);
} // always destroyed at scope exit — see [Resource management](./resource-management.md)

Filters ​

FilterBuilder assembles native filters; build() transfers ownership to a Filter you must destroy.

ts
// @ts-nocheck
import { buildDraftNote, BunNdb, FilterBuilder, ingestDraft } from "bunostrdb";

{
	using ndb = new BunNdb("./data.filters");
	const draft = buildDraftNote("hello filtered world");
	await ingestDraft(ndb, draft.eventJson);
	using filter = new FilterBuilder().kinds([1]).authors([draft.event.pubkey]).limit(10).build();
	const notes = ndb.query([filter], 10);
	console.log(`found ${notes.length} notes`);
}

Subscriptions ​

Live ingestion notifications: subscribe, then poll or await matching notes. Ingestion is asynchronous — processEvent queues work; the subscription tells you when it lands.

ts
// @ts-nocheck
import { buildDraftNote, BunNdb, FilterBuilder } from "bunostrdb";

{
	using ndb = new BunNdb("./data.subs");
	// Subscribe first — the subscription observes notes committed after it exists.
	const subId = ndb.subscribe([new FilterBuilder().kinds([1])]);
	const { event } = buildDraftNote("hello live world");
	ndb.processEvent(JSON.stringify(["EVENT", "sub1", event]));
	await ndb.waitForNotes(subId);
	console.log(ndb.pollForNotes(subId, 32));
}

Notes & tags ​

Typed access to parsed notes: content, pubkey, timestamps, and tag iteration without touching raw JSON.

ts
// @ts-nocheck
import { buildDraftNote, BunNdb, ingestDraft } from "bunostrdb";

{
	using ndb = new BunNdb("./data.tags");
	const first = buildDraftNote("original note");
	await ingestDraft(ndb, first.eventJson);
	const reply = buildDraftNote("a reply", { tags: [["e", first.id]] });
	await ingestDraft(ndb, reply.eventJson);
	const note = ndb.getNoteById(reply.id);
	for (const [name, ...values] of note?.tags ?? []) {
		if (name === "e") console.log("reply to", values[0]);
	}
}

Drafts ​

Local-only events: mint an ephemeral identity, sign, ingest, and search — never published anywhere.

ts
// @ts-nocheck
import { BunNdb, buildDraftNote, ingestDraft, searchDrafts } from "bunostrdb";

{
	using ndb = new BunNdb("./data.drafts");
	const draft = buildDraftNote("hello local world");
	const id = await ingestDraft(ndb, draft.eventJson);
	console.log("stored draft", id, searchDrafts(ndb, "hello").length);
}

CLI ​

Every library capability above is also a subcommand, scriptable over pipes: ingest (--event accepts JSON, a file, or - for stdin), query, get-note, get-profile, draft-note, draft-reaction, draft-profile, search.

bash
bun run cli -- draft-note --db ./data.drafts --content "my first local draft"
bun run cli -- search --db ./data.drafts --query "local draft" --limit 20

Next steps ​

  • Getting started — install, open your first DB, and the ownership rules that keep the FFI layer sound.
  • Resource management — using / await using for every native handle.
  • Integrations — feed relay events in, script the CLI, local-first drafts, and the browser companion package.
  • Personal draft DB (CLI) — the full CLI walkthrough. mapped to bunostrdb APIs.
  • Comparison vs nak vs deed — where bunostrdb wins (in-process queries, batch ingest) and where it doesn't (one-shot startup, streaming crypto).

These pages are static VitePress output — no server, no iframes.

Support ​

If bunostrdb is useful, support development with any amount using Monero:

Monero donation QR code

8AfaZJa3HRnS4F9yRzRK9iDcVPm17WA33EEZjWfREkkoUGWbLfA79aeSWoAj21B7swMW9bb8iWdgw8mtjJ5y4yMT7z6AmCc

Released under the BSD-3.0 License.