SPB Git
1.4 KB · 19 lines typescript
1import { z } from "zod";2import { handler, parseBody, uuid, HttpError } from "@/lib/api";3import { importBibtex } from "@/lib/research/references";4import { audit } from "@/lib/audit";5export const maxDuration = 120;6/** POST multipart (file=.bib, pageId) or JSON { text, pageId } */7export const POST = handler(async ({ req, ws, user }) => {8  let text = ""; let pageId: string | null = null;9  if ((req.headers.get("content-type") ?? "").includes("multipart/form-data")) {10    const form = await req.formData(); const f = form.get("file"); const t = form.get("text"); pageId = (form.get("pageId") as string) || null;11    if (f instanceof File) { if (f.size > 20 * 1024 * 1024) throw new HttpError(413, "BibTeX file too large (max 20 MB)"); text = await f.text(); } else if (typeof t === "string") text = t;12  } else { const b = await parseBody(req, z.object({ text: z.string().min(1).max(20_000_000), pageId: uuid.nullable().optional() })); text = b.text; pageId = b.pageId ?? null; }13  if (!text.trim()) throw new HttpError(400, "No BibTeX content");14  if (pageId && !/^[0-9a-f-]{36}$/.test(pageId)) throw new HttpError(400, "Invalid pageId");15  const res = await importBibtex(ws.id, text, pageId);16  await audit(user.id, "reference.import", { type: "page", id: pageId ?? "library" }, { created: res.created.length, skipped: res.skipped.length });17  return Response.json({ created: res.created, skipped: res.skipped, parsed: res.parsed });18});19
Files · 2c37cb5a3e2af18e5ba361996d453cab97da82c2
Menu

Theme