release: WRNexusJS 0.5.10

This commit is contained in:
2026-07-30 13:36:29 +05:30
parent 8fc6f15402
commit d1b0c55b53
159 changed files with 7509 additions and 604 deletions
+12 -5
View File
@@ -23,14 +23,21 @@ interface ExecMeta {
insertId?: number | bigint;
}
function runnerFor(client: BunSqlClient): TxHandle {
/** Convert the framework's portable positional placeholders for PostgreSQL. */
export function sqlForDialect(sql: string, dialect: Dialect): string {
if (dialect !== "postgres" || !sql.includes("?")) return sql;
let index = 0;
return sql.replace(/\?/g, () => `$${++index}`);
}
function runnerFor(client: BunSqlClient, dialect: Dialect): TxHandle {
return {
async query(sql, params = []): Promise<Row[]> {
const rows = (await client.unsafe(sql, params)) as Iterable<Row>;
const rows = (await client.unsafe(sqlForDialect(sql, dialect), params)) as Iterable<Row>;
return Array.from(rows);
},
async exec(sql, params = []) {
const meta = (await client.unsafe(sql, params)) as ExecMeta;
const meta = (await client.unsafe(sqlForDialect(sql, dialect), params)) as ExecMeta;
const id = meta.lastInsertRowid ?? meta.insertId;
return {
changes: Number(meta.affectedRows ?? meta.count ?? 0),
@@ -44,13 +51,13 @@ function runnerFor(client: BunSqlClient): TxHandle {
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);
const runner = runnerFor(client, dialect);
return {
dialect,
query: runner.query,
exec: runner.exec,
transaction(fn) {
return client.begin((tx) => fn(runnerFor(tx)));
return client.begin((tx) => fn(runnerFor(tx, dialect)));
},
close() {
return client.close();
+22 -6
View File
@@ -12,7 +12,9 @@
import type { Db } from "./driver.ts";
const DEFAULT = "default";
const registry = new Map<string, Db>();
type DbFactory = () => Db;
type RegistryEntry = { db?: Db; factory?: DbFactory };
const registry = new Map<string, RegistryEntry>();
/** Set the default database (called by the runtime at startup). */
export function setDb(db: Db): Db;
@@ -21,7 +23,7 @@ export function setDb(name: string, db: Db): Db;
export function setDb(a: string | Db, b?: Db): Db {
const name = typeof a === "string" ? a : DEFAULT;
const db = typeof a === "string" ? b! : a;
registry.set(name, db);
registry.set(name, { db });
return db;
}
@@ -30,10 +32,18 @@ export function registerDb(name: string, db: Db): Db {
return setDb(name, db);
}
/**
* Register a named database without opening its connection pool. The first
* `getDb(name)` call creates and caches the connection.
*/
export function registerLazyDb(name: string, factory: DbFactory): void {
registry.set(name, { factory });
}
/** The default database, or a named one. Throws if it isn't configured. */
export function getDb(name = DEFAULT): Db {
const db = registry.get(name);
if (!db) {
const entry = registry.get(name);
if (!entry) {
throw new Error(
name === DEFAULT
? "No database configured. Add `db: { driver, url }` to wrnexus.config.ts."
@@ -41,7 +51,11 @@ export function getDb(name = DEFAULT): Db {
`(e.g. databases: { ${name}: { driver, url } }).`,
);
}
return db;
if (!entry.db) {
if (!entry.factory) throw new Error(`Database '${name}' has no connection factory.`);
entry.db = entry.factory();
}
return entry.db;
}
/** Whether the default (or a named) database has been configured. */
@@ -56,6 +70,8 @@ export function databaseNames(): string[] {
/** Close every configured database and clear the registry. */
export async function closeDatabases(): Promise<void> {
for (const db of registry.values()) await db.close();
for (const entry of registry.values()) {
if (entry.db) await entry.db.close();
}
registry.clear();
}
+9 -1
View File
@@ -10,7 +10,15 @@ export { v, table, Column } from "./schema.ts";
export type { Model, Columns, ColumnDef, BaseType } from "./schema.ts";
export { createDb } from "./driver.ts";
export type { Db, Driver, Row, ExecResult, TxHandle } from "./driver.ts";
export { setDb, getDb, hasDb, registerDb, databaseNames, closeDatabases } from "./client.ts";
export {
setDb,
getDb,
hasDb,
registerDb,
registerLazyDb,
databaseNames,
closeDatabases,
} from "./client.ts";
export { createTableSql } from "./sql.ts";
export type { Dialect } from "./sql.ts";
export {
+1
View File
@@ -65,6 +65,7 @@ export async function appliedMigrations(db: Db): Promise<string[]> {
/** Apply an ordered migration list (each in a transaction). Returns applied names. */
export async function applyMigrations(db: Db, migrations: readonly Migration[]): Promise<string[]> {
if (migrations.length === 0) return [];
const applied = new Set(await appliedMigrations(db));
const pending = migrations.filter((migration) => !applied.has(migration.name));
const done: string[] = [];