import { readdir, readFile } from "node:fs/promises"; import { join } from "node:path"; import pg from "pg"; const connectionString = process.env.DATABASE_URL; if (!connectionString) { throw new Error("DATABASE_URL must be configured"); } const pool = new pg.Pool({ connectionString }); try { await pool.query(` CREATE TABLE IF NOT EXISTS schema_migrations ( name text PRIMARY KEY, applied_at timestamptz NOT NULL DEFAULT now() ) `); const applied = await pool.query("SELECT name FROM schema_migrations"); const appliedNames = new Set(applied.rows.map((row) => row.name)); const directory = join(process.cwd(), "db", "migrations"); const files = (await readdir(directory)) .filter((file) => /^\d+_.+\.sql$/.test(file)) .sort(); const client = await pool.connect(); try { await client.query("BEGIN"); for (const file of files.filter((name) => !appliedNames.has(name))) { await client.query(await readFile(join(directory, file), "utf8")); await client.query("INSERT INTO schema_migrations (name) VALUES ($1)", [file]); } await client.query("COMMIT"); } catch (error) { await client.query("ROLLBACK"); throw error; } finally { client.release(); } } finally { await pool.end(); }