This page documents the public runtime surface exported by @3xhaust/gitdb.
GitDB has two entrypoints:
@3xhaust/gitdb/browser: browser/extension/static app surface. Usesfetch, GitHub REST/Git Database APIs, and Web Crypto.@3xhaust/gitdb: Node surface. Includes local filesystem stores, CLI helpers, and Octokit-backed GitHub stores.
GitDB is ESM-only.
Plaintext GitHub database:
import { defineTable, GitDb, GitHubFetchPlaintextStore } from "@3xhaust/gitdb/browser"
import { z } from "zod"
const TodoRow = z.object({
id: z.string(),
title: z.string(),
done: z.boolean(),
})
const Todo = defineTable({
columns: { done: "BOOLEAN", id: "STRING", title: "STRING" },
indexes: [{ columns: ["done"], name: "todos_done_idx" }],
name: "todos",
primaryKey: "id",
row: TodoRow,
})
const db = await GitDb.open({
store: new GitHubFetchPlaintextStore({
branch: "main",
owner: "your-github-user",
prefix: "gitdb/v1",
repo: "my-app-db",
token: userProvidedGithubToken,
}),
syncSchema: true,
tables: [Todo],
})Encrypted GitHub database:
import {
createWebAesGcmCipher,
GitDb,
GitHubFetchEncryptedStore,
} from "@3xhaust/gitdb/browser"
const cipher = await createWebAesGcmCipher(base64UrlEncoded32ByteKey)
const db = await GitDb.open({
store: new GitHubFetchEncryptedStore(
{
branch: "main",
owner: "your-github-user",
prefix: "gitdb/v1",
repo: "my-private-db",
token: userProvidedGithubToken,
},
cipher,
),
})Both browser stores write through Git tree creation, commit creation, and non-force ref updates. If the target repository is missing, GitDB tries to create a public database repository for the authenticated owner.
const todos = db.table(Todo)
await todos.insert({ done: false, id: "t1", title: "Write docs" })
await todos.insertMany([
{ done: false, id: "t2", title: "Test browser store" },
{ done: true, id: "t3", title: "Ship example" },
])
await todos.upsertMany([{ done: true, id: "t2", title: "Test browser store" }])
const openTodos = await todos.select({ done: false })
const oneTodo = await todos.first({ id: "t2" })
const deleted = await todos.deleteWhere({ id: "t1" })insertMany() and upsertMany() share one transaction boundary. Prefer them
over repeated single-row calls when loading batches.
await db.execute("CREATE TABLE people (id STRING, name STRING)")
await db.execute("INSERT INTO people VALUES ('p1', 'Lin')")
const rows = await db.query("SELECT * FROM people WHERE id = 'p1'")The SQL subset currently covers table creation, inserts, deletes, selects, joins, grouping, ordering, and aggregates. Unsupported SQL should fail explicitly rather than pretending to succeed.
Indexes are equality-only and rebuildable. Table metadata records intent:
indexes: [{ columns: ["done"], name: "todos_done_idx" }]The runtime maintains primary/equality indexes from committed rows. Simple
table select({ ... }) calls and safe SELECT * FROM table WHERE col = literal
queries use the index path. Missing or stale index snapshot files are ignored.
await db.transaction(async (tx) => {
await tx.execute("INSERT INTO todos VALUES ('t4', 'Batch write', false)")
await tx.execute("INSERT INTO todos VALUES ('t5', 'Commit once', false)")
})Transactions run on an isolated database copy and persist only after the callback succeeds. Persisted transactions advance the manifest boundary and write GitHub commits when a GitHub store is configured.
Local plaintext:
import { GitDb, LocalPlaintextStore } from "@3xhaust/gitdb"
const db = await GitDb.open({
store: new LocalPlaintextStore({ root: ".gitdb" }),
})Local encrypted:
import { GitDb, LocalEncryptedStore, createAesGcmCipher } from "@3xhaust/gitdb"
const db = await GitDb.open({
store: new LocalEncryptedStore({
cipher: createAesGcmCipher(process.env.GITDB_KEY ?? ""),
root: ".gitdb",
}),
})Node GitHub stores remain available from the root entrypoint:
import { GitHubPlaintextStore } from "@3xhaust/gitdb"
new GitHubPlaintextStore({
branch: "main",
owner: "3x-haust",
prefix: "gitdb/v1",
repo: "my-project-db",
token: process.env.GITDB_GITHUB_TOKEN ?? "",
})const result = await db.compact()Compaction is currently enabled for local plaintext stores. It writes a matching
page snapshot, advances the manifest to an empty logSegments list, then
deletes obsolete mutation segments.
Existing gitdb/v1 repositories remain readable. The next committed write
upgrades manifest metadata to v2 while keeping the path layout. Unreferenced
mutation files are ignored unless the manifest lists them. See
MIGRATION.md for rollback and storage details.