Skip to main content

SQLite (WebAssembly / sql.js)

@sqb/sqljs is the SQB adapter for SQLite compiled to WebAssembly via sql.js. Use it wherever native SQLite bindings aren't available — in a browser, or in a JS runtime/environment where @sqb/sqlite's node:sqlite/bun:sqlite requirement can't be met.

Install

npm install @sqb/sqljs sql.js

@sqb/connect and @sqb/builder are peer dependencies pulled in transitively if you already depend on them directly; otherwise install them alongside.

Registering the adapter

Importing @sqb/sqljs registers it as a side effect:

import '@sqb/sqljs';
import { SqbClient } from '@sqb/connect';

const client = new SqbClient({
dialect: 'sqlite', // shares the "sqlite" dialect with @sqb/sqlite
database: './mydb.sqlite',
});
import { AdapterRegistry } from '@sqb/connect';
import { SqljsAdapter } from './sqljs-adapter.js';

AdapterRegistry.register(new SqljsAdapter());

Unlike the other adapter packages, @sqb/sqljs's entry point registers the adapter and exports nothing else — import it purely for the registration side effect.

warning

Unlike @sqb/sqlite, @sqb/sqljs's entry point does not import @sqb/sqlite-dialect for you — you must import it yourself alongside @sqb/sqljs:

import '@sqb/sqlite-dialect';
import '@sqb/sqljs';

Without it, @sqb/builder has no SerializerExtension registered for dialect: 'sqlite' and silently falls back to generic, non-dialect-aware SQL (see Why it matters that it's dialect-aware) rather than throwing — an easy way to end up with subtly wrong pagination/quoting without noticing.

SqljsAdapter reports driver: 'sqljs', but dialect: 'sqlite' — the same dialect name as @sqb/sqlite, since both generate standard SQLite SQL. This means:

note

Select this adapter with driver: 'sqljs' if @sqb/sqlite is also registered in the same process (since dialect: 'sqlite' would be ambiguous between the two); dialect: 'sqlite' is fine if @sqb/sqljs is the only SQLite adapter you've imported.

Configuration

database is required — the adapter throws if it's missing. It's resolved as an absolute file path, except for the special value :memory: (optionally suffixed, e.g. :memory:mydb), which opens an in-memory database instead. For a non-memory path, the file's contents are read up-front via fs.readFile and loaded into an in-memory sql.js database — there is no incremental disk I/O after that:

new SqbClient({ dialect: 'sqlite', database: './mydb.sqlite' });

There is no driverOptions passthrough for this adapter — only database is used to open the connection. sql.js itself runs entirely in-memory (it's a WebAssembly build of SQLite with no native filesystem access), so persisting changes back to disk is the caller's responsibility.

Connection sharing

Multiple SqbClient/pool connections opened against the same non-memory database path share a single underlying sql.js Database instance (reference-counted, closed once the last connection to it closes).

Feature notes

  • Cursors: supported (features.cursor: true).
  • Schemas: not supported.
  • RETURNING: emulated with a follow-up query — for inserts, via where rowid = last_insert_rowid(); for updates, by re-running the original WHERE clause.

Migrator support

warning

@sqb/migrator currently only implements its migration adapter for PostgreSQL — see Running migrations. SQLite/sql.js migrations must be managed outside @sqb/migrator today.

See also