Files
EpicNext-Cms/src/app/api/admin/import/audit/route.ts
T
openhands 1b817fe434
CI / check (push) Successful in 24s
CI / release (push) Skipped
CI / deploy (push) Successful in 1m0s
fix: resolve critical bugs and improve admin panel reliability
- Fix missing await in pets API route causing empty responses
- Fix updateSetting to use upsert pattern instead of update-only
- Create missing /api/admin/sounds/upload route (upload was broken)
- Wire bulk delete actions in catalog table
- Replace native confirm() with useConfirmDialog() across rooms and clone pages
- Add error logging to silent catch blocks in radio actions and audit route
- Add graceful degradation to devops health endpoint
- Add cache eviction to clone icon route to prevent memory leak
- Internationalize hardcoded Italian strings to English
- Remove placeholder created_at fields from prefix API responses
- Remove dead code and fix type errors in translations and import pages
- Standardize PERMS import path in analytics export route
2026-08-06 18:32:55 +02:00

83 lines
1.9 KiB
TypeScript

import { withAdmin } from "@/lib/api-handler";
import { logger } from "@/lib/logger";
import { PERMS } from "@/lib/permissions";
import { runCatalogAudit } from "@/lib/services/catalog-audit";
function sseEvent(data: unknown): string {
return `data: ${JSON.stringify(data)}\n\n`;
}
export const POST = withAdmin(
{ permission: PERMS.ASSETS_IMPORT },
async (request) => {
const encoder = new TextEncoder();
let repair = false;
let repairNitros = false;
let sql = false;
let applySql = false;
let repairFurniData = false;
let repairStructure = false;
try {
const body = (await request.json().catch(() => ({}))) as {
repair?: unknown;
repairNitros?: unknown;
sql?: unknown;
applySql?: unknown;
repairFurniData?: unknown;
repairStructure?: unknown;
};
repair = body.repair === true;
repairNitros = body.repairNitros === true;
sql = body.sql === true;
applySql = body.applySql === true;
repairFurniData = body.repairFurniData === true;
repairStructure = body.repairStructure === true;
} catch (err) {
logger.warn("Failed to parse audit request body", { err });
}
const stream = new ReadableStream({
async start(controller) {
const send = (data: unknown) => {
try {
controller.enqueue(encoder.encode(sseEvent(data)));
} catch {
/* stream closed */
}
};
try {
await runCatalogAudit(send, {
repair,
repairNitros,
sql,
applySql,
repairFurniData,
repairStructure,
});
} catch (err) {
send({
type: "error",
message: `Audit threw: ${(err as Error).message}`,
});
}
try {
controller.close();
} catch (err) {
logger.warn("Failed to close audit SSE stream", { err });
}
},
});
return new Response(stream, {
headers: {
"Content-Type": "text/event-stream",
"Cache-Control": "no-cache",
Connection: "keep-alive",
},
});
},
);