SQLite
sqlite is built into runtime:db: there is no package to install.
import { connect, sqlite } from "runtime:db"; const db = await connect("sqlite:./app.db", { driver: sqlite });
Queries, results, transactions and errors work as described in Databases. Parameters bind by position (?) or by name (:email).
Permissions
A database file is a file, and is scoped like one — the same root jail and --allow-read / --allow-write lists as file handling. esrun --allow-read=./data --allow-write=./data app.js is enough to open sqlite:./data/app.db for writing and nothing else. See Securing the runtime.
Open with readOnly: true when the program only reads; it then needs only the read grant.
In-memory databases
sqlite::memory: gives you a database that exists only in memory — ideal for tests, and for using SQL as a query language over data you already have:
const db = await connect("sqlite::memory:", { driver: sqlite });
It touches no filesystem, so it needs no capability: it works under esrun with nothing granted. Each connection gets its own database.
Encryption
const key = crypto.getRandomValues(new Uint8Array(32)); const db = await connect("sqlite:./secret.db", { driver: sqlite, key });
Encryption is experimental upstream. The key goes in the options object — a key in the connection string ends up in logs, error messages and stack traces, so connect("sqlite:./app.db?key=…", { driver: sqlite }) is refused rather than honoured quietly.
Every sqlite option is listed in the connect() reference.