Spaces:
Paused
Paused
| import type { MessageFile } from "$lib/types/Message"; | |
| import { z } from "zod"; | |
| export interface FileProcessorOptions<TMimeType extends string = string> { | |
| supportedMimeTypes: TMimeType[]; | |
| maxSizeInMB: number; | |
| } | |
| export type ImageProcessor<TMimeType extends string = string> = (file: MessageFile) => Promise<{ | |
| file: Buffer; | |
| mime: TMimeType; | |
| }>; | |
| export const createDocumentProcessorOptionsValidator = <TMimeType extends string = string>( | |
| defaults: FileProcessorOptions<TMimeType> | |
| ) => { | |
| return z | |
| .object({ | |
| supportedMimeTypes: z | |
| .array( | |
| z.enum<string, [TMimeType, ...TMimeType[]]>([ | |
| defaults.supportedMimeTypes[0], | |
| ...defaults.supportedMimeTypes.slice(1), | |
| ]) | |
| ) | |
| .default(defaults.supportedMimeTypes), | |
| maxSizeInMB: z.number().positive().default(defaults.maxSizeInMB), | |
| }) | |
| .default(defaults); | |
| }; | |
| export type DocumentProcessor<TMimeType extends string = string> = (file: MessageFile) => { | |
| file: Buffer; | |
| mime: TMimeType; | |
| }; | |
| export type AsyncDocumentProcessor<TMimeType extends string = string> = ( | |
| file: MessageFile | |
| ) => Promise<{ | |
| file: Buffer; | |
| mime: TMimeType; | |
| }>; | |
| export function makeDocumentProcessor<TMimeType extends string = string>( | |
| options: FileProcessorOptions<TMimeType> | |
| ): AsyncDocumentProcessor<TMimeType> { | |
| return async (file) => { | |
| const { supportedMimeTypes, maxSizeInMB } = options; | |
| const { mime, value } = file; | |
| const buffer = Buffer.from(value, "base64"); | |
| const tooLargeInBytes = buffer.byteLength > maxSizeInMB * 1000 * 1000; | |
| if (tooLargeInBytes) { | |
| throw Error("Document is too large"); | |
| } | |
| const outputMime = validateMimeType(supportedMimeTypes, mime); | |
| return { file: buffer, mime: outputMime }; | |
| }; | |
| } | |
| const validateMimeType = <T extends readonly string[]>( | |
| supportedMimes: T, | |
| mime: string | |
| ): T[number] => { | |
| if (!supportedMimes.includes(mime)) { | |
| const supportedMimesStr = supportedMimes.join(", "); | |
| throw Error(`Mimetype "${mime}" not found in supported mimes: ${supportedMimesStr}`); | |
| } | |
| return mime; | |
| }; | |