diff --git a/src/app/api/health/route.ts b/src/app/api/health/route.ts new file mode 100644 index 0000000..c02bbcb --- /dev/null +++ b/src/app/api/health/route.ts @@ -0,0 +1,34 @@ +import { NextResponse } from "next/server"; +import { prisma } from "@/lib/db"; +import pkg from "../../../../package.json"; + +export const dynamic = "force-dynamic"; + +/** + * Healthcheck für Reverse-Proxy und Uptime-Monitoring. + * Prüft die Datenbankverbindung mit — eine App ohne DB ist nicht gesund. + */ +export async function GET() { + const startedAt = Date.now(); + try { + await prisma.$queryRaw`SELECT 1`; + return NextResponse.json({ + status: "ok", + version: pkg.version, + database: "ok", + latencyMs: Date.now() - startedAt, + timestamp: new Date().toISOString(), + }); + } catch (error) { + return NextResponse.json( + { + status: "error", + version: pkg.version, + database: "unreachable", + message: error instanceof Error ? error.message : "unbekannter Fehler", + timestamp: new Date().toISOString(), + }, + { status: 503 }, + ); + } +} diff --git a/tsconfig.json b/tsconfig.json index 6d1b48c..67e276f 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,7 +1,11 @@ { "compilerOptions": { "target": "ES2022", - "lib": ["dom", "dom.iterable", "esnext"], + "lib": [ + "dom", + "dom.iterable", + "esnext" + ], "allowJs": true, "skipLibCheck": true, "strict": true, @@ -11,14 +15,28 @@ "moduleResolution": "bundler", "resolveJsonModule": true, "isolatedModules": true, - "jsx": "preserve", + "jsx": "react-jsx", "incremental": true, "noUncheckedIndexedAccess": true, - "plugins": [{ "name": "next" }], + "plugins": [ + { + "name": "next" + } + ], "paths": { - "@/*": ["./src/*"] + "@/*": [ + "./src/*" + ] } }, - "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], - "exclude": ["node_modules"] + "include": [ + "next-env.d.ts", + "**/*.ts", + "**/*.tsx", + ".next/types/**/*.ts", + ".next/dev/types/**/*.ts" + ], + "exclude": [ + "node_modules" + ] }