feat(templates): persist independent guide applications

This commit is contained in:
2026-08-28 19:41:08 +00:00 Unverified
parent 2ddbd374ae
commit 35a786156a
4 changed files with 331 additions and 0 deletions
+56
View File
@@ -9,8 +9,11 @@ import {
savePageDraft,
} from "@/lib/content/mutations";
import { dataSourceSnapshotSchema } from "@/lib/content/data-source";
import { slugSchema } from "@/lib/content/lifecycle";
import type { DataSourceSnapshot, PageSnapshot } from "@/lib/content/types";
import { requireAdmin } from "@/lib/auth/server";
import { builtInTemplates } from "@/lib/templates";
import { persistTemplateApplication } from "@/lib/templates/persist";
const serializedBlockSchema = z.strictObject({
id: z.string().uuid(),
@@ -132,3 +135,56 @@ export async function createEditorRevision(
const id = await createNamedRevision(parsed.data, safeLabel.data, admin.user.id);
return id ? { status: "saved", id } : { status: "error" };
}
const templateApplicationSchema = z.strictObject({
templateSlug: z.string().min(1).max(120),
characterSlug: slugSchema,
nameTh: z.string().trim().min(1).max(160),
nameEn: z.string().trim().max(160).optional(),
description: z.string().trim().max(2_000).optional(),
});
export async function applyEditorTemplate(input: unknown): Promise<
| { status: "created"; location: string }
| { status: "validation-error"; issues: string[] }
| { status: "error"; message: string }
> {
const admin = await requireAdmin();
const parsed = templateApplicationSchema.safeParse(input);
if (!parsed.success) {
return {
status: "validation-error",
issues: parsed.error.issues.map((issue) => issue.message),
};
}
const template = builtInTemplates.find(
(candidate) => candidate.slug === parsed.data.templateSlug,
);
if (!template) {
return { status: "validation-error", issues: ["ไม่พบเทมเพลต"] };
}
if (process.env.BUZZ_DEMO_MODE === "true") {
return { status: "created", location: "/admin/astra/info" };
}
try {
const applied = await persistTemplateApplication(
template,
{
slug: parsed.data.characterSlug,
nameTh: parsed.data.nameTh,
nameEn: parsed.data.nameEn,
description: parsed.data.description,
},
admin.user.id,
);
return {
status: "created",
location: `/admin/${applied.characterSlug}/${applied.firstPageSlug}`,
};
} catch (cause) {
return {
status: "error",
message: cause instanceof Error ? cause.message : "สร้างคู่มือไม่สำเร็จ",
};
}
}