infernod/core/migrations/migrations.ts

75 lines
2 KiB
TypeScript
Raw Permalink Normal View History

import type { DuckDBConnection } from "@duckdb/node-api";
import type { Manager } from "../manager.ts";
import type { Migration } from "./migration.ts";
import { V001_AddAgents } from "./migrations/V001_AddAgents.ts";
import { V002_AddApplicationWorkers } from "./migrations/V002_AddApplicationWorkers.ts";
import { V003_AddServiceProviders } from "./migrations/V003_AddServiceProviders.ts";
import { V004_AddSoftwares } from "./migrations/V004_AddSoftwares.ts";
export class Migrations {
protected connection: Promise<DuckDBConnection>;
constructor(protected manager: Manager) {
this.connection = this.manager.newDatabaseConnection();
}
/**
* Create migrations table if it does not exist.
* @protected
*/
protected async setupMigrationsTable() {
await (
await this.connection
).run(`
CREATE OR REPLACE TABLE migrations(
id VARCHAR(255) PRIMARY KEY,
migrated_at TIMESTAMPTZ DEFAULT NOW()
);
`);
}
/**
* Check if the provided migration is executed or not.
* @param migrationIdentifier The migration identifier to check for.
* @protected
*/
protected async isExecuted(migrationIdentifier: string): Promise<boolean> {
return (
(
await (
await this.connection
).runAndRead("SELECT id FROM migrations WHERE id = $id", {
id: migrationIdentifier,
})
).columnCount > 0
);
}
/**
* Register the provided migration.
* @param MigrationClass Migration class to register.
* @protected
*/
protected async register(MigrationClass: { new (): Migration }) {
const migration = new MigrationClass();
if (!(await this.isExecuted(migration.getIdentifier()))) {
await migration.execute(await this.connection);
}
}
async execute() {
await this.setupMigrationsTable();
await this.register(V001_AddAgents);
await this.register(V002_AddApplicationWorkers);
await this.register(V003_AddServiceProviders);
await this.register(V004_AddSoftwares);
}
async close() {
(await this.connection).closeSync();
}
}