move the database and mailer to own log sub dir, add all email change logic

This commit is contained in:
creations 2025-06-13 20:33:29 -04:00
parent ddd00e3f85
commit a783a0e663
Signed by: creations
GPG key ID: 8F553AA4320FC711
26 changed files with 808 additions and 225 deletions

View file

@ -1,15 +1,16 @@
import { readFile, readdir } from "node:fs/promises";
import { resolve } from "node:path";
import { echo } from "@atums/echo";
import { Echo } from "@atums/echo";
import { environment } from "#environment/config";
import { migrationsPath } from "#environment/constants";
import { noFileLog } from "#index";
import { cassandra } from "#lib/database";
import type { SqlMigration } from "#types/config";
class MigrationRunner {
private migrations: SqlMigration[] = [];
private static logger: Echo = new Echo({ subDirectory: "migrations" });
private static loggerNoFile: Echo = new Echo({ disableFile: true });
async loadMigrations(): Promise<void> {
try {
@ -28,7 +29,7 @@ class MigrationRunner {
const name = nameParts.join("_") || "migration";
if (!id || id.trim() === "") {
noFileLog.debug(
MigrationRunner.loggerNoFile.debug(
`Skipping migration file with invalid ID: ${sqlFile}`,
);
continue;
@ -50,16 +51,18 @@ class MigrationRunner {
...(downSql && { downSql: downSql.trim() }),
});
} catch (error) {
echo.error({
MigrationRunner.logger.error({
message: `Failed to load migration ${sqlFile}:`,
error,
});
}
}
noFileLog.debug(`Loaded ${this.migrations.length} migrations`);
MigrationRunner.loggerNoFile.debug(
`Loaded ${this.migrations.length} migrations`,
);
} catch (error) {
noFileLog.debug({
MigrationRunner.loggerNoFile.debug({
message: "No migrations directory found or error reading:",
error,
});
@ -76,7 +79,7 @@ class MigrationRunner {
)
`;
await cassandra.execute(query);
noFileLog.debug("Schema migrations table ready");
MigrationRunner.loggerNoFile.debug("Schema migrations table ready");
}
private async getExecutedMigrations(): Promise<Set<string>> {
@ -86,7 +89,7 @@ class MigrationRunner {
)) as { rows: Array<{ id: string }> };
return new Set(result.rows.map((row) => row.id));
} catch (error) {
noFileLog.debug({
MigrationRunner.loggerNoFile.debug({
message: "Could not fetch executed migrations:",
error,
});
@ -133,7 +136,7 @@ class MigrationRunner {
async runMigrations(): Promise<void> {
if (this.migrations.length === 0) {
noFileLog.debug("No migrations to run");
MigrationRunner.loggerNoFile.debug("No migrations to run");
return;
}
await this.createMigrationsTable();
@ -142,29 +145,31 @@ class MigrationRunner {
(migration) => !executedMigrations.has(migration.id),
);
if (pendingMigrations.length === 0) {
noFileLog.debug("All migrations are up to date");
MigrationRunner.loggerNoFile.debug("All migrations are up to date");
return;
}
noFileLog.debug(
MigrationRunner.loggerNoFile.debug(
`Running ${pendingMigrations.length} pending migrations...`,
);
for (const migration of pendingMigrations) {
try {
noFileLog.debug(
MigrationRunner.loggerNoFile.debug(
`Running migration: ${migration.id} - ${migration.name}`,
);
await this.executeSql(migration.upSql);
await this.markMigrationExecuted(migration);
noFileLog.debug(`Migration ${migration.id} completed`);
MigrationRunner.loggerNoFile.debug(
`Migration ${migration.id} completed`,
);
} catch (error) {
echo.error({
MigrationRunner.logger.error({
message: `Failed to run migration ${migration.id}:`,
error,
});
throw error;
}
}
noFileLog.debug("All migrations completed successfully");
MigrationRunner.loggerNoFile.debug("All migrations completed successfully");
}
async initialize(): Promise<void> {