import type { NextApiRequest, NextApiResponse } from "next"; import { DocumentValidationError, readDocumentSections, editDocumentSections } from "@/lib/docs"; import { outline } from "@/lib/document-sections"; import { authorizeDocuments, documentApiError, idempotency } from "@/lib/documents-api"; export const config = { api: { bodyParser: { sizeLimit: "8mb" } } }; export default function handler(request: NextApiRequest, response: NextApiResponse) { try { const key = authorizeDocuments(request, response, request.method === "POST"); if (!key) return; if (request.method !== "GET" && request.method !== "POST") { response.setHeader("Allow", "GET, POST"); return response.status(405).end(); } if (!Array.isArray(request.query.slug)) throw new DocumentValidationError("Invalid document slug"); const slug = request.query.slug.join("/"); if (Object.keys(request.query).some((k) => !["slug", "section", "revision"].includes(k))) throw new DocumentValidationError("Unknown section query"); if (request.method === "POST") { if (request.query.section !== undefined || request.query.revision !== undefined) throw new DocumentValidationError("POST uses revision and operations in the body"); const saved = editDocumentSections(slug, request.body, idempotency(request, key.id)); return saved ? response.status(200).json(saved) : response.status(404).json({ code: "not_found" }); } const revision = request.query.revision; if (revision !== undefined && (typeof revision !== "string" || !/^[1-9]\d*$/.test(revision))) throw new DocumentValidationError("Invalid revision"); const doc = readDocumentSections(slug, revision === undefined ? undefined : Number(revision)); if (!doc) return response.status(404).json({ code: "not_found" }); const selected = request.query.section; if (selected === undefined) return response.status(200).json({ ...doc, sections: outline(doc.sections) }); const ids = typeof selected === "string" ? [selected] : selected; if (!ids.length || ids.length > 100 || ids.some((id) => !id)) throw new DocumentValidationError("Select 1 to 100 sections"); if (ids.some((id) => !doc.sections.some((s) => s.id === id))) return response.status(404).json({ code: "not_found" }); return response.status(200).json({ ...doc, sections: doc.sections.filter((s) => ids.includes(s.id)) }); } catch (error) { return documentApiError(response, error); } }