Vectrum
Sign In
43 lines · 1.8 KB · TypeScript
"use server";

import { redirect } from "next/navigation";
import { GitError } from "@/lib/git";
import { deletePage, savePage, WikiError } from "@/lib/wiki";
import { pageHref } from "@/lib/wiki-links";
import { ActionError, repoForAction } from "./guard";
import type { FormState } from "./types";

const MAX_PAGE_BYTES = 1024 * 1024;

async function wikiForAction(owner: string, name: string) {
  const { repo, viewer } = await repoForAction(owner, name, "write");
  if (!repo.wikiEnabled) throw new ActionError("The wiki is turned off for this repository.");
  return { repo, author: { name: viewer.name || viewer.username, email: viewer.email } };
}

export async function saveWikiPageAction(owner: string, name: string, _prev: FormState, formData: FormData): Promise<FormState> {
  let destination: string;
  try {
    const { repo, author } = await wikiForAction(owner, name);
    const content = String(formData.get("content") ?? "");
    if (Buffer.byteLength(content) > MAX_PAGE_BYTES) throw new ActionError("Pages can be at most 1 MB.");
    const slug = await savePage(repo, author, {
      originalPath: String(formData.get("originalPath") ?? "") || null,
      title: String(formData.get("title") ?? ""),
      content,
      message: String(formData.get("message") ?? ""),
      baseSha: String(formData.get("baseSha") ?? "") || undefined,
    });
    destination = pageHref(`/${repo.owner}/${repo.name}/wiki`, slug);
  } catch (e) {
    if (e instanceof ActionError || e instanceof WikiError || e instanceof GitError) return { error: e.message };
    throw e;
  }
  redirect(destination);
}

export async function deleteWikiPageAction(owner: string, name: string, path: string) {
  const { repo, author } = await wikiForAction(owner, name);
  await deletePage(repo, author, String(path));
  redirect(`/${repo.owner}/${repo.name}/wiki`);
}