Skip to article
Documentation

src/app/api/documents/route.ts

Linked repository file from this build.

import { NextResponse } from "next/server";
import { z } from "zod";
import { apiRoute } from "@/lib/api-route";
import { getActor } from "@/lib/auth/server";
import { AccessError, can } from "@/lib/auth/scope";
import {
  DocumentError,
  documentKeySchema,
  documentStorage,
  putLocalDocument,
  uploadOwner,
  uploadRequestSchema,
} from "@/lib/documents/server-storage";
export const runtime = "nodejs";

export const POST = apiRoute(
  "Unable to save PDF. Check the file and try again.",
  async (request) => {
    const actor = await getActor(request);
    if (!can(actor, "uploadDocuments")) throw new AccessError("This role cannot upload documents.");
    const storage = documentStorage();
    if (request.headers.get("content-type")?.startsWith("application/json")) {
      const input: unknown = await request.json();
      if (storage.mode === "local") return NextResponse.json({ mode: "local" });
      const owner = uploadOwner(actor.program, actor.staffId);
      const completion = z.object({ uploadId: documentKeySchema }).safeParse(input);
      if (completion.success)
        return NextResponse.json({ key: await storage.complete(completion.data.uploadId, owner) });
      const parsed = uploadRequestSchema.safeParse(input);
      if (!parsed.success) throw new DocumentError("Select a PDF file, 10 MB or smaller.");
      return NextResponse.json({ mode: "neon", ...(await storage.prepare(parsed.data, owner)) });
    }
    if (storage.mode !== "local") throw new DocumentError("Start a direct document upload first.");
    const file = (await request.formData()).get("file");
    if (!(file instanceof File)) throw new DocumentError("Select a PDF file.");
    return NextResponse.json({
      key: await putLocalDocument(file, uploadOwner(actor.program, actor.staffId)),
    });
  },
);