import { NextRequest, NextResponse } from "next/server"; import { appendFile, mkdir } from "fs/promises"; import { dirname } from "path"; export const dynamic = "force-dynamic"; export const runtime = "nodejs"; const LOG_PATH = process.env.MC_DASHBOARD_ERROR_LOG || "/home/minecraft/logs/mc-dashboard/errors.log"; let ensured = false; async function ensureLog() { if (ensured) return; try { await mkdir(dirname(LOG_PATH), { recursive: true }); ensured = true; } catch {} } // Very light throttle: drop any request shorter than THROTTLE_MS after the last const THROTTLE_MS = 200; let lastWrite = 0; export async function POST(req: NextRequest) { const now = Date.now(); if (now - lastWrite < THROTTLE_MS) { return NextResponse.json({ ok: true, throttled: true }); } lastWrite = now; let body: unknown; try { body = await req.json(); } catch { return NextResponse.json({ error: "Invalid JSON" }, { status: 400 }); } const b = body as Record; const entry = { ts: new Date().toISOString(), type: String(b.type || "unknown").slice(0, 40), message: String(b.message || "").slice(0, 500), stack: typeof b.stack === "string" ? b.stack.slice(0, 4000) : undefined, url: typeof b.url === "string" ? b.url.slice(0, 500) : undefined, userAgent: req.headers.get("user-agent")?.slice(0, 200) || undefined, ip: req.headers.get("x-forwarded-for")?.split(",")[0].trim() || undefined, }; try { await ensureLog(); await appendFile(LOG_PATH, JSON.stringify(entry) + "\n", { encoding: "utf8" }); } catch { // Never fail the client on logging problems } return NextResponse.json({ ok: true }); }