Files
EpicNext-Cms/src/app/api/admin/studio/nitro-cleanup/auto-clean/route.ts
T
openhands 438277a17a
CI / check (push) Successful in 4m15s
CI / preflight (push) Skipped
CI / deploy (push) Successful in 1m59s
feat(studio): expand nitro cleanup with repair, auto-clean, and orphaned assets
Scan distinguishes fake, broken, and orphaned SWF/icon assets with age
metadata, deletes per asset kind, re-downloads broken nitro bundles from
configured sources, auto-cleans old fake leftovers, and exports a JSON
manifest. Adds rebuild and auto-clean API endpoints with audit coverage
and a housekeeping preview route under the hotel domain.

Verified: full vitest suite (2213 tests), typecheck, and biome all pass.
2026-09-15 21:59:21 +02:00

55 lines
1.6 KiB
TypeScript

import { apiError, apiOk } from "@/lib/api";
import { withAdmin } from "@/lib/api-handler";
import { PERMS } from "@/lib/permissions";
import { logAudit } from "@/lib/services/audit";
import { clearFurniImportCache } from "@/lib/services/furni-import-cache";
import { autoCleanFakeNitros } from "@/lib/services/nitro-cleanup";
/** Automatically remove fake .nitro leftovers older than `maxAgeDays`. */
export const POST = withAdmin(
{ permission: PERMS.ASSETS_IMPORT },
async (request, ctx) => {
let body: { maxAgeDays?: unknown };
try {
body = await request.json();
} catch {
return apiError("Invalid JSON body", 400);
}
const maxAgeDays =
typeof body?.maxAgeDays === "number" && Number.isFinite(body.maxAgeDays)
? Math.max(0, Math.floor(body.maxAgeDays))
: 30;
try {
const result = await autoCleanFakeNitros(maxAgeDays);
clearFurniImportCache();
if (result.deleted > 0) {
logAudit({
userId: ctx.session.user.id,
action: "nitro_auto_cleanup",
target: "NitroFiles",
after: {
maxAgeDays,
deleted: result.deleted,
copiesRemoved: result.copiesRemoved,
skippedRecent: result.skippedRecent,
skippedBroken: result.skippedBroken,
errors: result.errors.length > 0 ? result.errors : undefined,
},
});
}
return apiOk({
deleted: result.deleted,
copiesRemoved: result.copiesRemoved,
skippedRecent: result.skippedRecent,
skippedBroken: result.skippedBroken,
errors: result.errors.length > 0 ? result.errors : undefined,
});
} catch (err) {
return apiError(
`Nitro auto-cleanup failed: ${(err as Error).message}`,
500,
);
}
},
);