import type { ActionResult } from "./safe-action-shared"; export type ArticleSaveResult = ActionResult<{ redirectTo: string }>; export class ArticleInputError extends Error { constructor( public readonly code: | "titleRequired" | "titleTooLong" | "summaryTooLong" | "imageTooLong" | "invalidStatus" | "publishDateRequired", ) { super(code); } } export function readArticleInput(form: FormData) { const text = (key: string) => String(form.get(key) ?? "") .normalize("NFC") .trim(); const title = text("title"), shortStory = text("shortStory"), fullStory = text("fullStory"), image = text("image"); if (!title) throw new ArticleInputError("titleRequired"); if (title.length > 255) throw new ArticleInputError("titleTooLong"); if (shortStory.length > 255) throw new ArticleInputError("summaryTooLong"); if (image.length > 255) throw new ArticleInputError("imageTooLong"); const status = text("status") || "published"; if (status !== "published" && status !== "draft" && status !== "scheduled") throw new ArticleInputError("invalidStatus"); const publishAt = status === "scheduled" ? new Date(text("publishAt")) : null; if (publishAt && Number.isNaN(publishAt.getTime())) throw new ArticleInputError("publishDateRequired"); return { title, shortStory, fullStory, image, status, publishAt, rawSlug: text("slug"), }; } export function articleSlug(value: string | string[]): string { return Array.isArray(value) ? value.join("/") : value; }