import Database from 'better-sqlite3'; interface Migration { id: string; // unique, immutable — format: NNNN_short_description up: (db: InstanceType) => void; } // Append only. Never reorder or remove entries — that would corrupt tracking. // Each `up` function receives the open DB handle inside an already-open transaction. const migrations: Migration[] = [ { id: '0001_rename_device_checkMkUrl_to_cmkUrl', up: (db) => { db.exec(`ALTER TABLE devices RENAME COLUMN checkMkUrl TO cmkUrl`); }, }, { id: '0002_rename_booking_ansible_to_semaphore', up: (db) => { db.exec(`ALTER TABLE bookings RENAME COLUMN ansibleSetupTriggered TO semaphoreSetupTriggered`); db.exec(`ALTER TABLE bookings RENAME COLUMN ansibleTeardownTriggered TO semaphoreTeardownTriggered`); db.exec(`ALTER TABLE bookings RENAME COLUMN ansibleSetupJobId TO semaphoreSetupJobId`); db.exec(`ALTER TABLE bookings RENAME COLUMN ansibleTeardownJobId TO semaphoreTeardownJobId`); }, }, ]; export function runMigrations(db: InstanceType): void { db.exec(` CREATE TABLE IF NOT EXISTS _migrations ( id TEXT PRIMARY KEY, applied_at TEXT NOT NULL DEFAULT (datetime('now')) ) `); const isApplied = db.prepare('SELECT 1 FROM _migrations WHERE id = ?'); const markApplied = db.prepare('INSERT INTO _migrations (id) VALUES (?)'); for (const migration of migrations) { if (isApplied.get(migration.id)) continue; console.log(`[Migrations] Applying: ${migration.id}`); db.transaction(() => { migration.up(db); markApplied.run(migration.id); })(); console.log(`[Migrations] Applied: ${migration.id}`); } }