Files
homarr/apps/nextjs/src/app/api/backup/migrations/route.ts
T
Thomas Camlong 6befc5ad41 fix(backup): log restore errors via the central logger and harden cleanup
Replace raw console.error calls in the backup import/migrations routes with
createLogger + ErrorWithMetadata so restore failures flow through the standard
log transports (console + Redis). Wrap the temporary DB close in finally so a
close failure cannot 500 a successful restore, and log client-side restore and
analysis failures to the browser console.
2026-08-18 11:14:04 +02:00

69 lines
1.9 KiB
TypeScript

import fs from "fs";
import path from "path";
import { NextResponse } from "next/server";
import { createLogger } from "@homarr/core/infrastructure/logs";
import { ErrorWithMetadata } from "@homarr/core/infrastructure/logs/error";
import { findMigrationsFolder } from "../shared";
const logger = createLogger({ module: "backupMigrationsRoute" });
interface JournalEntry {
idx: number;
version: string;
when: number;
tag: string;
breakpoints: boolean;
}
interface MigrationFile {
idx: number;
tag: string;
sql: string;
when: number;
}
export async function GET() {
try {
const migrationsFolder = findMigrationsFolder();
if (!migrationsFolder) {
return NextResponse.json({ error: "Migration files not found" }, { status: 500 });
}
const journalPath = path.join(migrationsFolder, "meta", "_journal.json");
if (!fs.existsSync(journalPath)) {
return NextResponse.json({ error: "Migration journal not found" }, { status: 500 });
}
const journal = JSON.parse(fs.readFileSync(journalPath, "utf-8")) as { entries: JournalEntry[] };
const migrations: MigrationFile[] = [];
for (const entry of journal.entries) {
const sqlPath = path.join(migrationsFolder, `${entry.tag}.sql`);
if (!fs.existsSync(sqlPath)) continue;
migrations.push({
idx: entry.idx,
tag: entry.tag,
sql: fs.readFileSync(sqlPath, "utf-8"),
when: entry.when,
});
}
return NextResponse.json(
{ total: migrations.length, migrations },
{
headers: {
"Cache-Control": "public, max-age=3600",
},
},
);
} catch (error) {
logger.error(new ErrorWithMetadata("Failed to read migration files", {}, { cause: error }));
const message = error instanceof Error ? error.message : "Unknown error";
return NextResponse.json({ error: `Failed to read migrations: ${message}` }, { status: 500 });
}
}