WebExtension DB is a small TypeScript library for persistent JSON data in browser extensions. It uses IndexedDB by default and can use chrome.storage or browser.storage when a project explicitly chooses those backends.
The package does not expose a SQL or ORM layer. Those APIs were removed because they were not proven against the browser environments this package targets.
pnpm add webextension-dbIn an extension page, content script, or service worker, the default backend selects IndexedDB when it is available:
import { createDatabase, isJsonObject } from "webextension-db";
const db = await createDatabase({
name: "settings-db",
});
await db.set("settings", "theme", {
mode: "dark",
sync: true,
});
const value = await db.get("settings", "theme");
if (value !== undefined && isJsonObject(value)) {
console.log(JSON.stringify(value));
}By default, createDatabase selects the first durable backend available in this order:
indexeddbchrome-storagebrowser-storage
Tests and temporary tools can opt into the in-memory backend:
const db = await createDatabase({
name: "test-db",
backend: "memory",
});Use memory for Node.js scripts and tests that do not provide browser storage APIs.
Extension storage can also be selected directly:
const db = await createDatabase({
name: "extension-db",
backend: "chrome-storage",
storageArea: "local",
});When storageArea is set and backend is omitted, createDatabase selects an available extension storage backend for that area instead of falling back to IndexedDB.
Supported extension storage areas are local, sync, session, and managed.
session is read/write but memory-backed by the browser and is cleared when the extension is unloaded.
managed is read-only policy storage, so createDatabase returns a read-only database for that area:
const policyDb = await createDatabase({
name: "policy-db",
backend: "browser-storage",
storageArea: "managed",
});
const policy = await policyDb.get("policies", "homepage");Complete Chrome, Firefox, and Safari extension examples are available in examples/extensions.
Run pnpm build:extensions to create loadable test folders in examples/extensions/dist.
Creates a database instance.
const db = await createDatabase({
name: "my-db",
backend: "indexeddb",
version: 1,
});backend is optional. version applies to IndexedDB schema upgrades.
Records are addressed by table and key.
await db.set("users", "ada", { name: "Ada Lovelace", active: true });
const user = await db.get("users", "ada");
const exists = await db.has("users", "ada");
await db.delete("users", "ada");Values must be JSON-compatible: strings, finite numbers, booleans, null, arrays, and plain objects containing those values.
const keys = await db.keys("users");
const entries = await db.entries("users");
const tables = await db.listTables();
await db.clear("users");find filters records in one table. Dot paths read nested object fields.
const activeAdmins = await db.find(
"users",
{
role: "admin",
"profile.active": true,
age: { $gte: 18 },
},
{
sort: { age: "asc" },
limit: 20,
},
);Supported operators: $eq, $ne, $gt, $gte, $lt, $lte, $in, $nin, $regex, and $exists.
await db.batch([
{ type: "set", table: "users", key: "ada", value: { name: "Ada" } },
{ type: "delete", table: "cache", key: "stale-entry" },
{ type: "clear", table: "sessions" },
]);Batch operations run in order. They are not a transaction boundary.
This repository uses pnpm.
pnpm install
pnpm verifyUseful commands:
pnpm lint
pnpm type-check
pnpm test
pnpm test:browsers
pnpm buildBefore running browser-engine tests locally, install the Playwright browser binaries:
pnpm test:browsers:installThe lint step runs Biome and a source policy check that rejects explicit any, type assertions, TypeScript suppression comments, and linter suppression comments in source, tests, and examples.