Spaces:
Paused
Paused
| /** | |
| * Shared attachment content-type configuration. | |
| * | |
| * By default only image types are allowed. Set the | |
| * `PAPERCLIP_ALLOWED_ATTACHMENT_TYPES` environment variable to a | |
| * comma-separated list of MIME types or wildcard patterns to expand the | |
| * allowed set. | |
| * | |
| * Examples: | |
| * PAPERCLIP_ALLOWED_ATTACHMENT_TYPES=image/*,application/pdf | |
| * PAPERCLIP_ALLOWED_ATTACHMENT_TYPES=image/*,application/pdf,text/* | |
| * | |
| * Supported pattern syntax: | |
| * - Exact types: "application/pdf" | |
| * - Wildcards: "image/*" or "application/vnd.openxmlformats-officedocument.*" | |
| */ | |
| export const DEFAULT_ALLOWED_TYPES: readonly string[] = [ | |
| "image/png", | |
| "image/jpeg", | |
| "image/jpg", | |
| "image/webp", | |
| "image/gif", | |
| "application/pdf", | |
| "text/markdown", | |
| "text/plain", | |
| "application/json", | |
| "text/csv", | |
| "text/html", | |
| ]; | |
| /** | |
| * Parse a comma-separated list of MIME type patterns into a normalised array. | |
| * Returns the default image-only list when the input is empty or undefined. | |
| */ | |
| export function parseAllowedTypes(raw: string | undefined): string[] { | |
| if (!raw) return [...DEFAULT_ALLOWED_TYPES]; | |
| const parsed = raw | |
| .split(",") | |
| .map((s) => s.trim().toLowerCase()) | |
| .filter((s) => s.length > 0); | |
| return parsed.length > 0 ? parsed : [...DEFAULT_ALLOWED_TYPES]; | |
| } | |
| /** | |
| * Check whether `contentType` matches any entry in `allowedPatterns`. | |
| * | |
| * Supports exact matches ("application/pdf") and wildcard / prefix | |
| * patterns ("image/*", "application/vnd.openxmlformats-officedocument.*"). | |
| */ | |
| export function matchesContentType(contentType: string, allowedPatterns: string[]): boolean { | |
| const ct = contentType.toLowerCase(); | |
| return allowedPatterns.some((pattern) => { | |
| if (pattern === "*") return true; | |
| if (pattern.endsWith("/*") || pattern.endsWith(".*")) { | |
| return ct.startsWith(pattern.slice(0, -1)); | |
| } | |
| return ct === pattern; | |
| }); | |
| } | |
| // ---------- Module-level singletons read once at startup ---------- | |
| const allowedPatterns: string[] = parseAllowedTypes( | |
| process.env.PAPERCLIP_ALLOWED_ATTACHMENT_TYPES, | |
| ); | |
| /** Convenience wrapper using the process-level allowed list. */ | |
| export function isAllowedContentType(contentType: string): boolean { | |
| return matchesContentType(contentType, allowedPatterns); | |
| } | |
| export const MAX_ATTACHMENT_BYTES = | |
| Number(process.env.PAPERCLIP_ATTACHMENT_MAX_BYTES) || 10 * 1024 * 1024; | |