Files
WRNexusJS/packages/db/src/adapters/bunsql.ts
T
2026-07-12 15:55:18 +05:30

70 lines
2.1 KiB
TypeScript

/**
* Postgres + MySQL adapters built on Bun's native SQL client (`Bun.SQL`) — no
* external driver dependency. Both speak the same `Driver` interface; only the
* dialect (and thus the DDL types + placeholder style) differ.
*
* `Bun.SQL` pools connections, so transactions use its managed `begin(fn)` to
* keep BEGIN/…/COMMIT on one reserved connection.
*/
import type { Dialect } from "../sql.ts";
import type { Driver, Row, TxHandle } from "../driver.ts";
interface BunSqlClient {
unsafe(query: string, params?: unknown[]): Promise<unknown>;
begin<T>(fn: (tx: BunSqlClient) => Promise<T>): Promise<T>;
close(): Promise<void>;
}
interface ExecMeta {
count?: number;
affectedRows?: number;
lastInsertRowid?: number | bigint;
insertId?: number | bigint;
}
function runnerFor(client: BunSqlClient): TxHandle {
return {
async query(sql, params = []): Promise<Row[]> {
const rows = (await client.unsafe(sql, params)) as Iterable<Row>;
return Array.from(rows);
},
async exec(sql, params = []) {
const meta = (await client.unsafe(sql, params)) as ExecMeta;
const id = meta.lastInsertRowid ?? meta.insertId;
return {
changes: Number(meta.affectedRows ?? meta.count ?? 0),
lastInsertId: id != null ? Number(id) : undefined,
};
},
};
}
/** Create a Bun.sql-backed driver for the given connection URL + dialect. */
export function bunSql(url: string, dialect: Dialect): Driver {
const Ctor = (Bun as unknown as { SQL: new (u: string) => BunSqlClient }).SQL;
const client = new Ctor(url);
const runner = runnerFor(client);
return {
dialect,
query: runner.query,
exec: runner.exec,
transaction(fn) {
return client.begin((tx) => fn(runnerFor(tx)));
},
close() {
return client.close();
},
};
}
/** PostgreSQL adapter (`postgres://user:pass@host:5432/db`). Placeholders: `$N`. */
export function postgres(url: string): Driver {
return bunSql(url, "postgres");
}
/** MySQL adapter (`mysql://user:pass@host:3306/db`). Placeholders: `?`. */
export function mysql(url: string): Driver {
return bunSql(url, "mysql");
}