import path from "node:path" const FALLBACK_EXTENSION = "bin" const DEFAULT_VARIANT = "original" type BuildMediaStorageKeyParams = { tenantId: string assetId: string fileRole: string variant?: string fileName: string } function normalizeSegment(value: string): string { return value .toLowerCase() .replace(/[^a-z0-9._-]+/g, "-") .replace(/^-+|-+$/g, "") } function extensionFromFilename(fileName: string): string { const extension = path.extname(fileName).slice(1) if (!extension) { return FALLBACK_EXTENSION } const normalized = normalizeSegment(extension) return normalized.length > 0 ? normalized : FALLBACK_EXTENSION } export function buildMediaStorageKey(params: BuildMediaStorageKeyParams): string { const normalizedTenantId = normalizeSegment(params.tenantId) || "default" const normalizedAssetId = normalizeSegment(params.assetId) const normalizedFileRole = normalizeSegment(params.fileRole) || "original" const normalizedVariant = normalizeSegment(params.variant ?? DEFAULT_VARIANT) || DEFAULT_VARIANT const extension = extensionFromFilename(params.fileName) const fileName = `${normalizedAssetId}__${normalizedVariant}.${extension}` return [ "tenant", normalizedTenantId, "asset", normalizedAssetId, normalizedFileRole, fileName, ].join("/") }