38 lines
2.4 KiB
TypeScript
38 lines
2.4 KiB
TypeScript
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); }
|
|
}
|