Files
buzz-sheet/app/admin/actions.ts
T

72 lines
2.1 KiB
TypeScript

"use server";
import { z } from "zod";
import type { AutosaveResponse } from "@/lib/editor/autosave";
import { savePageDraft } from "@/lib/content/mutations";
import type { 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<typeof editorDraftSchema>;
export type EditorSaveResult = AutosaveResponse<PageSnapshot>;
export async function saveEditorPage(input: unknown): Promise<EditorSaveResult> {
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 : "บันทึกไม่สำเร็จ",
};
}
}