Skip to main content

Documentation 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.

Bun ships with bun:sqlite, a built-in SQLite module that needs no separate install. The createBunClient adapter wraps it as a SyncClient, so generated query wrappers return rows directly — no await required on each call.
1

Install sqlfu

bun:sqlite is already included in Bun, so you only need to install sqlfu itself:
bun install sqlfu
2

Configure sqlfu

Create sqlfu.config.ts in your project root. Set generate.sync: true so generated wrappers match the synchronous bun:sqlite driver:
sqlfu.config.ts
import {defineConfig} from 'sqlfu';

export default defineConfig({
  db: './db/app.sqlite',
  definitions: './definitions.sql',
  migrations: './migrations',
  queries: './sql',
  generate: {
    sync: true,
  },
});
generate.sync: true produces wrappers that accept a SyncClient and return rows directly. Without it, generated wrappers default to async and require await at each call site.
3

Write schema and queries

Add your schema to definitions.sql:
definitions.sql
create table jobs (
  id integer primary key,
  name text not null,
  status text not null
);
Add a query to sql/queries.sql:
sql/queries.sql
/** @name listJobsByStatus */
select id, name, status
from jobs
where status = :status
order by id;
4

Draft, migrate, and generate

Run the standard sqlfu commands:
npx sqlfu draft
npx sqlfu migrate
npx sqlfu generate
This creates the migration file, applies it to the database, and generates TypeScript wrappers into sql/.generated/.
5

Create the client and call your queries

Import Database from bun:sqlite, open the file, wrap it with createBunClient, and call the generated wrapper:
src/db.ts
import {Database} from 'bun:sqlite';
import {createBunClient} from 'sqlfu';

import {listJobsByStatus} from './sql/.generated/queries.sql.ts';

const db = new Database('./db/app.sqlite');
const client = createBunClient(db);

const pendingJobs = listJobsByStatus(client, {status: 'pending'});
The generated wrapper is the same wrapper you would call with node:sqlite or better-sqlite3 when generate.sync: true is set. Swap the adapter, keep the rest of the code unchanged.

Sync behavior

bun:sqlite is synchronous. sqlfu preserves that — createBunClient returns a SyncClient, and every generated wrapper and client.all(...) call returns rows directly:
// No await needed
const jobs = listJobsByStatus(client, {status: 'pending'});
const rows = client.all({sql: 'select * from jobs', params: []});
If you ever need to talk to a remote database from Bun — for example, a Turso Cloud instance — use @libsql/client with createLibsqlClient instead. That client is async but shares the same generated wrapper signatures, so the application logic stays the same.

Adapters reference

Every adapter snippet and the full sync/async compatibility matrix.

Type generation from SQL

Params, list params, INSERT objects, and generated row types.

Build docs developers (and LLMs) love