diff --git a/backend/src/utils/preview.ts b/backend/src/utils/preview.ts new file mode 100644 index 0000000..5c4c993 --- /dev/null +++ b/backend/src/utils/preview.ts @@ -0,0 +1,59 @@ +import { env } from '../config/env.js'; +import type { FileRecord } from '../types.js'; + +export type PreviewKind = 'image' | 'video' | 'audio' | 'pdf' | 'text'; + +const TEXT_MIME_TYPES = new Set([ + 'application/json', + 'application/x-ndjson', + 'text/csv', + 'text/markdown', + 'text/plain', +]); + +const IMAGE_MIME_TYPES = new Set([ + 'image/avif', + 'image/bmp', + 'image/gif', + 'image/jpeg', + 'image/png', + 'image/webp', +]); + +const VIDEO_MIME_TYPES = new Set([ + 'video/mp4', + 'video/ogg', + 'video/webm', +]); + +const AUDIO_MIME_TYPES = new Set([ + 'audio/aac', + 'audio/flac', + 'audio/mpeg', + 'audio/mp4', + 'audio/ogg', + 'audio/wav', + 'audio/webm', +]); + +export function getPreviewKind(mimeType: string): PreviewKind | null { + const normalized = mimeType.toLowerCase().split(';')[0].trim(); + if (IMAGE_MIME_TYPES.has(normalized)) return 'image'; + if (VIDEO_MIME_TYPES.has(normalized)) return 'video'; + if (AUDIO_MIME_TYPES.has(normalized)) return 'audio'; + if (normalized === 'application/pdf') return 'pdf'; + if (TEXT_MIME_TYPES.has(normalized)) return 'text'; + return null; +} + +export function getPreviewMeta(file: FileRecord) { + const kind = getPreviewKind(file.mimeType); + const available = Boolean(kind) && file.sizeBytes <= env.previewMaxFileSizeBytes; + + return { + available, + kind: available ? kind : null, + maxSize: env.previewMaxFileSizeBytes, + }; +} +