import { Database } from "bun:sqlite";
import { ACCOUNT_SCHEMA, REPO_SCHEMA } from "./schema.gen";
import { ACCOUNT_SCHEMA_EXTRA, REPO_SCHEMA_EXTRA } from "./schema-extra";
import type { ScopedDb, ScopedStatement, ScopedValue } from "./types";
/**
* Test double for `~/server/scoped-db`: every repo and account gets its own in-memory bun:sqlite with the real
* scoped schema. Use with `mock.module("<path>/scoped-db", () => memoryScopes().module)`.
*/
export function memoryScopes() {
const databases = new Map<string, Database>();
const open = (key: string, schema: readonly string[]) => {
let db = databases.get(key);
if (!db) {
db = new Database(":memory:");
for (const statement of schema) db.run(statement);
databases.set(key, db);
}
return db;
};
const make = (scopeId: string, db: Database): ScopedDb => {
const meta = (result: { changes: number; lastInsertRowid: number | bigint }) => ({
meta: { changes: result.changes, last_row_id: Number(result.lastInsertRowid) },
});
return {
scopeId,
async first<T>(sql: string, ...params: ScopedValue[]) {
return (db.query(sql).get(...params) as T | null) ?? null;
},
async all<T>(sql: string, ...params: ScopedValue[]) {
return db.query(sql).all(...params) as T[];
},
async run(sql: string, ...params: ScopedValue[]) {
return meta(db.query(sql).run(...params));
},
async batch(statements: ScopedStatement[]) {
return db.transaction(() =>
statements.map((statement) => meta(db.query(statement.sql).run(...statement.params))),
)();
},