Files
skills/docs/persistence/database/db-sqlite/src/adapter/adapter.md
2026-05-29 08:20:56 +01:00

5.0 KiB

adapter

(no submodules)

- adapter.wasm — Browser-runtime entry point for the……
  • adapter.wasm — Browser-runtime entry point for the ./adapter conditional export in @suaveplan/db-sqlite. When a browser bundler re…

  • adapter.wasm — Browser-runtime entry point for the……

  • adapter.wasm — Browser-runtime entry point for the ./adapter conditional export in @suaveplan/db-sqlite. When a browser bundler re…

  • adapter.wasm — Browser-runtime entry point for the……

  • adapter.wasm — Browser-runtime entry point for the ./adapter conditional export in @suaveplan/db-sqlite. When a browser bundler re…

  • adapter.wasm — Browser-runtime entry point for the…

  • adapter.wasm — Browser-runtime entry point for the ./adapter conditional export in @suaveplan/db-sqlite. When a browser bundler re…

  • adapter.wasm — Browser-runtime entry point for the ./adapter conditional export in @suaveplan/db-sqlite. When a browser bundler re…

Purpose

SqliteAdapter is the main DatabaseAdapter implementation for @suaveplan/db-sqlite. It implements the full DatabaseAdapter contract from @suaveplan/db, backing it with a bun:sqlite database instance, an LRU PreparedStatementCache, a MigrationRunner, and OTel span instrumentation on every public operation.

The adapter is designed for the Bun server runtime only. Attempting to construct it outside Bun throws SqliteError(SQLITE.ENVIRONMENT_ERROR) immediately. Browser callers should use createWasmDriver directly via the ./adapter conditional export, which resolves to adapter.wasm.ts in browser bundles.

Features

  • Implements DatabaseAdapter from @suaveplan/db — fully substitutable wherever DatabaseLike is expected
  • Idempotent connect() — concurrent callers share one in-flight connection promise
  • PreparedStatementCache (LRU, default 128 entries) reused across query() calls
  • transaction() uses BEGIN IMMEDIATE to prevent deadlocks on concurrent writes; auto-rollback on failure
  • migrate() delegates to MigrationRunner and invalidates the cache on success
  • AbortSignal respected on every public method — throws SqliteError(SQLITE.*) when aborted
  • All operations wrapped in withQuerySpan for OTel tracing and latency metrics
  • sideEffects: false — safe for tree-shaking

Usage: Basic Example

import { SqliteAdapter } from "@suaveplan/db-sqlite";

const adapter = new SqliteAdapter({ filename: ":memory:" });
await adapter.connect();

const rows = await adapter.query<{ id: number }>(
  "SELECT id FROM users WHERE active = ?",
  [1]
);
await adapter.disconnect();

Usage: Advanced Example

import { SqliteAdapter } from "@suaveplan/db-sqlite";

const adapter = new SqliteAdapter({ filename: "/data/app.db" });
await adapter.connect();

// Transactional insert
await adapter.transaction(async (tx) => {
  await tx.execute("INSERT INTO accounts VALUES (?, ?)", [1, "Alice"]);
  await tx.execute("INSERT INTO accounts VALUES (?, ?)", [2, "Bob"]);
});

// Run migrations
const result = await adapter.migrate({
  migrationsFolder: "./db/migrations",
});
console.log(`Applied ${result.applied} migration(s)`);

await adapter.disconnect();

API Reference

new SqliteAdapter(options?, schema?)

Validates options, throws SqliteError(SQLITE.ENVIRONMENT_ERROR) outside Bun.

connect(config?, opts?): Promise<void>

Opens the SQLite file or :memory: database. Idempotent under concurrent calls — only one connection is opened.

disconnect(opts?): Promise<void>

Closes the database, invalidates the prepared-statement cache, and resets connection state.

query<T>(sql, params?, opts?): Promise<T[]>

Executes a SELECT query. Uses the prepared-statement cache for repeated SQL strings.

execute(sql, params?, opts?): Promise<{ rowsAffected: number }>

Executes a INSERT/UPDATE/DELETE statement. Returns affected row count.

transaction<T>(fn, opts?): Promise<T>

Runs fn inside a BEGIN IMMEDIATE transaction. Commits on success, rolls back on failure.

migrate(config?, opts?): Promise<MigrationResult>

Delegates to MigrationRunner and invalidates the prepared-statement cache on success.

isConnected: boolean

true after connect() and before disconnect().

Implementation Notes

The _connectingPromise field serialises concurrent connect() calls — the second caller awaits the same in-flight promise rather than opening a second connection. This is safe because bun:sqlite uses synchronous I/O under the covers and does not support concurrent connections to the same file.

transaction() casts this to DatabaseLike when passing it to fn. This is sound because SqliteAdapter implements all DatabaseLike methods. The cast avoids exposing internal _sqlite state to transaction callbacks while keeping the type constraint tight.