feat: add secure auth, admin and postgres persistence

This commit is contained in:
2026-07-29 21:52:22 -04:00
parent 74b4c3a368
commit 432dd2176f
18 changed files with 946 additions and 256 deletions
+24
View File
@@ -0,0 +1,24 @@
import pg from "pg";
import fs from "node:fs/promises";
import path from "node:path";
import { fileURLToPath } from "node:url";
export function createDb(connectionString = process.env.DATABASE_URL) {
if (!connectionString) throw new Error("DATABASE_URL is required");
const pool = new pg.Pool({ connectionString, max: 10, ssl: process.env.DATABASE_SSL === "true" ? { rejectUnauthorized: true } : undefined });
return { query: (...args) => pool.query(...args), close: () => pool.end() };
}
/** Apply each versioned SQL file once; failed migrations are not recorded. */
export async function migrate(db) {
await db.query("CREATE TABLE IF NOT EXISTS schema_migrations (filename text PRIMARY KEY, applied_at timestamptz NOT NULL DEFAULT now())");
const directory = path.join(path.dirname(fileURLToPath(import.meta.url)), "..", "db", "migrations");
const files = (await fs.readdir(directory)).filter((file) => file.endsWith(".sql")).sort();
for (const filename of files) {
if ((await db.query("SELECT 1 FROM schema_migrations WHERE filename=$1", [filename])).rowCount) continue;
const sql = await fs.readFile(path.join(directory, filename), "utf8");
await db.query("BEGIN");
try { await db.query(sql); await db.query("INSERT INTO schema_migrations(filename) VALUES($1)", [filename]); await db.query("COMMIT"); }
catch (error) { await db.query("ROLLBACK"); throw error; }
}
}