46 lines
1.5 KiB
TypeScript
46 lines
1.5 KiB
TypeScript
import { NextResponse } from "next/server";
|
|
import { recordAppLog } from "@/lib/server/log-manager";
|
|
|
|
export function jsonOk<T>(payload: T, init?: ResponseInit) {
|
|
return NextResponse.json(payload, init);
|
|
}
|
|
|
|
export type JsonErrorOptions = {
|
|
request?: Request;
|
|
source?: string;
|
|
details?: unknown;
|
|
logClientErrors?: boolean;
|
|
};
|
|
|
|
export async function jsonError(error: unknown, status = 400, options: JsonErrorOptions = {}) {
|
|
const resolvedStatus = statusFromError(error) || status;
|
|
if (resolvedStatus >= 500 || options.logClientErrors) {
|
|
await recordAppLog({
|
|
level: resolvedStatus >= 500 ? "error" : "warning",
|
|
source: options.source || "api",
|
|
message: error instanceof Error ? error.message : String(error),
|
|
error,
|
|
status: resolvedStatus,
|
|
request: options.request,
|
|
details: options.details
|
|
}).catch(() => undefined);
|
|
}
|
|
return NextResponse.json({
|
|
error: error instanceof Error ? error.message : String(error)
|
|
}, { status: resolvedStatus });
|
|
}
|
|
|
|
export async function readJsonBody<T extends Record<string, unknown>>(request: Request): Promise<T> {
|
|
try {
|
|
return await request.json() as T;
|
|
} catch {
|
|
return {} as T;
|
|
}
|
|
}
|
|
|
|
function statusFromError(error: unknown): number | undefined {
|
|
if (typeof error !== "object" || error === null || !("status" in error)) return undefined;
|
|
const status = Number((error as { status?: unknown }).status);
|
|
return Number.isInteger(status) && status >= 400 && status <= 599 ? status : undefined;
|
|
}
|