All checks were successful
Build and Publish Docker Image / build-and-push (push) Successful in 42s
44 lines
1.2 KiB
TypeScript
44 lines
1.2 KiB
TypeScript
import type { DatabaseSync } from "node:sqlite";
|
|
import { up as up0001CommentLikes } from "./migrations/0001_comment_likes.ts";
|
|
|
|
interface Migration {
|
|
name: string;
|
|
up: (db: DatabaseSync) => void;
|
|
}
|
|
|
|
// Append-only — never edit or reorder a migration once it has shipped.
|
|
// Each `up` must be idempotent: it also runs against fresh databases created
|
|
// straight from schema.sql, where the change it makes already exists.
|
|
const MIGRATIONS: Migration[] = [
|
|
{ name: "0001_comment_likes", up: up0001CommentLikes },
|
|
];
|
|
|
|
export function runMigrations(db: DatabaseSync): void {
|
|
db.exec(`CREATE TABLE IF NOT EXISTS schema_migrations (
|
|
name TEXT PRIMARY KEY,
|
|
applied_at TEXT NOT NULL
|
|
);`);
|
|
|
|
const applied = new Set(
|
|
(db.prepare(`SELECT name FROM schema_migrations;`).all() as {
|
|
name: string;
|
|
}[]).map((r) => r.name),
|
|
);
|
|
|
|
for (const { name, up } of MIGRATIONS) {
|
|
if (applied.has(name)) continue;
|
|
db.exec("BEGIN;");
|
|
try {
|
|
up(db);
|
|
db.prepare(
|
|
`INSERT INTO schema_migrations (name, applied_at) VALUES (?, ?);`,
|
|
).run(name, new Date().toISOString());
|
|
db.exec("COMMIT;");
|
|
console.log(`[migrate] applied ${name}`);
|
|
} catch (err) {
|
|
db.exec("ROLLBACK;");
|
|
throw err;
|
|
}
|
|
}
|
|
}
|