"use server"; import { revalidatePath } from "next/cache"; import path from "node:path"; import fs from "node:fs/promises"; import { rawDb } from "@/lib/db/client"; import { safeJoin } from "@/lib/safePath"; export type CollectionCoverSlot = "portrait" | "landscape"; const COVER_ROOT = path.join(process.cwd(), "data", "collection-covers"); const SLOT_COLS: Record = { portrait: { path: "cover_portrait_path", zoom: "cover_portrait_zoom", ox: "cover_portrait_offset_x", oy: "cover_portrait_offset_y" }, landscape: { path: "cover_landscape_path", zoom: "cover_landscape_zoom", ox: "cover_landscape_offset_x", oy: "cover_landscape_offset_y" }, }; export async function setCollectionCoverTransform( collectionId: number, slot: CollectionCoverSlot, transform: { zoom: number; offsetX: number; offsetY: number }, ) { const c = SLOT_COLS[slot]; if (!c) return; const zoom = Math.max(0.5, Math.min(5, transform.zoom)); rawDb.prepare(` UPDATE collections SET ${c.zoom} = ?, ${c.ox} = ?, ${c.oy} = ? WHERE id = ? `).run(zoom, transform.offsetX, transform.offsetY, collectionId); const row = rawDb.prepare(`SELECT slug FROM collections WHERE id = ?`).get(collectionId) as { slug: string } | undefined; revalidatePath("/collection"); if (row) revalidatePath(`/collection/${row.slug}`); } export async function clearCollectionCover(collectionId: number, slot: CollectionCoverSlot) { const c = SLOT_COLS[slot]; if (!c) return; const row = rawDb.prepare(`SELECT slug, ${c.path} AS p FROM collections WHERE id = ?`).get(collectionId) as | { slug: string; p: string | null } | undefined; if (!row) return; if (row.p) { const abs = safeJoin(COVER_ROOT, row.p); if (abs) await fs.rm(abs, { force: true }).catch(() => {}); } rawDb.prepare(` UPDATE collections SET ${c.path} = NULL, ${c.zoom} = 1, ${c.ox} = 0, ${c.oy} = 0 WHERE id = ? `).run(collectionId); revalidatePath("/collection"); revalidatePath(`/collection/${row.slug}`); }