TheDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/iterate/sqlfu/llms.txt
Use this file to discover all available pages before exploring further.
Client type is the only runtime-specific boundary your application code needs to know about. Everything else — generated query wrappers, migrations, the observability layer — works against this same surface, regardless of which SQLite driver sits beneath it.
The Client type
SyncClient returns values directly, while an AsyncClient returns promises.
The client surface
BothSyncClient and AsyncClient expose the same methods:
| Method | Purpose |
|---|---|
client.all(query) | Execute a row-returning query |
client.run(query) | Execute a write or DDL statement |
client.iterate(query) | Stream rows one at a time |
client.prepare(sql) | Create a reusable statement handle |
client.transaction(fn) | Run a function inside a driver-backed transaction |
client.sql | Tagged template helper for inline SQL fragments |
client.driver | Escape hatch to the underlying driver object |
Generated query wrappers accept
Client directly. They are the primary data-access layer — client.all, client.run, and client.prepare are there for dynamic or ad-hoc SQL that doesn’t fit into a .sql file.Sync stays sync
Most query libraries coerce every database call toasync, even when the underlying driver is synchronous. sqlfu preserves what you brought.
Sync drivers (SyncClient):
better-sqlite3node:sqlitebun:sqlite- Cloudflare Durable Object storage (
SqlStorage)
AsyncClient):
@libsql/client@tursodatabase/database/@tursodatabase/sync/@tursodatabase/serverless- Cloudflare D1
expo-sqlite@sqlite.org/sqlite-wasm
SyncClient where an AsyncClient is expected is a type error, not a silent behaviour change. If you swap from one sync driver to another, it is a one-line boundary change. Swapping from sync to async is a real application change — sqlfu keeps that visible.
Prepared statements
Generated wrappers from.sql files are the primary path. client.prepare(sql) is the lower-level API for SQL that needs to stay dynamic without reaching through to client.driver.
Use prepare when you want to reuse one statement handle, bind named parameters directly, or call .all() and .run() against the same SQL string.
Sync prepared statements
sync usage
using declaration releases the underlying driver statement when the scope exits.
Async prepared statements
async usage
await using works the same way: the handle’s [Symbol.asyncDispose] method is called when the scope exits.
What prepared handles expose
Each handle exposes.all(params), .run(params), and .iterate(params). Parameters can be positional ([id]) or named ({slug}). Adapters that have native prepared statements hold the driver handle for the lifetime of the using scope. Adapters whose driver exposes only an exec/execute API provide a shim that re-issues the SQL on each call — the interface is identical either way.
Where to go next
Adapters
Every built-in adapter factory, with copy-paste setup snippets for each driver.
Type generation
How
.sql files become typed generated wrappers via sqlfu generate.Observability
Wrap a client with tracing, metrics, and error hooks.
Errors
The normalized
SqlfuError kinds raised by every adapter.