Driver
The storage surface the ORM runs against. Three methods.
ts
export interface Driver {
exec(sql: string): Promise<void>;
run(sql: string, params?: readonly unknown[]): Promise<RunResult>;
all<T = Record<string, unknown>>(
sql: string,
params?: readonly unknown[],
): Promise<T[]>;
close?(): Promise<void>;
}
export interface RunResult {
changes: number;
lastInsertRowid: number | bigint;
}exec— run SQL, ignore result. Typically schema DDL / transaction control (BEGIN/COMMIT).run— run a mutation, return row count + last inserted id.all— run a SELECT, return rows asRecord<string, unknown>[](the generic is for typed consumers).close— optional. Called byorm.close().
Built-in: SqlJsDriver
ts
import { SqlJsDriver } from "sql-reactive-orm/drivers/sqljs";ts
interface SqlJsDriverOptions {
locateFile?: (file: string) => string;
wasmBinary?: ArrayBuffer;
data?: Uint8Array;
}locateFile(name)— return the URL / path for thenamed support file. Used to point at the bundler-resolvedsql-wasm.wasm.wasmBinary— alternative tolocateFile; pass the bytes directly.data— pre-existing database bytes (from a download, a file, or a previousdriver.export()).
Methods:
SqlJsDriver.open(opts?)— static factory returning a resolved instance.driver.export()—Uint8Arrayof the whole db.driver.close()— closes the connection.
wrapReactive
Low-level. Used by new Orm(driver) internally; exported for advanced users who want to layer their own wrappers:
ts
import { wrapReactive, detectMutatedTables } from "sql-reactive-orm";
const reactive = wrapReactive(rawDriver, (tables: Set<string>) => {
for (const t of tables) myBus.notify(t);
});The wrapper:
- On
run/exec, callsdetectMutatedTables(sql)to extract INSERT / UPDATE / DELETE / REPLACE / DROP TABLE / ALTER TABLE targets. - Inside
BEGIN ... COMMIT, accumulates the set and fires once onCOMMIT. Dropped onROLLBACK. allis a direct delegate.
Writing a custom driver
Any backend that can run SQL qualifies. See Drivers for a better-sqlite3 sketch.
Invariants:
execreturns when all statements complete. Don't swallow errors.runmust return accuratechanges(usesqlite3_changes()/ the driver's equivalent).allreturns rows in SELECT order (for consumer stability).close(if defined) makes subsequent calls throw.