SPB Git

Repository Public

route.ts 1.6 KB 46 lines typescript

1// Auteur : Simon-Pierre Boucher — contact@spboucher.ai2/**3 * POST /api/stats/report/custom — v3 : rapport PDF personnalisé4 * (src/ka/stats/SPEC.md §3bis). Corps : {"title", "period", "from", "to",5 * "blocks": [{"key": "series:…", "render": "bar"}, …]} — ordre respecté,6 * clés inconnues ignorées, aucune clé valide → 400. Généré LOCALEMENT7 * depuis l'EcoPayload consolidé (le rapport écosystème v2 à 5 modes reste,8 * lui, proxifié vers API-KA via /api/stats/ecosystem-report).9 */10import { type NextRequest, NextResponse } from "next/server";11import {12  buildCustomReport,13  customReportFilename,14  getReportPayload,15  type CustomSpec,16} from "@/lib/report-stats";17import { isPeriod } from "@/lib/ecostats";1819export const dynamic = "force-dynamic";2021export async function POST(req: NextRequest) {22  let spec: CustomSpec;23  try {24    spec = (await req.json()) as CustomSpec;25  } catch {26    return NextResponse.json({ error: "Corps JSON invalide" }, { status: 400 });27  }28  const period = isPeriod(spec?.period) ? spec.period : "30j";29  const payload = await getReportPayload(period);30  try {31    const pdf = await buildCustomReport(spec ?? {}, payload);32    return new NextResponse(new Uint8Array(pdf), {33      headers: {34        "Content-Type": "application/pdf",35        "Content-Disposition": `attachment; filename="${customReportFilename(period)}"`,36        "Cache-Control": "no-store",37      },38    });39  } catch (e) {40    if (e instanceof Error && e.message === "aucun-bloc") {41      return NextResponse.json({ error: "Aucun bloc valide dans la composition" }, { status: 400 });42    }43    throw e;44  }45}46
Files main
Menu

Theme