Browser SQLite and D1
SQLBraid keeps SQLite as one dialect while separating the execution driver and runtime. Browser code uses SQLite WASM; a Worker binding uses Cloudflare D1. Neither path changes the SQLBraid query contract.
SQLite WASM
Section titled “SQLite WASM”Install the SQLite package and official WASM runtime in the application that owns the browser/worker resource:
npm install sqlbraid @sqlite.org/sqlite-wasmCreate one direct database from the OO1-style object in the current realm:
import { createSqliteWasmDatabase, sql } from "sqlbraid/sqlite-wasm";
const db = createSqliteWasmDatabase(wasmDatabase, { sqlite3 });const rows = await db.all(sql.rows<{ id: string }>`SELECT id FROM account`);INTEGER storage is exposed as a canonical decimal string. The WASM adapter uses
native column types and sqlite3_column_int64, not a numeric-value heuristic;
integral REAL values remain number. Native bigint is an internal transport
detail and is not a public integer mode. D1 is a separate guarded profile:
safe integral JavaScript Numbers become strings, while values outside the safe
range are unsupported rather than rounded.
The adapter supports prepare/bind/step/finalize, row streaming by pull, callback transactions, and command-only bulk with one prepared statement reset per item. It is a direct resource, not a pool. While a transaction or stream owns it, conflicting root operations reject; SQLBraid does not depend on an incomplete async-context polyfill.
Cloudflare D1
Section titled “Cloudflare D1”D1 remains SQLite and uses a structural binding interface, so the package does not require a Cloudflare type package at runtime:
import { createD1Database } from "sqlbraid/d1";
const db = createD1Database(env.DB);D1 exposes untyped JavaScript numbers. Its guarded profile rejects integral
numbers outside the safe range; this also excludes integral REAL values outside
that range because the public result API cannot distinguish them from rounded
INTEGER values. It does not promise full int64 or exact decimal output.
The API denies sqlite_version(), so db.environment() leaves the server
version unknown. A Worker compatibility date is not a database version.
D1 uses ordered ?1, ?2, … binds and public result metadata for materialized
queries. db.bulk() maps one logical shape to one D1Database.batch() call and
reports remote-batch. D1 has no incremental row cursor in the Worker Binding
API: db.stream() is BRAID_STREAM_UNSUPPORTED, and SQLBraid does not paginate
to simulate streaming. Callback db.tx() is unsupported unless a future D1
primitive matches SQLBraid’s callback transaction contract.
The native D1 batch may have stronger transaction behavior than root bulk, but that is not the portable SQLBraid contract. Root bulk is not implicitly transactional and has no portable auto-chunking promise.
The runtime and driver support matrix records labels for the exact database/driver/profile/runtime/capability tuple and its revision and workflow evidence. A neighboring version or package installation is not certification. Final exact-SHA Runtime, Docs, and Release gates and explicit release authorization remain separate requirements. D1 remains Compatible; its managed SQLite version is unreported. No browser gate claims OPFS persistence, SharedArrayBuffer, remote production support, or npm publication.
Browser and Worker representation profiles
Section titled “Browser and Worker representation profiles”SQLite remains the dialect, but WASM and D1 are different drivers and must not share an evidence label.
| Driver | Driver raw / SQLBraid canonical boundary | Stream/bulk/transaction |
|---|---|---|
| SQLite WASM OO1 | SQLite dynamic values; INTEGER storage is canonical string | pull iteration, prepared-loop bulk, callback transaction |
| Cloudflare D1 binding | materialized rows and ordered ?1, ?2, … binds |
native batch() bulk; streaming and callback transaction are unsupported |
JSON1 is text unless the selected WASM build/parser proves another
representation. BLOB values remain bytes. Native RETURNING is materialized
before delivery. Browser SQL is sent through transparently; this does not make
the browser runtime a SQL grammar implementation or make Node-only adapters
browser-compatible.