refactor(media): use asset-centric storage key layout

This commit is contained in:
2026-02-12 18:41:01 +01:00
parent 86a8af25d8
commit 3e4f0b6c75
12 changed files with 218 additions and 27 deletions

View File

@@ -1,3 +1,4 @@
import { randomUUID } from "node:crypto"
import { hasPermission } from "@cms/content/rbac"
import { createMediaAsset } from "@cms/db"
@@ -57,6 +58,20 @@ function parseTags(formData: FormData): string[] {
.filter((item) => item.length > 0)
}
function deriveTitleFromFilename(fileName: string): string {
const trimmed = fileName.trim()
if (!trimmed) {
return "Untitled media"
}
const dotIndex = trimmed.lastIndexOf(".")
const base = dotIndex > 0 ? trimmed.slice(0, dotIndex) : trimmed
const normalized = base.trim()
return normalized.length > 0 ? normalized : "Untitled media"
}
function isMimeAllowed(mediaType: string, mimeType: string): boolean {
const rule = ALLOWED_MIME_BY_TYPE[mediaType]
@@ -116,14 +131,9 @@ export async function POST(request: Request): Promise<Response> {
return badRequest("Invalid form payload.")
}
const title = parseTextField(formData, "title")
const type = parseTextField(formData, "type")
const fileEntry = formData.get("file")
if (!title) {
return badRequest("Title is required.")
}
if (!type) {
return badRequest("Type is required.")
}
@@ -146,13 +156,21 @@ export async function POST(request: Request): Promise<Response> {
return badRequest(`File type ${fileEntry.type || "unknown"} is not allowed for ${type}.`)
}
const title = parseTextField(formData, "title") || deriveTitleFromFilename(fileEntry.name)
const mediaAssetId = randomUUID()
const variant = "original"
const fileRole = "original"
try {
const stored = await storeUpload({
file: fileEntry,
mediaType: type,
assetId: mediaAssetId,
variant,
fileRole,
})
const created = await createMediaAsset({
id: mediaAssetId,
title,
type,
description: parseOptionalField(formData, "description"),
@@ -171,6 +189,7 @@ export async function POST(request: Request): Promise<Response> {
{
id: created.id,
provider: stored.provider,
warning: stored.fallbackReason,
notice: "Media uploaded successfully.",
},
{ status: 201 },