You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
68 lines
2.0 KiB
68 lines
2.0 KiB
import { QueryExecResult } from "../interfaces/database";
|
|
|
|
interface Migration {
|
|
name: string;
|
|
sql: string;
|
|
}
|
|
|
|
export class MigrationService {
|
|
private static instance: MigrationService;
|
|
private migrations: Migration[] = [];
|
|
|
|
private constructor() {}
|
|
|
|
static getInstance(): MigrationService {
|
|
if (!MigrationService.instance) {
|
|
MigrationService.instance = new MigrationService();
|
|
}
|
|
return MigrationService.instance;
|
|
}
|
|
|
|
async registerMigration(migration: Migration): Promise<void> {
|
|
this.migrations.push(migration);
|
|
}
|
|
|
|
async runMigrations(
|
|
sqlExec: (sql: string, params?: any[]) => Promise<Array<QueryExecResult>>,
|
|
): Promise<void> {
|
|
// Create migrations table if it doesn't exist
|
|
await sqlExec(`
|
|
CREATE TABLE IF NOT EXISTS migrations (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
name TEXT NOT NULL UNIQUE,
|
|
executed_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
`);
|
|
|
|
// Get list of executed migrations
|
|
const result: QueryExecResult[] = await sqlExec(
|
|
"SELECT name FROM migrations;",
|
|
);
|
|
let executedMigrations: Set<string> = new Set();
|
|
// Even with that query, the QueryExecResult may be [] (which doesn't make sense to me).
|
|
if (result.length > 0) {
|
|
const singleResult = result[0];
|
|
executedMigrations = new Set(
|
|
singleResult.values.map((row: any[]) => row[0]),
|
|
);
|
|
}
|
|
|
|
// Run pending migrations in order
|
|
for (const migration of this.migrations) {
|
|
if (!executedMigrations.has(migration.name)) {
|
|
try {
|
|
await sqlExec(migration.sql);
|
|
await sqlExec("INSERT INTO migrations (name) VALUES (?)", [
|
|
migration.name,
|
|
]);
|
|
console.log(`Migration ${migration.name} executed successfully`);
|
|
} catch (error) {
|
|
console.error(`Error executing migration ${migration.name}:`, error);
|
|
throw error;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
export default MigrationService.getInstance();
|
|
|