90 lines
2.3 KiB
TypeScript
90 lines
2.3 KiB
TypeScript
import type sqlite3 from "better-sqlite3";
|
|
import { config } from "../../config";
|
|
import { logger } from "../../logger";
|
|
import { migrations } from "./migrations";
|
|
|
|
export const DATABASE_VERSION = 3;
|
|
|
|
let database: sqlite3.Database | undefined;
|
|
let log = logger.child({ module: "database" });
|
|
|
|
export function getDatabase(): sqlite3.Database {
|
|
if (!database) {
|
|
throw new Error("Sqlite database not initialized.");
|
|
}
|
|
return database;
|
|
}
|
|
|
|
export async function initializeDatabase() {
|
|
if (!config.eventLogging) {
|
|
return;
|
|
}
|
|
|
|
log.info("Initializing database...");
|
|
|
|
const sqlite3 = await import("better-sqlite3");
|
|
database = sqlite3.default(config.sqliteDataPath);
|
|
migrateDatabase();
|
|
database.pragma("journal_mode = WAL");
|
|
log.info("Database initialized.");
|
|
}
|
|
|
|
export function migrateDatabase(
|
|
targetVersion = DATABASE_VERSION,
|
|
targetDb?: sqlite3.Database
|
|
) {
|
|
const db = targetDb || getDatabase();
|
|
|
|
const currentVersion = db.pragma("user_version", { simple: true });
|
|
assertNumber(currentVersion);
|
|
|
|
if (currentVersion === targetVersion) {
|
|
log.info("No migrations to run.");
|
|
return;
|
|
}
|
|
|
|
const direction = currentVersion < targetVersion ? "up" : "down";
|
|
const pending = migrations
|
|
.slice()
|
|
.sort((a, b) =>
|
|
direction === "up" ? a.version - b.version : b.version - a.version
|
|
)
|
|
.filter((m) =>
|
|
direction === "up"
|
|
? m.version > currentVersion && m.version <= targetVersion
|
|
: m.version > targetVersion && m.version <= currentVersion
|
|
);
|
|
|
|
if (pending.length === 0) {
|
|
log.warn("No pending migrations found.");
|
|
return;
|
|
}
|
|
|
|
for (const migration of pending) {
|
|
const { version, name, up, down } = migration;
|
|
if (
|
|
(direction === "up" && version > currentVersion) ||
|
|
(direction === "down" && version <= currentVersion)
|
|
) {
|
|
if (direction === "up") {
|
|
log.info({ name }, "Applying migration.");
|
|
up(db);
|
|
db.pragma("user_version = " + version);
|
|
} else {
|
|
log.info({ name }, "Reverting migration.");
|
|
down(db);
|
|
db.pragma("user_version = " + (version - 1));
|
|
}
|
|
}
|
|
}
|
|
|
|
log.info("Migrations applied.");
|
|
}
|
|
|
|
function assertNumber(value: unknown): asserts value is number {
|
|
if (typeof value !== "number") {
|
|
throw new Error("Expected number");
|
|
}
|
|
}
|
|
export { EventLogEntry } from "./repos/event";
|