Files
MOH 0a5f77d8de REFACTORED - migrate the data layer from Prisma to Drizzle (unify the stack)
- Add lib/db (Drizzle schema: 7 tables + 6 enums + relations, postgres.js client),
  drizzle.config.ts, lib/db/enums.ts (Prisma-compatible enum objects)
- Rewrite all 14 app consumers + 4 admin components to Drizzle
- Move the test DB layer to Drizzle + in-process PGlite; convert all 8 integration
  test files + factories (371 tests green)
- Remove Prisma: deps, prisma/ schema+migrations, lib/prisma.ts, Dockerfile prisma
  generate; wire db:generate/migrate/push/studio to drizzle-kit; update Makefile
- Preserve the old seed as scripts/legacy-prisma-seed.cjs (needs a Drizzle rewrite)
2026-08-07 14:18:41 +02:00

97 lines
3.0 KiB
TypeScript

"use server";
import { MediaKind } from "@/lib/db/enums";
import { revalidatePath } from "next/cache";
import { redirect } from "next/navigation";
import { isRedirectError } from "next/dist/client/components/redirect-error";
import { getAdminAppPath, toInternalAdminPath } from "@/lib/admin-routing";
import { clearAdminSessionCookie, isAdminAuthenticated } from "@/lib/admin-auth";
import { withFlash } from "@/lib/admin-feedback";
import { countMediaUsageReferences, getMediaAssetById } from "@/lib/media";
import { createStandaloneMediaAsset, deleteMediaAssetAndFile } from "@/lib/media-service";
import { isManagedMediaFilePath } from "@/lib/media-storage";
import { eq } from "drizzle-orm";
import { db } from "@/lib/db";
import { mediaAsset } from "@/lib/db/schema";
async function ensureAdmin() {
if (!(await isAdminAuthenticated())) {
await clearAdminSessionCookie();
redirect(getAdminAppPath("/"));
}
}
function revalidateMediaPages() {
revalidatePath(toInternalAdminPath("/"));
revalidatePath(toInternalAdminPath("/media"));
revalidatePath(toInternalAdminPath("/portfolio"));
revalidatePath(toInternalAdminPath("/portfolio/projects"));
}
export async function createMediaAssetAction(formData: FormData) {
await ensureAdmin();
try {
const kindValue = String(formData.get("kind") ?? "IMAGE");
const kind = kindValue === "DOCUMENT" ? MediaKind.DOCUMENT : MediaKind.IMAGE;
await createStandaloneMediaAsset({
kind,
label: String(formData.get("label") ?? ""),
uploadFile: formData.get("file"),
});
revalidateMediaPages();
redirect(withFlash(getAdminAppPath("/media"), { success: "Datei gespeichert." }));
} catch (error) {
if (isRedirectError(error)) {
throw error;
}
const message = error instanceof Error ? error.message : "Datei konnte nicht gespeichert werden.";
redirect(withFlash(getAdminAppPath("/media"), { error: message }));
}
}
export async function deleteMediaAssetAction(formData: FormData) {
await ensureAdmin();
const assetId = String(formData.get("assetId") ?? "");
try {
const asset = await getMediaAssetById(assetId);
if (!asset) {
redirect(withFlash(getAdminAppPath("/media"), { error: "Datei nicht gefunden." }));
}
const usageCount = await countMediaUsageReferences(asset.id);
if (usageCount > 0) {
redirect(withFlash(getAdminAppPath("/media"), { error: "Datei wird noch verwendet." }));
}
await db.delete(mediaAsset).where(eq(mediaAsset.id, asset.id));
if (isManagedMediaFilePath(asset.url)) {
await deleteMediaAssetAndFile({
assetId: asset.id,
assetUrl: asset.url,
});
}
revalidateMediaPages();
redirect(withFlash(getAdminAppPath("/media"), { success: "Datei geloescht." }));
} catch (error) {
if (isRedirectError(error)) {
throw error;
}
const message = error instanceof Error ? error.message : "Datei konnte nicht geloescht werden.";
redirect(withFlash(getAdminAppPath("/media"), { error: message }));
}
}