import path from "path"; import { MediaKind, MediaSource } from "@prisma/client"; import { createMediaAsset, getMediaAssetById } from "@/lib/media"; import { getExtensionForMimeType, removeManagedMediaFile, saveMediaUpload } from "@/lib/media-storage"; import type { MediaFieldInput } from "@/lib/media-validation"; function getFileNameFromUrl(url: string) { const pathname = new URL(url, "https://placeholder.local").pathname; const fileName = path.basename(pathname); return fileName && fileName !== "/" ? fileName : "external-file"; } export async function resolveMediaSelection(input: { media: MediaFieldInput | undefined; uploadFile: FormDataEntryValue | null; folder: string; fallbackLabel: string; required: boolean; }) { const media = input.media; if (!media) { if (input.required) { throw new Error("Media configuration is missing."); } return { assetId: null, url: "", uploadedUrl: null, }; } if (media.mode === "library") { const asset = media.assetId ? await getMediaAssetById(media.assetId) : null; if (!asset) { throw new Error("Selected media asset was not found."); } return { assetId: asset.id, url: asset.url, createdAssetId: null, uploadedUrl: null, }; } if (media.mode === "external") { if (!media.url) { if (input.required) { throw new Error("Media URL is required."); } return { assetId: null, url: "", uploadedUrl: null, }; } const asset = await createMediaAsset({ source: MediaSource.EXTERNAL, kind: media.kind, url: media.url, fileName: getFileNameFromUrl(media.url), label: media.label || input.fallbackLabel, altText: media.label || input.fallbackLabel, }); return { assetId: asset.id, url: asset.url, createdAssetId: asset.id, uploadedUrl: null, }; } const uploadFile = input.uploadFile; if (!(uploadFile instanceof File) || uploadFile.size === 0) { if (input.required) { throw new Error("Upload file is required."); } return { assetId: null, url: "", createdAssetId: null, uploadedUrl: null, }; } const savedFile = await saveMediaUpload(uploadFile, input.folder); if (!savedFile) { throw new Error("Unable to save upload."); } const asset = await createMediaAsset({ source: MediaSource.UPLOAD, kind: media.kind, url: savedFile.url, fileName: savedFile.fileName, label: media.label || input.fallbackLabel, altText: media.label || input.fallbackLabel, mimeType: savedFile.mimeType, size: savedFile.size, }); return { assetId: asset.id, url: asset.url, createdAssetId: asset.id, uploadedUrl: asset.url, }; } export async function createStandaloneMediaAsset(input: { kind: MediaKind; label: string; uploadFile: FormDataEntryValue | null; }) { if (input.uploadFile instanceof File && input.uploadFile.size > 0) { const savedFile = await saveMediaUpload(input.uploadFile, input.kind.toLowerCase()); const derivedLabel = input.uploadFile.name.replace(/\.[^.]+$/, "").trim(); const trimmedLabel = input.label.trim() || derivedLabel || "Media asset"; if (!savedFile) { throw new Error("Unable to save upload."); } return createMediaAsset({ source: MediaSource.UPLOAD, kind: input.kind, url: savedFile.url, fileName: savedFile.fileName, label: trimmedLabel, altText: trimmedLabel, mimeType: savedFile.mimeType, size: savedFile.size, }); } throw new Error("Upload file is required."); } export async function deleteMediaAssetAndFile(input: { assetId: string; assetUrl: string; }) { await removeManagedMediaFile(input.assetUrl); } export function inferMediaKindFromMimeType(mimeType: string | null | undefined): MediaKind { return mimeType?.startsWith("image/") || mimeType === "image/svg+xml" ? MediaKind.IMAGE : MediaKind.DOCUMENT; } export function inferMediaKindFromFileName(fileName: string): MediaKind { const extension = path.extname(fileName).toLowerCase(); if ([".jpg", ".jpeg", ".png", ".webp", ".svg"].includes(extension)) { return MediaKind.IMAGE; } return MediaKind.DOCUMENT; } export function getKindFromUploadFile(file: File) { const extension = getExtensionForMimeType(file.type); if (extension && [".jpg", ".jpeg", ".png", ".webp", ".svg"].includes(extension)) { return MediaKind.IMAGE; } return MediaKind.DOCUMENT; }