import "server-only"; import { asc, eq } from "drizzle-orm"; import { getDb } from "@/db"; import { outboxEvents, catalogArtifacts, catalogCharacters, catalogWeapons, glossaryAliases, } from "@/db/schema"; import { glossaryAliasInputSchema, normalizeGlossaryAlias, } from "@/lib/glossary"; import { writeAuditLog, type AuditActor } from "@/lib/audit-log"; const catalogTables = { character: catalogCharacters, weapon: catalogWeapons, artifact: catalogArtifacts, } as const; export async function listGlossaryAliases() { return getDb().select().from(glossaryAliases).orderBy( asc(glossaryAliases.kind), asc(glossaryAliases.alias), ); } export async function createGlossaryAlias(input: unknown, actor: AuditActor) { const data = glossaryAliasInputSchema.parse(input); const table = catalogTables[data.kind]; return getDb().transaction(async (tx) => { const [item] = await tx .select({ key: table.key }) .from(table) .where(eq(table.key, data.catalogKey)) .limit(1); if (!item) throw new Error("ไม่พบรายการใน Catalog"); const [created] = await tx.insert(glossaryAliases).values({ ...data, alias: data.alias.trim(), normalizedAlias: normalizeGlossaryAlias(data.alias), }).returning(); await writeAuditLog(tx, actor, { action: "glossary_alias.created", targetType: "glossary_alias", targetId: created.id, metadata: { alias: created.alias, kind: created.kind, catalogKey: created.catalogKey, }, }); await tx.insert(outboxEvents).values({ topic: "admin", aggregateId: created.id, eventType: "glossary.updated", payload: { id: created.id, version: Date.now() }, }); return created; }); } export async function deleteGlossaryAlias(id: string, actor: AuditActor) { return getDb().transaction(async (tx) => { const [deleted] = await tx .delete(glossaryAliases) .where(eq(glossaryAliases.id, id)) .returning(); if (!deleted) throw new Error("ไม่พบ Shortcut"); await writeAuditLog(tx, actor, { action: "glossary_alias.deleted", targetType: "glossary_alias", targetId: deleted.id, metadata: { alias: deleted.alias, kind: deleted.kind, catalogKey: deleted.catalogKey, }, }); await tx.insert(outboxEvents).values({ topic: "admin", aggregateId: deleted.id, eventType: "glossary.updated", payload: { id: deleted.id, version: Date.now() }, }); return deleted; }); }