import { storeUploadLocally } from "@/lib/media/local-storage" import { storeUploadToS3 } from "@/lib/media/s3-storage" export type MediaStorageProvider = "local" | "s3" type StoreUploadParams = { file: File assetId: string variant: string fileRole: string } type StoredUpload = { storageKey: string provider: MediaStorageProvider fallbackReason?: string } type S3LikeError = { name?: unknown message?: unknown Code?: unknown code?: unknown $metadata?: { httpStatusCode?: unknown requestId?: unknown } } function resolveTenantId(): string { return process.env.CMS_MEDIA_STORAGE_TENANT_ID?.trim() || "default" } function describeS3Error(error: unknown): string { if (!error || typeof error !== "object") { return "Unknown S3 error" } const err = error as S3LikeError const details: string[] = [] if (typeof err.name === "string" && err.name.length > 0) { details.push(`name=${err.name}`) } if (typeof err.message === "string" && err.message.length > 0) { details.push(`message=${err.message}`) } if (typeof err.Code === "string" && err.Code.length > 0) { details.push(`code=${err.Code}`) } else if (typeof err.code === "string" && err.code.length > 0) { details.push(`code=${err.code}`) } const status = err.$metadata?.httpStatusCode if (typeof status === "number") { details.push(`status=${status}`) } const requestId = err.$metadata?.requestId if (typeof requestId === "string" && requestId.length > 0) { details.push(`requestId=${requestId}`) } return details.length > 0 ? details.join(", ") : "Unknown S3 error" } export function resolveMediaStorageProvider(raw: string | undefined): MediaStorageProvider { if (raw?.toLowerCase() === "local") { return "local" } return "s3" } export async function storeUpload(params: StoreUploadParams): Promise { const provider = resolveMediaStorageProvider(process.env.CMS_MEDIA_STORAGE_PROVIDER) const tenantId = resolveTenantId() if (provider === "s3") { try { const stored = await storeUploadToS3({ file: params.file, tenantId, assetId: params.assetId, fileRole: params.fileRole, variant: params.variant, }) return { ...stored, provider, } } catch (error) { const detail = describeS3Error(error) const fallbackStored = await storeUploadLocally({ file: params.file, tenantId, assetId: params.assetId, fileRole: params.fileRole, variant: params.variant, }) return { ...fallbackStored, provider: "local", fallbackReason: `S3 upload failed; file stored locally instead. ${detail}`, } } } const stored = await storeUploadLocally({ file: params.file, tenantId, assetId: params.assetId, fileRole: params.fileRole, variant: params.variant, }) return { ...stored, provider, } }