"use server"; import * as z from "zod"; import type { AutosaveResponse } from "@/lib/editor/autosave"; import { createNamedRevision, saveDataSourceVersion, savePageDraft, } from "@/lib/content/mutations"; import { dataSourceSnapshotSchema } from "@/lib/content/data-source"; import type { DataSourceSnapshot, PageSnapshot } from "@/lib/content/types"; import { requireAdmin } from "@/lib/auth/server"; const serializedBlockSchema = z.strictObject({ id: z.string().uuid(), type: z.string().min(1).max(64), schemaVersion: z.number().int().nonnegative(), config: z.unknown(), responsiveLayout: z.unknown().optional(), sortOrder: z.number().int().nonnegative(), }); const editorDraftSchema = z.strictObject({ pageId: z.string().uuid(), expectedVersion: z.number().int().positive(), title: z.string().max(300), slug: z.string().max(120), visible: z.boolean(), publicNote: z.string().max(10_000).nullable().optional(), blocks: z.array(serializedBlockSchema).max(500), }); export type EditorSaveInput = z.input; export type EditorSaveResult = AutosaveResponse; export async function saveEditorPage(input: unknown): Promise { const admin = await requireAdmin(); const parsed = editorDraftSchema.safeParse(input); if (!parsed.success) { return { status: "validation-error", issues: parsed.error.issues.map((issue) => issue.message), }; } if (process.env.BUZZ_DEMO_MODE === "true") { return { status: "saved", version: parsed.data.expectedVersion + 1 }; } try { const result = await savePageDraft({ ...parsed.data, authorId: admin.user.id, }); if (result.status === "accepted") { return { status: "saved", version: result.value.page.version, snapshot: result.value, }; } if (result.status === "not-found") { return { status: "validation-error", issues: ["ไม่พบหน้าที่ต้องการบันทึก"], }; } return result; } catch (cause) { return { status: "transient-error", message: cause instanceof Error ? cause.message : "บันทึกไม่สำเร็จ", }; } } export async function saveEditorDataSource( input: unknown, ): Promise> { const admin = await requireAdmin(); const parsed = dataSourceSnapshotSchema.safeParse(input); if (!parsed.success) { return { status: "validation-error", issues: parsed.error.issues.map((issue) => issue.message), }; } if (process.env.BUZZ_DEMO_MODE === "true") { return { status: "saved", version: parsed.data.version + 1, snapshot: { ...parsed.data, version: parsed.data.version + 1 }, }; } try { const result = await saveDataSourceVersion({ ...parsed.data, expectedVersion: parsed.data.version, authorId: admin.user.id, }); if (result.status === "accepted") { return { status: "saved", version: result.value.version, snapshot: result.value, }; } if (result.status === "not-found") { return { status: "validation-error", issues: ["ไม่พบแหล่งข้อมูล"] }; } return result; } catch (cause) { return { status: "transient-error", message: cause instanceof Error ? cause.message : "บันทึกข้อมูลไม่สำเร็จ", }; } } export async function createEditorRevision( pageId: string, label: string, ): Promise<{ status: "saved"; id: string } | { status: "error" }> { const admin = await requireAdmin(); const parsed = z.string().uuid().safeParse(pageId); const safeLabel = z.string().trim().min(1).max(160).safeParse(label); if (!parsed.success || !safeLabel.success) return { status: "error" }; if (process.env.BUZZ_DEMO_MODE === "true") { return { status: "saved", id: crypto.randomUUID() }; } const id = await createNamedRevision(parsed.data, safeLabel.data, admin.user.id); return id ? { status: "saved", id } : { status: "error" }; }