// File: route.ts // Path: apps/web/app/api/v1/occupations/route.ts // Project: AI Risk Index — airiskindex.io // Author: Simon-Pierre Boucher // Contact: contact@spboucher.ai // Copyright © 2026 Simon-Pierre Boucher. All rights reserved. // // Description: Public API: occupation list/search (paginated). import { prisma } from "@airiskindex/db"; import { INDEX_VERSION } from "@airiskindex/scoring"; import type { NextRequest } from "next/server"; export const dynamic = "force-dynamic"; export async function GET(request: NextRequest): Promise { const { searchParams } = new URL(request.url); const q = searchParams.get("q") ?? undefined; const page = Math.max(1, Number(searchParams.get("page") ?? "1") || 1); const perPage = Math.min(100, Math.max(1, Number(searchParams.get("per_page") ?? "25") || 25)); const where = q ? { OR: [ { title: { contains: q, mode: "insensitive" as const } }, { code: { startsWith: q } }, ], } : {}; try { const [total, items] = await Promise.all([ prisma.occupation.count({ where }), prisma.occupation.findMany({ where, orderBy: { code: "asc" }, skip: (page - 1) * perPage, take: perPage, select: { code: true, title: true }, }), ]); return Response.json( { index_version: INDEX_VERSION, page, per_page: perPage, total, items }, { headers: { "Cache-Control": "public, s-maxage=3600, stale-while-revalidate=600" } }, ); } catch { return Response.json({ error: "database_unavailable" }, { status: 503 }); } }