/** * The database handle. Importing this module opens the database at * {@link DB_PATH}, applies the pending migrations and runs the startup tasks. * * @module */ import { DatabaseSync } from "node:sqlite"; import { DB_PATH } from "../config.ts"; import { runMigrations } from "./migrate.ts"; import { runStartupTasks } from "./startup.ts"; /** The one connection every service queries through. */ export const db: DatabaseSync = new DatabaseSync(DB_PATH); // WAL lets readers run alongside a writer, and with synchronous = NORMAL a // commit no longer waits on an fsync (a crash can lose the last transactions, // never corrupt the file). busy_timeout covers the init/migration scripts and // the test harness opening the same file. db.exec(` PRAGMA journal_mode = WAL; PRAGMA synchronous = NORMAL; PRAGMA busy_timeout = 5000; PRAGMA foreign_keys = ON; `); runMigrations(db); await runStartupTasks(db); /** * Runs `fn` inside one transaction: several writes commit together (and cost * one commit rather than one each), and a throw rolls them all back. Nested * calls join the outer transaction. */ export function transaction(fn: () => T): T { if (db.isTransaction) return fn(); db.exec("BEGIN;"); try { const result = fn(); db.exec("COMMIT;"); return result; } catch (err) { db.exec("ROLLBACK;"); throw err; } }