img-upload-kit 1.1.1 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +56 -41
- package/MIGRATION.md +192 -0
- package/README.md +138 -154
- package/dist/bin.js +1186 -0
- package/dist/bin.js.map +1 -0
- package/dist/blur.cjs +40 -412
- package/dist/blur.cjs.map +1 -1
- package/dist/blur.d.cts +5 -5
- package/dist/blur.d.ts +5 -5
- package/dist/blur.js +39 -393
- package/dist/blur.js.map +1 -1
- package/dist/blurDataUtils-DveBRtqE.d.cts +43 -0
- package/dist/blurDataUtils-yx9Q6HlU.d.ts +43 -0
- package/dist/blurService-D5TpMNji.d.ts +83 -0
- package/dist/blurService-DacwylJx.d.cts +83 -0
- package/dist/chunk-2OVNXHTN.cjs +514 -0
- package/dist/chunk-2OVNXHTN.cjs.map +1 -0
- package/dist/chunk-3ICG2SLL.cjs +135 -0
- package/dist/chunk-3ICG2SLL.cjs.map +1 -0
- package/dist/chunk-4ASFG3KB.js +514 -0
- package/dist/chunk-4ASFG3KB.js.map +1 -0
- package/dist/chunk-AI3JJLSA.js +2370 -0
- package/dist/chunk-AI3JJLSA.js.map +1 -0
- package/dist/chunk-CV23O4YU.js +145 -0
- package/dist/chunk-CV23O4YU.js.map +1 -0
- package/dist/chunk-G7LLSKBV.js +158 -0
- package/dist/chunk-G7LLSKBV.js.map +1 -0
- package/dist/chunk-IB3TEDLR.js +294 -0
- package/dist/chunk-IB3TEDLR.js.map +1 -0
- package/dist/chunk-KJVYWKIG.cjs +158 -0
- package/dist/chunk-KJVYWKIG.cjs.map +1 -0
- package/dist/chunk-NEDBIIE3.cjs +226 -0
- package/dist/chunk-NEDBIIE3.cjs.map +1 -0
- package/dist/chunk-QHU7FUO4.cjs +37 -0
- package/dist/chunk-QHU7FUO4.cjs.map +1 -0
- package/dist/chunk-QQHZJKNA.js +135 -0
- package/dist/chunk-QQHZJKNA.js.map +1 -0
- package/dist/chunk-S2IFAWJK.js +37 -0
- package/dist/chunk-S2IFAWJK.js.map +1 -0
- package/dist/chunk-TT5C7K3Q.js +226 -0
- package/dist/chunk-TT5C7K3Q.js.map +1 -0
- package/dist/chunk-U2TWTEBY.cjs +2370 -0
- package/dist/chunk-U2TWTEBY.cjs.map +1 -0
- package/dist/chunk-WISG74VL.cjs +294 -0
- package/dist/chunk-WISG74VL.cjs.map +1 -0
- package/dist/chunk-YRXXQUDE.cjs +145 -0
- package/dist/chunk-YRXXQUDE.cjs.map +1 -0
- package/dist/cli.cjs +273 -76
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +269 -73
- package/dist/cli.js.map +1 -1
- package/dist/headless.cjs +8 -1880
- package/dist/headless.cjs.map +1 -1
- package/dist/headless.d.cts +3 -1
- package/dist/headless.d.ts +3 -1
- package/dist/headless.js +25 -1886
- package/dist/headless.js.map +1 -1
- package/dist/index-BIdnqtW8.d.ts +234 -0
- package/dist/index-Brk_uHs6.d.cts +234 -0
- package/dist/{index-FVXXKf2v.d.ts → index-CPMlaQsC.d.ts} +76 -153
- package/dist/{index-FVXXKf2v.d.cts → index-DHINe-rA.d.cts} +76 -153
- package/dist/index.cjs +64 -532
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +7 -4
- package/dist/index.d.ts +7 -4
- package/dist/index.js +63 -504
- package/dist/index.js.map +1 -1
- package/dist/{memoryAdapter-CBu7_3Pp.d.ts → memoryAdapter-Ck0ccZbF.d.cts} +3 -2
- package/dist/{memoryAdapter-BJjyLR-1.d.cts → memoryAdapter-DxEKaG0b.d.ts} +3 -2
- package/dist/placeholders-C4ftwaII.d.ts +5 -0
- package/dist/placeholders-x_3rt65M.d.cts +5 -0
- package/dist/react.cjs +1952 -3257
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +188 -50
- package/dist/react.d.ts +188 -50
- package/dist/react.js +1763 -3013
- package/dist/react.js.map +1 -1
- package/dist/server-handler.cjs +14 -0
- package/dist/server-handler.cjs.map +1 -0
- package/dist/server-handler.d.cts +3 -0
- package/dist/server-handler.d.ts +3 -0
- package/dist/server-handler.js +14 -0
- package/dist/server-handler.js.map +1 -0
- package/dist/server.cjs +1096 -532
- package/dist/server.cjs.map +1 -1
- package/dist/server.d.cts +77 -154
- package/dist/server.d.ts +77 -154
- package/dist/server.js +1050 -448
- package/dist/server.js.map +1 -1
- package/dist/storage.cjs +239 -232
- package/dist/storage.cjs.map +1 -1
- package/dist/storage.d.cts +21 -5
- package/dist/storage.d.ts +21 -5
- package/dist/storage.js +227 -207
- package/dist/storage.js.map +1 -1
- package/dist/styles/animated-image.css +112 -0
- package/dist/styles/dropzone-and-tiles.css +247 -0
- package/dist/styles/modals-and-dock.css +248 -0
- package/dist/styles/primitives.css +197 -0
- package/dist/styles/quality-and-inputs.css +184 -0
- package/dist/styles/tokens.css +123 -0
- package/dist/styles.css +39 -24
- package/dist/types-BrP-o9nd.d.cts +85 -0
- package/dist/types-sZ3KoFQY.d.ts +85 -0
- package/dist/types-yShGNQnW.d.cts +61 -0
- package/dist/types-yShGNQnW.d.ts +61 -0
- package/dist/{types-CiLY0DwB.d.cts → upload-C5Trd6Dh.d.cts} +27 -53
- package/dist/{types-CiLY0DwB.d.ts → upload-C5Trd6Dh.d.ts} +27 -53
- package/package.json +92 -32
- package/dist/blurService-DqsnfPTd.d.cts +0 -172
- package/dist/blurService-DqsnfPTd.d.ts +0 -172
package/dist/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/server/handler.ts","../src/server/optimization/types.ts","../src/types/presets.ts","../src/server/optimization/imageOptimizer.ts","../src/utils/color.ts","../src/server/optimization/colorHistogram.ts","../src/server/optimization/edgeColorExtractor.ts","../src/server/optimization/blurGenerator.ts","../src/server/semaphore.ts","../src/server/uploader/bufferProcessor.ts","../src/utils/validators.ts","../src/server/uploader/pathGenerator.ts","../src/server/uploader/uploadRetry.ts","../src/server/uploader/createImageUploader.ts"],"names":["sharp","r","g","b","encodeBlurHash","fullPath","crypto"],"mappings":"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","file":"server.js","sourcesContent":["import type { ExplicitOutputFormat, ImageDimensions } from '../types';\nimport type { ImageUploader } from './uploadService';\n\nexport interface UploadHttpHandlerOptions<TPreset extends string = string> {\n uploader: ImageUploader<TPreset>;\n /**\n * Optional authorization check. Return `false` or throw to reject with 401.\n */\n authorize?: (request: Request) => boolean | Promise<boolean>;\n /**\n * Optional whitelist of allowed preset names.\n */\n allowedPresets?: string[];\n /**\n * Allow clients to override `bucket` via FormData. Defaults to `false` for security.\n */\n allowClientBucketOverride?: boolean;\n}\n\nexport class UploadValidationError extends Error {\n readonly status = 400;\n constructor(message: string) {\n super(message);\n this.name = 'UploadValidationError';\n }\n}\n\nconst VALIDATION_ERROR_SUBSTRINGS = [\n 'exceeds maximum',\n 'file size',\n 'too large',\n 'is not allowed',\n 'not allowed',\n 'unsupported image format',\n 'unsupported format',\n 'invalid format',\n 'invalid image',\n 'not a valid image',\n 'file type',\n 'invalid preset',\n 'no file provided',\n 'file is empty',\n];\n\nexport function isClientValidationError(error: unknown): boolean {\n if (!error) return false;\n if (error instanceof UploadValidationError) return true;\n if (\n typeof error === 'object' &&\n error !== null &&\n 'status' in error &&\n (error as { status: unknown }).status === 400\n ) {\n return true;\n }\n if (\n error instanceof Error &&\n (error.name === 'UploadValidationError' ||\n error.name === 'ValidationError')\n ) {\n return true;\n }\n\n const msg =\n error instanceof Error ? error.message.toLowerCase() : String(error).toLowerCase();\n\n return VALIDATION_ERROR_SUBSTRINGS.some((sub) => msg.includes(sub));\n}\n\nfunction jsonResponse(body: unknown, status: number = 200): Response {\n return new Response(JSON.stringify(body), {\n status,\n headers: { 'Content-Type': 'application/json' },\n });\n}\n\nfunction parseJsonRecord(raw: string | null): Record<string, string> | undefined {\n if (!raw) return undefined;\n try {\n const parsed = JSON.parse(raw);\n if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {\n const clean: Record<string, string> = {};\n for (const [k, v] of Object.entries(parsed)) {\n if (v !== undefined && v !== null) {\n clean[k] = String(v);\n }\n }\n return Object.keys(clean).length > 0 ? clean : undefined;\n }\n } catch {\n // Ignore malformed metadata JSON\n }\n return undefined;\n}\n\n/**\n * Standard Web Fetch (`Request` -> `Response`) upload & delete route handlers.\n * Works across Next.js App Router, Remix, React Router, SvelteKit, Astro, Hono, and Node Fetch servers.\n */\nexport function createUploadHttpHandler<TPreset extends string = string>(\n options: UploadHttpHandlerOptions<TPreset>,\n) {\n const {\n uploader,\n authorize,\n allowedPresets,\n allowClientBucketOverride = false,\n } = options;\n\n async function POST(request: Request): Promise<Response> {\n try {\n if (authorize) {\n const allowed = await authorize(request);\n if (!allowed) {\n return jsonResponse({ error: 'Unauthorized' }, 401);\n }\n }\n\n const formData = await request.formData();\n const file = formData.get('file') as File | null;\n if (\n !file ||\n typeof file === 'string' ||\n (typeof file.size === 'number' && file.size === 0 && !file.name)\n ) {\n return jsonResponse({ error: 'No file provided' }, 400);\n }\n if (typeof file.size === 'number' && file.size === 0) {\n return jsonResponse({ error: 'File is empty' }, 400);\n }\n\n const preset = (formData.get('preset') as TPreset | null) || undefined;\n if (preset) {\n if (\n allowedPresets &&\n allowedPresets.length > 0 &&\n !allowedPresets.includes(preset)\n ) {\n return jsonResponse(\n {\n error: `Invalid preset \"${preset}\". Allowed presets: ${allowedPresets.join(', ')}`,\n },\n 400,\n );\n }\n if (\n typeof uploader.resolvePreset === 'function' &&\n !uploader.resolvePreset(preset)\n ) {\n return jsonResponse(\n {\n error: `Invalid preset \"${preset}\".`,\n },\n 400,\n );\n }\n }\n\n const folder = (formData.get('folder') as string | null) || undefined;\n const bucket = allowClientBucketOverride\n ? (formData.get('bucket') as string | null) || undefined\n : undefined;\n const altText = (formData.get('altText') as string | null) || undefined;\n const customFilename =\n (formData.get('customFilename') as string | null) || undefined;\n\n const outputFormatRaw = formData.get('outputFormat') as string | null;\n if (\n outputFormatRaw &&\n !['jpeg', 'png', 'webp', 'avif'].includes(outputFormatRaw)\n ) {\n return jsonResponse(\n {\n error: `Invalid output format \"${outputFormatRaw}\". Allowed formats: jpeg, png, webp, avif`,\n },\n 400,\n );\n }\n const outputFormat =\n (outputFormatRaw as ExplicitOutputFormat) || undefined;\n\n const qualityRaw = formData.get('quality') as string | null;\n const quality =\n qualityRaw !== null\n ? Math.max(1, Math.min(100, parseInt(qualityRaw, 10) || 85))\n : undefined;\n\n const maxWidthRaw = formData.get('maxWidth') as string | null;\n const maxHeightRaw = formData.get('maxHeight') as string | null;\n let maxDimensions: ImageDimensions | undefined;\n if (maxWidthRaw && maxHeightRaw) {\n const w = parseInt(maxWidthRaw, 10);\n const h = parseInt(maxHeightRaw, 10);\n if (w > 0 && h > 0) {\n maxDimensions = { width: w, height: h };\n }\n }\n\n const metadata = parseJsonRecord(\n formData.get('metadata') as string | null,\n );\n\n const result = await uploader.uploadImage(file, {\n preset,\n folder,\n bucket,\n altText,\n customFilename,\n outputFormat,\n quality,\n maxDimensions,\n metadata,\n });\n\n return jsonResponse(result, 200);\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : 'Internal server error';\n const status = isClientValidationError(error) ? 400 : 500;\n return jsonResponse({ error: errorMessage }, status);\n }\n }\n\n async function DELETE(request: Request): Promise<Response> {\n try {\n if (authorize) {\n const allowed = await authorize(request);\n if (!allowed) {\n return jsonResponse({ error: 'Unauthorized' }, 401);\n }\n }\n\n const { searchParams } = new URL(request.url);\n const url = searchParams.get('url');\n if (url) {\n const deleted = await uploader.deleteByUrl(url);\n return jsonResponse({ success: deleted }, deleted ? 200 : 400);\n }\n\n const storagePath = searchParams.get('path');\n const bucket = allowClientBucketOverride\n ? searchParams.get('bucket') || undefined\n : undefined;\n\n if (!storagePath) {\n return jsonResponse(\n { error: 'Missing required \"path\" or \"url\" query parameter' },\n 400,\n );\n }\n\n await uploader.deleteImage(storagePath, bucket);\n return jsonResponse({ success: true }, 200);\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : 'Internal server error';\n return jsonResponse({ error: errorMessage }, 500);\n }\n }\n\n return { POST, DELETE };\n}\n","import type {\n ExplicitOutputFormat,\n ImageDimensions,\n ImageOutputFormat,\n} from '../../types';\n\nexport interface OptimizedImageResult {\n buffer: Buffer;\n width: number;\n height: number;\n format: ImageOutputFormat;\n size: number;\n}\n\nexport interface BlurHashResult {\n dataURL: string;\n color: string;\n blurHash?: string;\n}\n\nexport interface OptimizeImageOptions {\n /** Max bounding box dimensions (fit: 'inside', withoutEnlargement: true). Defaults to 1920x1080. */\n maxDimensions?: ImageDimensions;\n /** Explicit output format; omit for smart size-guarded AVIF/WebP selection */\n outputFormat?: ExplicitOutputFormat;\n /** 1–100 compression quality. Defaults to smart photo/graphic heuristic (85–88). */\n quality?: number;\n}\n\nexport interface GenerateBlurOptions {\n width?: number;\n fallbackWidth?: number;\n quality?: number;\n maxDataUrlChars?: number;\n includeBlurHash?: boolean;\n}\n\nexport type ColorSamplingMode = 'balanced' | 'edge';\nexport type EdgeKey = 'top' | 'right' | 'bottom' | 'left';\nexport type EdgeColorSet = Record<EdgeKey, string>;\n\nexport const PRIMARY_AVIF_EFFORT = 6;\nexport const RETRY_AVIF_EFFORT = 5;\n\nexport const BLUR_PLACEHOLDER_WIDTH = 128;\nexport const BLUR_PLACEHOLDER_FALLBACK_WIDTH = 96;\nexport const BLUR_PLACEHOLDER_QUALITY = 80;\nexport const BLUR_PLACEHOLDER_MAX_CHARS = 8000;\n\nexport const EDGE_COLOR_FALLBACK = '#6B7280';\nexport const EDGE_WHITE_FALLBACK = '#F9FAFB';\nexport const WHITE_DOMINANCE_RATIO = 1.35;\n","import type {\n ExplicitOutputFormat,\n ImageDimensions,\n QualityLevel,\n} from './quality';\n\n/**\n * Universal visual role presets (project-agnostic).\n * Consumers can define their own presets via `defineUploadPresets` / `createImageUploader({ presets })`\n * or augment `UploadKitRegister` for global type-safety.\n */\nexport type StandardPresetName =\n | 'thumbnail'\n | 'avatar'\n | 'card'\n | 'cover'\n | 'hero'\n | 'logo'\n | 'original';\n\n/**\n * Module augmentation hook for global preset autocomplete across a project:\n * ```ts\n * declare module 'img-upload-kit' {\n * interface UploadKitRegister {\n * presets: 'product-main' | 'product-thumb' | 'user-avatar';\n * }\n * }\n * ```\n */\n// eslint-disable-next-line @typescript-eslint/no-empty-object-type\nexport interface UploadKitRegister {}\n\nexport type UploadPresetName = UploadKitRegister extends {\n presets: infer TCustom extends string;\n}\n ? TCustom\n : StandardPresetName | (string & {});\n\nexport interface UploadPresetConfig {\n /** Target storage bucket for this preset */\n bucket?: string;\n /** Default folder prefix within the bucket (e.g. 'avatars' or 'products/thumbnails') */\n folder?: string;\n /** Maximum bounding box dimensions (aspect ratio preserved, never enlarged) */\n maxDimensions?: ImageDimensions;\n /** Maximum allowed source file size in MB */\n maxSizeMB?: number;\n /** Allowed source MIME types */\n allowedFormats?: string[];\n /** Force a specific output format; omit for smart size-guarded AVIF/WebP optimization */\n outputFormat?: ExplicitOutputFormat;\n /** Default compression quality (1–100) */\n quality?: number;\n /** Recommended UI quality tab for React `<QualitySelector />` */\n recommendedQualityLevel?: QualityLevel;\n /** Optional guidance note shown in `<QualitySelector />` */\n recommendationNote?: { en: string; ar?: string };\n /** Generate compact BlurHash string alongside WebP LQIP data URL */\n includeBlurHash?: boolean;\n /** Optional local directory to mirror uploaded files into */\n mirrorDir?: string;\n /** Optional public URL prefix when `mirrorDir` is used */\n publicUrlBase?: string;\n}\n\nexport const DEFAULT_ALLOWED_FORMATS: string[] = [\n 'image/jpeg',\n 'image/png',\n 'image/webp',\n 'image/avif',\n 'image/svg+xml',\n];\n\nexport const RASTER_ALLOWED_FORMATS: string[] = [\n 'image/jpeg',\n 'image/png',\n 'image/webp',\n 'image/avif',\n];\n\nexport const DEFAULT_IMAGE_DIMENSIONS: ImageDimensions = {\n width: 1920,\n height: 1080,\n};\n\nexport const STANDARD_PRESETS: Record<StandardPresetName, UploadPresetConfig> = {\n thumbnail: {\n folder: 'thumbnails',\n maxDimensions: { width: 600, height: 600 },\n maxSizeMB: 5,\n quality: 78,\n recommendedQualityLevel: 'medium',\n allowedFormats: RASTER_ALLOWED_FORMATS,\n recommendationNote: {\n en: 'Thumbnails display at compact sizes — Medium quality keeps pages fast',\n ar: 'المصغرات تعرض بأحجام صغيرة — الجودة المتوسطة تحافظ على سرعة الصفحة',\n },\n },\n avatar: {\n folder: 'avatars',\n maxDimensions: { width: 512, height: 512 },\n maxSizeMB: 5,\n quality: 80,\n recommendedQualityLevel: 'medium',\n allowedFormats: RASTER_ALLOWED_FORMATS,\n recommendationNote: {\n en: 'Avatars display small — Medium quality balances sharpness and speed',\n ar: 'الصور الشخصية صغيرة — الجودة المتوسطة توازن بين الوضوح والسرعة',\n },\n },\n card: {\n folder: 'cards',\n maxDimensions: { width: 1200, height: 900 },\n maxSizeMB: 8,\n quality: 85,\n recommendedQualityLevel: 'high',\n allowedFormats: DEFAULT_ALLOWED_FORMATS,\n },\n cover: {\n folder: 'covers',\n maxDimensions: { width: 1920, height: 1080 },\n maxSizeMB: 10,\n quality: 88,\n recommendedQualityLevel: 'high',\n allowedFormats: DEFAULT_ALLOWED_FORMATS,\n },\n hero: {\n folder: 'hero',\n maxDimensions: { width: 2560, height: 1440 },\n maxSizeMB: 15,\n quality: 92,\n recommendedQualityLevel: 'maximum',\n allowedFormats: DEFAULT_ALLOWED_FORMATS,\n recommendationNote: {\n en: 'Full-width hero visuals benefit from Maximum quality to preserve fine detail',\n ar: 'الصور الرئيسية بعرض كامل تستفيد من الجودة القصوى للحفاظ على التفاصيل الدقيقة',\n },\n },\n logo: {\n folder: 'logos',\n maxDimensions: { width: 800, height: 800 },\n maxSizeMB: 5,\n quality: 90,\n recommendedQualityLevel: 'high',\n allowedFormats: DEFAULT_ALLOWED_FORMATS,\n recommendationNote: {\n en: 'Prefer SVG for vector logos — High quality preserves crisp edges on raster logos',\n ar: 'يفضل SVG للشعارات المتجهة — الجودة العالية تحافظ على حواف واضحة',\n },\n },\n original: {\n folder: 'originals',\n maxDimensions: { width: 4096, height: 4096 },\n maxSizeMB: 25,\n quality: 95,\n recommendedQualityLevel: 'maximum',\n allowedFormats: DEFAULT_ALLOWED_FORMATS,\n },\n};\n\n/**\n * Type-safe helper to define project-specific upload presets with full key inference.\n */\nexport function defineUploadPresets<\n T extends Record<string, UploadPresetConfig>,\n>(presets: T): T {\n return presets;\n}\n","import sharp from 'sharp';\nimport { DEFAULT_IMAGE_DIMENSIONS } from '../../types';\nimport {\n type OptimizedImageResult,\n type OptimizeImageOptions,\n PRIMARY_AVIF_EFFORT,\n RETRY_AVIF_EFFORT,\n} from './types';\n\nexport async function optimizeImage(\n buffer: Buffer,\n options: OptimizeImageOptions = {},\n): Promise<OptimizedImageResult> {\n const maxDimensions = options.maxDimensions || DEFAULT_IMAGE_DIMENSIONS;\n const { outputFormat, quality } = options;\n\n let pipeline = sharp(buffer, {\n failOnError: false,\n limitInputPixels: 268402689,\n }).rotate();\n\n const metadata = await pipeline.metadata();\n const originalFormat = metadata.format;\n\n if (originalFormat === 'svg') {\n let width = metadata.width;\n let height = metadata.height;\n\n if (!width || !height) {\n const svgText = buffer.toString('utf8');\n const viewBoxMatch = svgText.match(\n /viewBox\\s*=\\s*[\"']\\s*([\\d.-]+)\\s+([\\d.-]+)\\s+([\\d.-]+)\\s+([\\d.-]+)\\s*[\"']/i,\n );\n if (viewBoxMatch) {\n width = Math.round(parseFloat(viewBoxMatch[3]));\n height = Math.round(parseFloat(viewBoxMatch[4]));\n }\n }\n\n return {\n buffer,\n width: width || maxDimensions.width || 600,\n height: height || maxDimensions.height || 600,\n format: 'svg',\n size: buffer.length,\n };\n }\n\n const isPhoto =\n originalFormat === 'jpeg' ||\n Boolean(metadata.density && metadata.density > 150);\n\n let baseQuality = quality ?? (isPhoto ? 85 : 88);\n baseQuality = Math.max(1, Math.min(100, baseQuality));\n\n pipeline = pipeline.resize(maxDimensions.width, maxDimensions.height, {\n fit: 'inside',\n withoutEnlargement: true,\n kernel: 'lanczos3',\n });\n\n if (\n outputFormat === 'jpeg' ||\n outputFormat === 'png' ||\n outputFormat === 'webp'\n ) {\n let cloned = pipeline.clone();\n if (outputFormat === 'jpeg') {\n cloned = cloned.jpeg({ quality: baseQuality, mozjpeg: true });\n } else if (outputFormat === 'png') {\n cloned = cloned.png();\n } else if (outputFormat === 'webp') {\n cloned = cloned.webp({ quality: baseQuality, effort: 4 });\n }\n\n const outputBuffer = await cloned.toBuffer({ resolveWithObject: true });\n\n return {\n buffer: outputBuffer.data,\n width: outputBuffer.info.width || maxDimensions.width,\n height: outputBuffer.info.height || maxDimensions.height,\n format: outputFormat,\n size: outputBuffer.info.size,\n };\n }\n\n const avifBuffer = await pipeline\n .clone()\n .avif({\n quality: baseQuality,\n effort: PRIMARY_AVIF_EFFORT,\n chromaSubsampling: '4:2:0',\n bitdepth: 8,\n })\n .toBuffer({ resolveWithObject: true });\n\n // Size-guard against bloating previously low-Q JPEGs when re-encoded at high-Q AVIF\n const avifSize = avifBuffer.info.size;\n const originalSize = buffer.length;\n\n if (avifSize <= originalSize || outputFormat === 'avif') {\n const finalMetadata = await sharp(avifBuffer.data).metadata();\n return {\n buffer: avifBuffer.data,\n width: finalMetadata.width ?? maxDimensions.width,\n height: finalMetadata.height ?? maxDimensions.height,\n format: 'avif',\n size: avifSize,\n };\n }\n\n const scaledQuality = Math.max(\n 40,\n Math.round(baseQuality * Math.sqrt(originalSize / avifSize)),\n );\n\n const avifRetry = await pipeline\n .clone()\n .avif({\n quality: scaledQuality,\n effort: RETRY_AVIF_EFFORT,\n chromaSubsampling: '4:2:0',\n bitdepth: 8,\n })\n .toBuffer({ resolveWithObject: true });\n\n if (avifRetry.info.size <= originalSize) {\n const retryMeta = await sharp(avifRetry.data).metadata();\n return {\n buffer: avifRetry.data,\n width: retryMeta.width ?? maxDimensions.width,\n height: retryMeta.height ?? maxDimensions.height,\n format: 'avif',\n size: avifRetry.info.size,\n };\n }\n\n const wasDimensionCapped =\n (metadata.width ?? 0) > maxDimensions.width ||\n (metadata.height ?? 0) > maxDimensions.height;\n\n if (!wasDimensionCapped) {\n const PASSTHROUGH_FORMATS = new Set(['jpeg', 'png', 'webp', 'avif']);\n const srcFmt = PASSTHROUGH_FORMATS.has(originalFormat ?? '')\n ? (originalFormat as 'jpeg' | 'png' | 'webp' | 'avif')\n : 'jpeg';\n return {\n buffer,\n width: metadata.width ?? maxDimensions.width,\n height: metadata.height ?? maxDimensions.height,\n format: srcFmt,\n size: originalSize,\n };\n }\n\n const webpBuffer = await pipeline\n .clone()\n .webp({ quality: baseQuality, effort: 6, smartSubsample: true })\n .toBuffer({ resolveWithObject: true });\n\n const useWebP = webpBuffer.info.size <= avifRetry.info.size;\n const winner = useWebP\n ? { buf: webpBuffer.data, fmt: 'webp' as const, sz: webpBuffer.info.size }\n : { buf: avifRetry.data, fmt: 'avif' as const, sz: avifRetry.info.size };\n\n const winnerMeta = await sharp(winner.buf).metadata();\n return {\n buffer: winner.buf,\n width: winnerMeta.width ?? maxDimensions.width,\n height: winnerMeta.height ?? maxDimensions.height,\n format: winner.fmt,\n size: winner.sz,\n };\n}\n","export const DEFAULT_BLUR_COLOR = '#F5F5F5';\n\nexport function normalizeColorInput(value?: string | null): string | null {\n if (!value) return null;\n let next = value.trim();\n if (!next) return null;\n if (!next.startsWith('#')) {\n next = `#${next}`;\n }\n const threeHex = /^#([0-9a-fA-F]{3})$/;\n const sixHex = /^#([0-9a-fA-F]{6})$/;\n if (threeHex.test(next)) {\n const [, triplet] = next.match(threeHex) ?? [];\n if (triplet) {\n next = `#${triplet\n .split('')\n .map((char) => char + char)\n .join('')}`;\n }\n } else if (!sixHex.test(next)) {\n return null;\n }\n return next.toUpperCase();\n}\n\nexport function hexToRgb(hex: string): { r: number; g: number; b: number } {\n const normalized = hex.replace('#', '');\n const expanded =\n normalized.length === 3\n ? normalized\n .split('')\n .map((char) => char + char)\n .join('')\n : normalized;\n const padded = expanded.padEnd(6, '0').slice(0, 6);\n const value = Number.parseInt(padded, 16);\n if (Number.isNaN(value)) {\n return { r: 245, g: 245, b: 245 };\n }\n return {\n r: (value >> 16) & 255,\n g: (value >> 8) & 255,\n b: value & 255,\n };\n}\n\nexport function rgbToHex(r: number, g: number, b: number): string {\n const clamp = (v: number) => Math.max(0, Math.min(255, Math.round(v)));\n const value = (clamp(r) << 16) | (clamp(g) << 8) | clamp(b);\n return `#${value.toString(16).padStart(6, '0').toUpperCase()}`;\n}\n\nfunction encodeBase64Ascii(str: string): string {\n if (typeof btoa === 'function') {\n return btoa(str);\n }\n return Buffer.from(str, 'utf8').toString('base64');\n}\n\nexport function generateColorSvgDataURL(color: string = DEFAULT_BLUR_COLOR): string {\n const safeColor = normalizeColorInput(color) || DEFAULT_BLUR_COLOR;\n const svg = `<svg width=\"100\" height=\"100\" xmlns=\"http://www.w3.org/2000/svg\"><rect width=\"100%\" height=\"100%\" fill=\"${safeColor}\"/></svg>`;\n return `data:image/svg+xml;base64,${encodeBase64Ascii(svg)}`;\n}\n","import sharp from 'sharp';\nimport { rgbToHex } from '../../utils/color';\nimport {\n type ColorSamplingMode,\n EDGE_COLOR_FALLBACK,\n EDGE_WHITE_FALLBACK,\n WHITE_DOMINANCE_RATIO,\n} from './types';\n\nexport async function extractEnhancedColorFromBuffer(\n buffer: Buffer,\n mode: ColorSamplingMode = 'balanced',\n): Promise<string> {\n try {\n const metadata = await sharp(buffer).metadata();\n const maxSize = 400;\n const needsResize =\n metadata.width &&\n metadata.height &&\n (metadata.width > maxSize || metadata.height > maxSize);\n\n if (needsResize) {\n const resized = await sharp(buffer)\n .resize(maxSize, maxSize, {\n fit: 'inside',\n kernel: 'lanczos3',\n withoutEnlargement: true,\n })\n .ensureAlpha()\n .raw()\n .toBuffer({ resolveWithObject: true });\n\n return extractDominantColorHistogramAdvanced(\n resized.data,\n resized.info.width,\n resized.info.height,\n mode,\n );\n }\n\n const raw = await sharp(buffer)\n .ensureAlpha()\n .raw()\n .toBuffer({ resolveWithObject: true });\n\n return extractDominantColorHistogramAdvanced(\n raw.data,\n raw.info.width,\n raw.info.height,\n mode,\n );\n } catch {\n const stats = await sharp(buffer)\n .resize(64, 64, { fit: 'cover', kernel: 'lanczos3' })\n .ensureAlpha()\n .raw()\n .toBuffer({ resolveWithObject: true });\n return extractDominantColorHistogram(stats.data);\n }\n}\n\nfunction extractDominantColorHistogramAdvanced(\n data: Buffer,\n width: number,\n height: number,\n mode: ColorSamplingMode,\n): string {\n const colorMap = new Map<string, number>();\n const bucketSize = 16;\n\n const centerWeight = 1.5;\n const centerX = width / 2 || 1;\n const centerY = height / 2 || 1;\n let whiteWeight = 0;\n\n for (let i = 0; i < data.length; i += 4) {\n const alpha = data[i + 3];\n if (alpha !== undefined && alpha < 8) continue;\n\n const r = data[i];\n const g = data[i + 1];\n const b = data[i + 2];\n const brightness = (r + g + b) / 3;\n if (brightness < 10) continue;\n\n const pixelIndex = i / 4;\n const x = pixelIndex % width;\n const y = Math.floor(pixelIndex / width);\n const dx = (x - centerX) / centerX;\n const dy = (y - centerY) / centerY;\n const distanceFromCenter = Math.sqrt(dx * dx + dy * dy);\n let weight = 1.0;\n\n if (mode === 'edge') {\n const edgeThicknessX = Math.max(1, Math.floor(width * 0.12));\n const edgeThicknessY = Math.max(1, Math.floor(height * 0.12));\n\n const onLeftEdge = x < edgeThicknessX;\n const onRightEdge = x >= width - edgeThicknessX;\n const onTopEdge = y < edgeThicknessY;\n const onBottomEdge = y >= height - edgeThicknessY;\n\n if (!(onLeftEdge || onRightEdge || onTopEdge || onBottomEdge)) {\n continue;\n }\n\n const distanceToNearestEdge = Math.min(\n x,\n y,\n width - 1 - x,\n height - 1 - y,\n );\n const maxEdgeDistance = Math.max(edgeThicknessX, edgeThicknessY) || 1;\n const edgeFactor = 1 - distanceToNearestEdge / maxEdgeDistance;\n weight = 1 + edgeFactor * 3;\n } else {\n weight = distanceFromCenter < 0.5 ? centerWeight : 1.0;\n }\n\n const isNearWhite = r >= 245 && g >= 245 && b >= 245;\n if (isNearWhite) {\n whiteWeight += weight;\n continue;\n }\n\n const bucketR = Math.floor(r / bucketSize) * bucketSize;\n const bucketG = Math.floor(g / bucketSize) * bucketSize;\n const bucketB = Math.floor(b / bucketSize) * bucketSize;\n\n const key = `${bucketR},${bucketG},${bucketB}`;\n colorMap.set(key, (colorMap.get(key) || 0) + weight);\n }\n\n if (!colorMap.size) {\n return whiteWeight > 0 ? EDGE_WHITE_FALLBACK : EDGE_COLOR_FALLBACK;\n }\n\n let maxCount = 0;\n let dominantColor = '64,64,80';\n let totalColorWeight = 0;\n\n colorMap.forEach((count, color) => {\n totalColorWeight += count;\n if (count > maxCount) {\n maxCount = count;\n dominantColor = color;\n }\n });\n\n const whiteDominates =\n whiteWeight > 0 && whiteWeight >= totalColorWeight * WHITE_DOMINANCE_RATIO;\n if (whiteDominates) {\n return EDGE_WHITE_FALLBACK;\n }\n\n const [r, g, b] = dominantColor.split(',').map(Number);\n return rgbToHex(r, g, b);\n}\n\nfunction extractDominantColorHistogram(data: Buffer): string {\n const colorMap = new Map<string, number>();\n const bucketSize = 16;\n let whiteWeight = 0;\n\n for (let i = 0; i < data.length; i += 4) {\n const alpha = data[i + 3];\n if (alpha !== undefined && alpha < 8) continue;\n\n const r = Math.floor(data[i] / bucketSize) * bucketSize;\n const g = Math.floor(data[i + 1] / bucketSize) * bucketSize;\n const b = Math.floor(data[i + 2] / bucketSize) * bucketSize;\n\n if (r >= 240 && g >= 240 && b >= 240) {\n whiteWeight += 1;\n continue;\n }\n\n const key = `${r},${g},${b}`;\n colorMap.set(key, (colorMap.get(key) || 0) + 1);\n }\n\n if (!colorMap.size) {\n return whiteWeight > 0 ? EDGE_WHITE_FALLBACK : EDGE_COLOR_FALLBACK;\n }\n\n let maxCount = 0;\n let dominantColor = '64,64,80';\n let totalColorWeight = 0;\n\n colorMap.forEach((count, color) => {\n totalColorWeight += count;\n if (count > maxCount) {\n maxCount = count;\n dominantColor = color;\n }\n });\n\n const whiteDominates =\n whiteWeight > 0 && whiteWeight >= totalColorWeight * WHITE_DOMINANCE_RATIO;\n if (whiteDominates) {\n return EDGE_WHITE_FALLBACK;\n }\n\n const [r, g, b] = dominantColor.split(',').map(Number);\n return rgbToHex(r, g, b);\n}\n","import sharp from 'sharp';\nimport { hexToRgb, rgbToHex } from '../../utils/color';\nimport { extractEnhancedColorFromBuffer } from './colorHistogram';\nimport {\n EDGE_COLOR_FALLBACK,\n EDGE_WHITE_FALLBACK,\n type EdgeColorSet,\n type EdgeKey,\n WHITE_DOMINANCE_RATIO,\n} from './types';\n\nexport async function extractEdgeColorsFromBuffer(\n buffer: Buffer,\n): Promise<EdgeColorSet> {\n try {\n const sample = await sharp(buffer)\n .resize(400, 400, {\n fit: 'inside',\n kernel: 'lanczos3',\n withoutEnlargement: true,\n })\n .ensureAlpha()\n .raw()\n .toBuffer({ resolveWithObject: true });\n\n return computeEdgeColorSet(\n sample.data,\n sample.info.width,\n sample.info.height,\n );\n } catch {\n try {\n const fallback = await extractEnhancedColorFromBuffer(buffer, 'edge');\n return {\n top: fallback,\n right: fallback,\n bottom: fallback,\n left: fallback,\n };\n } catch {\n return {\n top: EDGE_COLOR_FALLBACK,\n right: EDGE_COLOR_FALLBACK,\n bottom: EDGE_COLOR_FALLBACK,\n left: EDGE_COLOR_FALLBACK,\n };\n }\n }\n}\n\nfunction computeEdgeColorSet(\n data: Buffer,\n width: number,\n height: number,\n): EdgeColorSet {\n const thicknessX = Math.max(2, Math.floor(width * 0.12));\n const thicknessY = Math.max(2, Math.floor(height * 0.12));\n const bucketSize = 16;\n\n const edgeMaps: Record<EdgeKey, Map<string, number>> = {\n top: new Map(),\n right: new Map(),\n bottom: new Map(),\n left: new Map(),\n };\n\n const whiteEdgeStrength: Record<EdgeKey, number> = {\n top: 0,\n right: 0,\n bottom: 0,\n left: 0,\n };\n\n const accumulateEdgeSample = (\n edge: EdgeKey,\n weight: number,\n key: string,\n isWhiteSample: boolean,\n ) => {\n if (weight <= 0) return;\n if (isWhiteSample) {\n whiteEdgeStrength[edge] += weight;\n return;\n }\n edgeMaps[edge].set(key, (edgeMaps[edge].get(key) || 0) + weight);\n };\n\n for (let i = 0; i < data.length; i += 4) {\n const r = data[i];\n const g = data[i + 1];\n const b = data[i + 2];\n const alpha = data[i + 3];\n\n if (alpha !== undefined && alpha < 8) continue;\n\n const brightness = (r + g + b) / 3;\n if (brightness < 12) continue;\n\n const isNearWhite = r >= 245 && g >= 245 && b >= 245;\n\n const pixelIndex = i / 4;\n const x = pixelIndex % width;\n const y = Math.floor(pixelIndex / width);\n\n const bucketR = Math.floor(r / bucketSize) * bucketSize;\n const bucketG = Math.floor(g / bucketSize) * bucketSize;\n const bucketB = Math.floor(b / bucketSize) * bucketSize;\n const key = `${bucketR},${bucketG},${bucketB}`;\n\n const topWeight = y < thicknessY ? 1 + (thicknessY - y) / thicknessY : 0;\n if (topWeight > 0) {\n accumulateEdgeSample('top', topWeight, key, isNearWhite);\n }\n\n const bottomWeight =\n y >= height - thicknessY\n ? 1 + (y - (height - thicknessY)) / thicknessY\n : 0;\n if (bottomWeight > 0) {\n accumulateEdgeSample('bottom', bottomWeight, key, isNearWhite);\n }\n\n const leftWeight = x < thicknessX ? 1 + (thicknessX - x) / thicknessX : 0;\n if (leftWeight > 0) {\n accumulateEdgeSample('left', leftWeight, key, isNearWhite);\n }\n\n const rightWeight =\n x >= width - thicknessX\n ? 1 + (x - (width - thicknessX)) / thicknessX\n : 0;\n if (rightWeight > 0) {\n accumulateEdgeSample('right', rightWeight, key, isNearWhite);\n }\n }\n\n return {\n top: resolveEdgeColor(edgeMaps.top, whiteEdgeStrength.top),\n right: resolveEdgeColor(edgeMaps.right, whiteEdgeStrength.right),\n bottom: resolveEdgeColor(edgeMaps.bottom, whiteEdgeStrength.bottom),\n left: resolveEdgeColor(edgeMaps.left, whiteEdgeStrength.left),\n };\n}\n\nfunction resolveEdgeColor(\n map: Map<string, number>,\n whiteStrength: number,\n): string {\n if (!map.size) {\n return whiteStrength > 0 ? EDGE_WHITE_FALLBACK : EDGE_COLOR_FALLBACK;\n }\n\n let dominantColor = '';\n let maxCount = 0;\n let totalColorWeight = 0;\n\n map.forEach((count, color) => {\n totalColorWeight += count;\n if (count > maxCount) {\n maxCount = count;\n dominantColor = color;\n }\n });\n\n if (!dominantColor) {\n return whiteStrength > 0 ? EDGE_WHITE_FALLBACK : EDGE_COLOR_FALLBACK;\n }\n\n const whiteDominates =\n whiteStrength > 0 &&\n (totalColorWeight === 0 ||\n whiteStrength >= totalColorWeight * WHITE_DOMINANCE_RATIO);\n\n if (whiteDominates) {\n return EDGE_WHITE_FALLBACK;\n }\n\n if (dominantColor.startsWith('#')) {\n return dominantColor.toUpperCase();\n }\n\n const [r, g, b] = dominantColor.split(',').map(Number);\n return rgbToHex(r, g, b);\n}\n\nexport function blendEdgeColors(edgeColors: EdgeColorSet): string {\n const colors = Object.values(edgeColors);\n if (!colors.length) {\n return EDGE_COLOR_FALLBACK;\n }\n\n const totals = colors.reduce(\n (acc, hex) => {\n const { r, g, b } = hexToRgb(hex || EDGE_COLOR_FALLBACK);\n acc.r += r;\n acc.g += g;\n acc.b += b;\n return acc;\n },\n { r: 0, g: 0, b: 0 },\n );\n\n const count = colors.length;\n return rgbToHex(totals.r / count, totals.g / count, totals.b / count);\n}\n","import { encode as encodeBlurHash } from 'blurhash';\nimport lqip from 'lqip-modern';\nimport sharp from 'sharp';\nimport {\n blendEdgeColors,\n extractEdgeColorsFromBuffer,\n} from './edgeColorExtractor';\nimport {\n BLUR_PLACEHOLDER_FALLBACK_WIDTH,\n BLUR_PLACEHOLDER_MAX_CHARS,\n BLUR_PLACEHOLDER_QUALITY,\n BLUR_PLACEHOLDER_WIDTH,\n type BlurHashResult,\n type GenerateBlurOptions,\n} from './types';\n\nexport async function encodeBlurHashString(\n buffer: Buffer,\n componentX: number = 4,\n componentY: number = 3,\n): Promise<string> {\n const { data, info } = await sharp(buffer)\n .resize(32, 32, { fit: 'inside' })\n .ensureAlpha()\n .raw()\n .toBuffer({ resolveWithObject: true });\n\n const clampedX = Math.max(1, Math.min(Math.round(componentX), info.width, 9));\n const clampedY = Math.max(1, Math.min(Math.round(componentY), info.height, 9));\n\n return encodeBlurHash(\n new Uint8ClampedArray(data),\n info.width,\n info.height,\n clampedX,\n clampedY,\n );\n}\n\nexport async function generateBlurPlaceholder(\n buffer: Buffer,\n options: GenerateBlurOptions = {},\n): Promise<BlurHashResult> {\n const targetWidth = options.width ?? BLUR_PLACEHOLDER_WIDTH;\n const fallbackWidth =\n options.fallbackWidth ?? BLUR_PLACEHOLDER_FALLBACK_WIDTH;\n const quality = options.quality ?? BLUR_PLACEHOLDER_QUALITY;\n const maxChars = options.maxDataUrlChars ?? BLUR_PLACEHOLDER_MAX_CHARS;\n\n try {\n let processBuffer = buffer;\n const isSvg = /<svg[\\s>]/i.test(buffer.toString('utf8', 0, 1024));\n if (isSvg) {\n const normalizedSvg = buffer\n .toString('utf8')\n .replace(/<svg\\b/gi, '<svg')\n .replace(/<\\/svg\\s*>/gi, '</svg>');\n processBuffer = await sharp(Buffer.from(normalizedSvg, 'utf8'))\n .resize(targetWidth, targetWidth, { fit: 'inside' })\n .png()\n .toBuffer();\n }\n\n const buildPlaceholder = (width: number, q: number) =>\n lqip(processBuffer, {\n outputFormat: 'webp',\n resize: width,\n outputOptions: { quality: q, effort: 6, smartSubsample: true },\n });\n\n let result = await buildPlaceholder(targetWidth, quality);\n if (result.metadata.dataURIBase64.length > maxChars) {\n result = await buildPlaceholder(fallbackWidth, quality);\n }\n\n const dataURL = result.metadata.dataURIBase64;\n const edgeColors = await extractEdgeColorsFromBuffer(processBuffer);\n const color = blendEdgeColors(edgeColors);\n\n let blurHash: string | undefined;\n if (options.includeBlurHash) {\n try {\n blurHash = await encodeBlurHashString(processBuffer);\n } catch {\n blurHash = undefined;\n }\n }\n\n return {\n dataURL,\n color,\n ...(blurHash && { blurHash }),\n };\n } catch {\n return generateFallbackBlur(buffer, options.includeBlurHash);\n }\n}\n\nexport const generateBlurHash = generateBlurPlaceholder;\n\nasync function generateFallbackBlur(\n buffer: Buffer,\n includeBlurHash?: boolean,\n): Promise<BlurHashResult> {\n const tinyBuffer = await sharp(buffer)\n .resize(64, 64, { fit: 'cover', kernel: 'lanczos3' })\n .blur(1.0)\n .webp({\n quality: 75,\n effort: 6,\n smartSubsample: false,\n })\n .toBuffer();\n\n const dataURL = `data:image/webp;base64,${tinyBuffer.toString('base64')}`;\n const edgeColors = await extractEdgeColorsFromBuffer(buffer);\n const color = blendEdgeColors(edgeColors);\n\n let blurHash: string | undefined;\n if (includeBlurHash) {\n try {\n blurHash = await encodeBlurHashString(tinyBuffer);\n } catch {\n blurHash = undefined;\n }\n }\n\n return { dataURL, color, ...(blurHash && { blurHash }) };\n}\n","export class AsyncSemaphore {\n private activeCount = 0;\n private readonly queue: Array<() => void> = [];\n\n constructor(private readonly concurrency: number) {\n if (concurrency < 1) {\n throw new Error('AsyncSemaphore concurrency must be >= 1');\n }\n }\n\n async run<T>(task: () => Promise<T>): Promise<T> {\n await this.acquire();\n\n try {\n return await task();\n } finally {\n this.release();\n }\n }\n\n private acquire(): Promise<void> {\n if (this.activeCount < this.concurrency) {\n this.activeCount += 1;\n return Promise.resolve();\n }\n\n return new Promise((resolve) => {\n this.queue.push(() => {\n this.activeCount += 1;\n resolve();\n });\n });\n }\n\n private release(): void {\n this.activeCount = Math.max(0, this.activeCount - 1);\n const next = this.queue.shift();\n next?.();\n }\n}\n\nexport async function withTimeout<T>(\n task: Promise<T>,\n timeoutMs: number,\n label: string,\n): Promise<T> {\n let timeoutHandle: NodeJS.Timeout | null = null;\n\n try {\n return await Promise.race([\n task,\n new Promise<never>((_, reject) => {\n timeoutHandle = setTimeout(() => {\n reject(new Error(`${label} timed out after ${timeoutMs}ms`));\n }, timeoutMs);\n }),\n ]);\n } finally {\n if (timeoutHandle) {\n clearTimeout(timeoutHandle);\n }\n }\n}\n","import crypto from 'node:crypto';\nimport { generateBlurPlaceholder, optimizeImage } from '../optimization';\nimport { withTimeout } from '../semaphore';\nimport type {\n ProcessedImageBufferResult,\n ProcessImageBufferOptions,\n} from './types';\n\nexport async function processImageBuffer(\n originalBuffer: Buffer,\n options: ProcessImageBufferOptions = {},\n): Promise<ProcessedImageBufferResult> {\n const optTimeout = options.optimizationTimeoutMs ?? 60000;\n const blurTimeout = options.blurTimeoutMs ?? 30000;\n\n const contentHash = crypto\n .createHash('sha256')\n .update(originalBuffer)\n .digest('hex');\n\n const optimized = await withTimeout(\n optimizeImage(originalBuffer, {\n maxDimensions: options.maxDimensions,\n outputFormat: options.outputFormat,\n quality: options.quality,\n }),\n optTimeout,\n 'Image optimization',\n );\n\n if (!optimized || !optimized.buffer) {\n throw new Error('Image optimization returned invalid result');\n }\n\n if (!optimized.width || !optimized.height) {\n throw new Error(\n `Image dimensions missing: width=${optimized.width}, height=${optimized.height}`,\n );\n }\n\n const blurData = await withTimeout(\n generateBlurPlaceholder(optimized.buffer, {\n includeBlurHash: options.includeBlurHash,\n }),\n blurTimeout,\n 'Blur generation',\n );\n\n return {\n optimized,\n blurData,\n contentHash,\n originalSize: originalBuffer.length,\n };\n}\n","import type { UploadLocale } from '../types';\n\nexport interface FileLike {\n name?: string;\n size: number;\n type: string;\n}\n\nexport function validateImageFileStrict(\n file: FileLike,\n maxSizeMB: number,\n allowedFormats: string[],\n): { valid: boolean; error?: string } {\n const maxBytes = maxSizeMB * 1024 * 1024;\n if (file.size > maxBytes) {\n return {\n valid: false,\n error: `File size (${(file.size / 1024 / 1024).toFixed(2)}MB) exceeds maximum of ${maxSizeMB}MB`,\n };\n }\n\n if (allowedFormats.length > 0 && !allowedFormats.includes(file.type)) {\n return {\n valid: false,\n error: `File type ${file.type || 'unknown'} is not allowed. Allowed: ${allowedFormats.join(', ')}`,\n };\n }\n\n return { valid: true };\n}\n\nexport function validateImageFile(\n file: FileLike,\n maxSizeMB: number,\n locale: UploadLocale = 'en',\n allowedFormats?: string[],\n): string | null {\n if (!file.type || !file.type.startsWith('image/')) {\n return locale === 'ar'\n ? 'يرجى اختيار ملف صورة صالح'\n : 'Please select a valid image file';\n }\n\n if (allowedFormats && allowedFormats.length > 0 && !allowedFormats.includes(file.type)) {\n return locale === 'ar'\n ? `صيغة الملف غير مدعومة (${file.type})`\n : `Unsupported image format (${file.type})`;\n }\n\n const fileSizeMB = file.size / (1024 * 1024);\n if (fileSizeMB > maxSizeMB) {\n return locale === 'ar'\n ? `يجب ألا يتجاوز حجم الملف ${maxSizeMB}MB`\n : `File size must be less than ${maxSizeMB}MB`;\n }\n\n return null;\n}\n\nexport function validateImageFileWithName(\n file: FileLike & { name: string },\n maxSizeMB: number,\n locale: UploadLocale = 'en',\n): string | null {\n if (!file.type || !file.type.startsWith('image/')) {\n return locale === 'ar'\n ? `${file.name}: ليس ملف صورة صالحاً`\n : `${file.name}: Not a valid image file`;\n }\n\n const fileSizeMB = file.size / (1024 * 1024);\n if (fileSizeMB > maxSizeMB) {\n return locale === 'ar'\n ? `${file.name}: يجب ألا يتجاوز حجم الملف ${maxSizeMB}MB`\n : `${file.name}: File size must be less than ${maxSizeMB}MB`;\n }\n\n return null;\n}\n\nexport function validateMultipleFiles(\n files: Array<FileLike & { name: string }>,\n maxSizeMB: number,\n currentCount: number,\n maxImages: number,\n locale: UploadLocale = 'en',\n): string | null {\n if (currentCount + files.length > maxImages) {\n return locale === 'ar'\n ? `يمكن رفع ${maxImages} صورة فقط. المتبقي: ${maxImages - currentCount}.`\n : `Can only upload ${maxImages} images. ${maxImages - currentCount} remaining.`;\n }\n\n const oversizedFiles: string[] = [];\n for (const file of files) {\n const fileSizeMB = file.size / (1024 * 1024);\n if (fileSizeMB > maxSizeMB) {\n oversizedFiles.push(file.name);\n }\n }\n\n if (oversizedFiles.length > 0) {\n if (locale === 'ar') {\n return `الملفات التالية أكبر من الحد المسموح (${maxSizeMB}MB): ${oversizedFiles.join(', ')}`;\n }\n return `The following file${\n oversizedFiles.length > 1 ? 's are' : ' is'\n } too large (max ${maxSizeMB}MB): ${oversizedFiles.join(', ')}`;\n }\n\n return null;\n}\n","import crypto from 'node:crypto';\nimport type { ImageOutputFormat } from '../../types';\nimport type {\n GeneratedStorageTarget,\n StoragePathContext,\n StoragePathGenerator,\n} from './types';\n\nexport function formatToExtension(format: ImageOutputFormat): string {\n switch (format) {\n case 'svg':\n return 'svg';\n case 'png':\n return 'png';\n case 'webp':\n return 'webp';\n case 'jpeg':\n return 'jpg';\n default:\n return 'avif';\n }\n}\n\nexport function sanitizeSegment(value: string): string {\n return value\n .replace(/\\\\/g, '/')\n .split('/')\n .map((part) => part.trim().replace(/[^a-zA-Z0-9._-]/g, '-'))\n .filter((part) => part && part !== '.' && part !== '..')\n .join('/');\n}\n\nexport function createDefaultPathGenerator(): StoragePathGenerator {\n let imageCounter = 0;\n\n return (ctx: StoragePathContext): GeneratedStorageTarget => {\n const cleanFolder = ctx.folder ? sanitizeSegment(ctx.folder) : '';\n\n if (ctx.customFilename?.trim()) {\n let cleanName = ctx.customFilename.replace(/^.*[\\\\/]/, '').trim();\n if (!cleanName.includes('.')) {\n cleanName = `${cleanName}.${ctx.extension}`;\n }\n cleanName = cleanName.replace(/[^a-zA-Z0-9._-]/g, '-');\n const fullPath = cleanFolder ? `${cleanFolder}/${cleanName}` : cleanName;\n return {\n bucket: ctx.bucket,\n path: fullPath,\n filename: cleanName,\n };\n }\n\n const date = new Date();\n const year = date.getFullYear();\n const month = String(date.getMonth() + 1).padStart(2, '0');\n const day = String(date.getDate()).padStart(2, '0');\n\n imageCounter = (imageCounter + 1) % 10000;\n const seq = String(imageCounter).padStart(4, '0');\n const timestamp = Date.now();\n const randomSuffix = crypto.randomUUID().split('-')[0];\n\n const prefix = sanitizeSegment(\n ctx.preset || cleanFolder.split('/')[0] || 'img',\n );\n const filename = `${prefix}-${year}${month}${day}-${seq}-${timestamp}-${randomSuffix}.${ctx.extension}`;\n const fullPath = cleanFolder\n ? `${cleanFolder}/${year}/${month}/${filename}`\n : `${year}/${month}/${filename}`;\n\n return {\n bucket: ctx.bucket,\n path: fullPath,\n filename,\n };\n };\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport type {\n StorageAdapter,\n StorageUploadResult,\n} from '../../storage/types';\nimport type {\n GeneratedStorageTarget,\n StoragePathContext,\n StoragePathGenerator,\n} from './types';\n\nexport interface UploadWithCollisionRetryParams {\n storage: StorageAdapter;\n buildPath: StoragePathGenerator;\n pathContext: StoragePathContext;\n data: Buffer | Uint8Array;\n contentType: string;\n maxRetries?: number;\n}\n\nexport interface UploadWithCollisionRetryResult {\n uploadResult: StorageUploadResult;\n storageTarget: GeneratedStorageTarget;\n}\n\n/**\n * Determines whether a storage error represents a filename or object collision.\n * Matches `already exists` or `EEXIST`, while strictly excluding `does not exist`\n * (e.g. non-existent buckets, directories, or missing keys).\n */\nexport function isCollisionError(e: unknown): boolean {\n if (!e) return false;\n\n const code =\n typeof e === 'object' && e !== null && 'code' in e\n ? String((e as { code: unknown }).code).toUpperCase()\n : '';\n\n if (code === 'EEXIST') {\n return true;\n }\n if (code === 'ENOENT') {\n return false;\n }\n\n const msg =\n e instanceof Error ? e.message.toLowerCase() : String(e).toLowerCase();\n\n // Strictly exclude non-existence errors (missing bucket, directory, key)\n if (\n msg.includes('does not exist') ||\n msg.includes(\"doesn't exist\") ||\n msg.includes('not exist') ||\n msg.includes('enoent')\n ) {\n return false;\n }\n\n // Match genuine collision indicators\n return (\n msg.includes('already exists') ||\n msg.includes('already_exists') ||\n msg.includes('eexist') ||\n msg.includes('file exists')\n );\n}\n\n/**\n * Uploads optimized image bytes to the storage backend with automatic filename\n * collision retries (or immediate `upsert: true` fallback when `customFilename` is set).\n */\nexport async function uploadWithCollisionRetry(\n params: UploadWithCollisionRetryParams,\n): Promise<UploadWithCollisionRetryResult> {\n const {\n storage,\n buildPath,\n pathContext,\n data,\n contentType,\n maxRetries = 3,\n } = params;\n\n let storageTarget = buildPath(pathContext);\n let uploadResult: StorageUploadResult | undefined;\n\n for (let attempt = 0; attempt < maxRetries; attempt++) {\n try {\n uploadResult = await storage.upload({\n bucket: storageTarget.bucket,\n path: storageTarget.path,\n data,\n contentType,\n upsert: Boolean(pathContext.customFilename),\n contentHash: pathContext.contentHash,\n metadata: pathContext.metadata,\n });\n break;\n } catch (e) {\n if (isCollisionError(e)) {\n if (pathContext.customFilename) {\n uploadResult = await storage.upload({\n bucket: storageTarget.bucket,\n path: storageTarget.path,\n data,\n contentType,\n upsert: true,\n contentHash: pathContext.contentHash,\n metadata: pathContext.metadata,\n });\n break;\n }\n storageTarget = buildPath({\n ...pathContext,\n customFilename: undefined,\n });\n continue;\n }\n throw e;\n }\n }\n\n if (!uploadResult) {\n throw new Error('Failed to upload image after multiple retries');\n }\n\n return { uploadResult, storageTarget };\n}\n\nexport interface MirrorBufferLocallyOptions {\n buffer: Buffer | Uint8Array;\n filename: string;\n fallbackUrl: string;\n mirrorDir?: string;\n publicUrlBase?: string;\n}\n\n/**\n * Mirrors an uploaded image buffer to a local directory when `mirrorDir` is configured.\n * Safely swallows read-only filesystem errors on serverless runtimes and resolves\n * `publicUrlBase` when local mirroring succeeds.\n */\nexport function mirrorBufferLocally(\n options: MirrorBufferLocallyOptions,\n): string {\n const { buffer, filename, fallbackUrl, mirrorDir, publicUrlBase } = options;\n if (!mirrorDir) {\n return fallbackUrl;\n }\n\n try {\n if (!fs.existsSync(mirrorDir)) {\n fs.mkdirSync(mirrorDir, { recursive: true });\n }\n fs.writeFileSync(path.join(mirrorDir, filename), buffer);\n if (publicUrlBase) {\n return `${publicUrlBase.replace(/\\/+$/, '')}/${filename}`;\n }\n } catch {\n // Safely ignored on read-only serverless filesystems\n }\n\n return fallbackUrl;\n}\n","import type {\n ImageUploadOptions,\n ImageUploadRecord,\n UploadedImageData,\n UploadPresetConfig,\n} from '../../types';\nimport {\n DEFAULT_ALLOWED_FORMATS,\n DEFAULT_IMAGE_DIMENSIONS,\n STANDARD_PRESETS,\n} from '../../types';\nimport { validateImageFileStrict } from '../../utils/validators';\nimport { UploadValidationError } from '../handler';\nimport { AsyncSemaphore } from '../semaphore';\nimport { processImageBuffer } from './bufferProcessor';\nimport {\n createDefaultPathGenerator,\n formatToExtension,\n} from './pathGenerator';\nimport type {\n ImageUploader,\n ImageUploaderOptions,\n InferredPresetKey,\n ProcessedImageBufferResult,\n ProcessImageBufferOptions,\n} from './types';\nimport { mirrorBufferLocally, uploadWithCollisionRetry } from './uploadRetry';\n\nexport function createImageUploader<\n TPresets extends Record<string, UploadPresetConfig> = Record<\n string,\n UploadPresetConfig\n >,\n>(\n options: ImageUploaderOptions<TPresets>,\n): ImageUploader<InferredPresetKey<TPresets>> {\n const {\n storage,\n defaultBucket = 'images',\n defaultFolder = '',\n defaultMaxSizeMB = 10,\n defaultAllowedFormats = DEFAULT_ALLOWED_FORMATS,\n defaultMaxDimensions = DEFAULT_IMAGE_DIMENSIONS,\n presets: customPresets,\n includeStandardPresets = true,\n pathGenerator,\n onUploadRecord,\n awaitRecordHook = false,\n concurrency = 2,\n optimizationTimeoutMs = 60000,\n blurTimeoutMs = 30000,\n includeBlurHash: defaultIncludeBlurHash = false,\n } = options;\n\n const mergedPresets: Record<string, UploadPresetConfig> = {\n ...(includeStandardPresets ? STANDARD_PRESETS : {}),\n ...(customPresets || {}),\n };\n\n const semaphore = new AsyncSemaphore(concurrency);\n const buildPath = pathGenerator || createDefaultPathGenerator();\n\n const resolvePreset = (\n presetName?: string,\n ): UploadPresetConfig | undefined =>\n presetName ? mergedPresets[presetName] : undefined;\n\n return {\n resolvePreset,\n\n async processBuffer(\n buffer: Buffer,\n procOptions: ProcessImageBufferOptions = {},\n ): Promise<ProcessedImageBufferResult> {\n return semaphore.run(() =>\n processImageBuffer(buffer, {\n maxDimensions: defaultMaxDimensions,\n optimizationTimeoutMs,\n blurTimeoutMs,\n includeBlurHash: defaultIncludeBlurHash,\n ...procOptions,\n }),\n );\n },\n\n async uploadImage(\n input,\n uploadOptions: ImageUploadOptions<InferredPresetKey<TPresets>> = {},\n ): Promise<UploadedImageData> {\n const presetConfig = resolvePreset(uploadOptions.preset);\n\n const bucket =\n uploadOptions.bucket || presetConfig?.bucket || defaultBucket;\n const folder =\n uploadOptions.folder ?? presetConfig?.folder ?? defaultFolder;\n const maxSizeMB =\n uploadOptions.maxSizeMB ??\n presetConfig?.maxSizeMB ??\n defaultMaxSizeMB;\n const allowedFormats =\n uploadOptions.allowedFormats ??\n presetConfig?.allowedFormats ??\n defaultAllowedFormats;\n const maxDimensions =\n uploadOptions.maxDimensions ??\n presetConfig?.maxDimensions ??\n defaultMaxDimensions;\n const outputFormat =\n uploadOptions.outputFormat ?? presetConfig?.outputFormat;\n const quality = uploadOptions.quality ?? presetConfig?.quality;\n const includeBlurHash =\n uploadOptions.includeBlurHash ??\n presetConfig?.includeBlurHash ??\n defaultIncludeBlurHash;\n\n const isWebFile = typeof (input as File).arrayBuffer === 'function';\n const fileType = input.type;\n const originalName = input.name;\n const fileSize = isWebFile\n ? (input as File).size\n : ((input as { size?: number; buffer: Buffer }).size ??\n (input as { buffer: Buffer }).buffer.length);\n\n const validation = validateImageFileStrict(\n { size: fileSize, type: fileType },\n maxSizeMB,\n allowedFormats,\n );\n if (!validation.valid) {\n throw new UploadValidationError(validation.error!);\n }\n\n try {\n const originalBuffer = isWebFile\n ? Buffer.from(await (input as File).arrayBuffer())\n : (input as { buffer: Buffer }).buffer;\n\n const { optimized, blurData, contentHash, originalSize } =\n await semaphore.run(() =>\n processImageBuffer(originalBuffer, {\n maxDimensions,\n outputFormat,\n quality,\n includeBlurHash,\n optimizationTimeoutMs,\n blurTimeoutMs,\n }),\n );\n\n const mainFormat = optimized.format;\n const extension = formatToExtension(mainFormat);\n const mainContentType =\n mainFormat === 'svg' ? 'image/svg+xml' : `image/${mainFormat}`;\n\n const { uploadResult, storageTarget } = await uploadWithCollisionRetry({\n storage,\n buildPath,\n pathContext: {\n bucket,\n folder,\n preset: uploadOptions.preset,\n format: mainFormat,\n extension,\n customFilename: uploadOptions.customFilename,\n contentHash,\n originalName,\n metadata: uploadOptions.metadata,\n },\n data: optimized.buffer,\n contentType: mainContentType,\n });\n\n const resolvedUrl = mirrorBufferLocally({\n buffer: optimized.buffer,\n filename: storageTarget.filename,\n fallbackUrl: uploadResult.url,\n mirrorDir: presetConfig?.mirrorDir,\n publicUrlBase: presetConfig?.publicUrlBase,\n });\n\n const resolvedQuality = quality ?? 85;\n const result: UploadedImageData = {\n url: resolvedUrl,\n blurDataUrl: blurData.dataURL,\n blurColor: blurData.color,\n ...(blurData.blurHash && { blurHash: blurData.blurHash }),\n altText: uploadOptions.altText || '',\n width: optimized.width,\n height: optimized.height,\n format: optimized.format,\n size: optimized.size,\n originalSize,\n contentHash,\n storagePath: uploadResult.path,\n bucket: storageTarget.bucket,\n ...(uploadOptions.preset && { preset: uploadOptions.preset }),\n ...(folder && { folder }),\n ...(uploadOptions.metadata && { metadata: uploadOptions.metadata }),\n uploadedAt: new Date().toISOString(),\n };\n\n if (onUploadRecord) {\n const record: ImageUploadRecord = {\n ...result,\n quality: resolvedQuality,\n };\n\n if (awaitRecordHook) {\n await onUploadRecord(record);\n } else {\n Promise.resolve(onUploadRecord(record)).catch(() => {\n // Non-blocking best-effort persistence\n });\n }\n }\n\n return result;\n } catch (error) {\n if (error instanceof UploadValidationError) {\n throw error;\n }\n throw new Error(\n `Image upload failed: ${\n error instanceof Error ? error.message : 'Unknown error'\n }`,\n );\n }\n },\n\n async deleteImage(targetPath: string, bucket?: string): Promise<void> {\n try {\n await storage.delete(bucket || defaultBucket, targetPath);\n } catch (error) {\n throw new Error(\n `Image deletion failed: ${\n error instanceof Error ? error.message : 'Unknown error'\n }`,\n );\n }\n },\n\n async deleteByUrl(url: string): Promise<boolean> {\n if (storage.deleteByUrl) {\n return storage.deleteByUrl(url);\n }\n return false;\n },\n };\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/server/optimization/types.ts","../src/server/security/sanitizeSvg.ts","../src/server/optimization/loadSharp.ts","../src/server/optimization/imageOptimizer.ts","../src/server/optimization/blurGenerator.ts","../src/server/optimization/colorHistogram.ts","../src/server/optimization/edgeColorExtractor.ts","../src/server/security/sniffFormat.ts","../src/server/semaphore.ts","../src/server/uploader/bufferProcessor.ts","../src/server/uploader/pathGenerator.ts","../src/server/uploader/uploadRetry.ts","../src/server/uploader/variantGenerator.ts","../src/server/uploader/createImageUploader.ts"],"sourcesContent":["import type {\n ExplicitOutputFormat,\n ImageDimensions,\n ImageOutputFormat,\n} from '../../types';\n\nexport interface OptimizedImageResult {\n buffer: Buffer;\n width: number;\n height: number;\n format: ImageOutputFormat;\n size: number;\n quality?: number;\n}\n\nexport interface BlurHashResult {\n dataURL: string;\n color: string;\n blurHash?: string;\n}\n\nexport interface OptimizeImageOptions {\n /** Max bounding box dimensions (fit: 'inside', withoutEnlargement: true). Defaults to 1920x1080. */\n maxDimensions?: ImageDimensions;\n /** Explicit output format; omit for smart size-guarded AVIF/WebP selection */\n outputFormat?: ExplicitOutputFormat;\n /** 1–100 compression quality. Defaults to smart photo/graphic heuristic (85–88). */\n quality?: number;\n /** Maximum input pixel count allowed by Sharp (defaults to 50 MP = 50,000,000) */\n limitInputPixels?: number;\n /** AVIF/WebP encoding effort (defaults to 6) */\n effort?: number;\n}\n\nexport const DEFAULT_LIMIT_INPUT_PIXELS = 50_000_000;\n\nexport interface GenerateBlurOptions {\n width?: number;\n fallbackWidth?: number;\n quality?: number;\n maxDataUrlChars?: number;\n includeBlurHash?: boolean;\n}\n\nexport type ColorSamplingMode = 'balanced' | 'edge';\nexport type EdgeKey = 'top' | 'right' | 'bottom' | 'left';\nexport type EdgeColorSet = Record<EdgeKey, string>;\n\nexport const PRIMARY_AVIF_EFFORT = 6;\nexport const RETRY_AVIF_EFFORT = 5;\n\nexport const BLUR_PLACEHOLDER_WIDTH = 128;\nexport const BLUR_PLACEHOLDER_FALLBACK_WIDTH = 96;\nexport const BLUR_PLACEHOLDER_QUALITY = 80;\nexport const BLUR_PLACEHOLDER_MAX_CHARS = 8000;\n\nexport const EDGE_COLOR_FALLBACK = '#6B7280';\nexport const EDGE_WHITE_FALLBACK = '#F9FAFB';\nexport const WHITE_DOMINANCE_RATIO = 1.35;\n","import { UploadValidationError } from '../handler/responses';\n\nexport const DEFAULT_MAX_SVG_BYTES = 1024 * 1024; // 1 MB\n\nconst FORBIDDEN_ELEMENTS = [\n 'script',\n 'foreignObject',\n 'iframe',\n 'embed',\n 'object',\n 'applet',\n 'meta',\n 'link',\n 'base',\n 'audio',\n 'video',\n 'canvas',\n 'animate',\n 'animateMotion',\n 'animateTransform',\n 'set',\n 'handler',\n 'listener',\n 'tbreak',\n];\n\nconst SAFE_NAMED_ENTITIES = new Set(['amp', 'lt', 'gt', 'quot', 'apos']);\n\nconst SAFE_HREF_FRAGMENT_RE = /^#[a-zA-Z0-9_.:-]+$/;\nconst SAFE_DATA_IMAGE_RE =\n /^data:image\\/(?:png|jpeg|webp);base64,[a-zA-Z0-9+/=\\s]+$/i;\n\nfunction stripControlAndSpace(str: string): string {\n let out = '';\n for (let i = 0; i < str.length; i++) {\n if (str.charCodeAt(i) > 0x20) out += str[i];\n }\n return out;\n}\n\nfunction decodeHtmlEntitiesForCheck(value: string): string {\n const decoded = value\n .replace(/&#x([0-9a-fA-F]+);?/g, (_, hex: string) =>\n String.fromCodePoint(Number.parseInt(hex, 16) || 0),\n )\n .replace(/&#(\\d+);?/g, (_, dec: string) =>\n String.fromCodePoint(Number.parseInt(dec, 10) || 0),\n );\n return stripControlAndSpace(decoded);\n}\n\nfunction isSafeSvgHref(rawValue: string): boolean {\n const trimmed = rawValue.trim();\n if (SAFE_HREF_FRAGMENT_RE.test(trimmed)) return true;\n const decoded = decodeHtmlEntitiesForCheck(trimmed);\n if (SAFE_HREF_FRAGMENT_RE.test(decoded)) return true;\n if (SAFE_DATA_IMAGE_RE.test(trimmed) && SAFE_DATA_IMAGE_RE.test(decoded)) {\n return true;\n }\n return false;\n}\n\nfunction sanitizeCssBlock(css: string): string {\n return css\n .replace(/@import\\b[^;{}]*(?:;|$)/gi, '')\n .replace(/expression\\s*\\([^)]*\\)/gi, '')\n .replace(/(?:javascript|vbscript|data)\\s*:[^;)\"']*/gi, '')\n .replace(/-moz-binding\\s*:[^;}\"']*/gi, '')\n .replace(/behavior\\s*:[^;}\"']*/gi, '')\n .replace(/url\\s*\\(\\s*(['\"]?)(.*?)\\1\\s*\\)/gi, (full, _q, target: string) => {\n const cleaned = decodeHtmlEntitiesForCheck(target.trim());\n return SAFE_HREF_FRAGMENT_RE.test(cleaned) ? full : 'none';\n });\n}\n\nfunction sanitizeTagAttributes(attrs: string): string {\n const attrRe =\n /([a-zA-Z_:][\\w:.-]*)\\s*(?:=\\s*(?:\"([^\"]*)\"|'([^']*)'|([^\\s\"'=<>`]+)))?/g;\n\n const kept: string[] = [];\n for (const match of attrs.matchAll(attrRe)) {\n const rawName = match[1];\n const lowerName = rawName.toLowerCase();\n const localName = lowerName.includes(':')\n ? lowerName.split(':')[1]\n : lowerName;\n const rawValue = match[2] ?? match[3] ?? match[4] ?? '';\n\n // Strip all event handler attributes (onload, onclick, onbegin, etc.)\n if (lowerName.startsWith('on') || localName.startsWith('on')) {\n continue;\n }\n\n // Check href / xlink:href / src / action / formaction / data\n if (\n localName === 'href' ||\n lowerName === 'xlink:href' ||\n localName === 'src' ||\n localName === 'action' ||\n localName === 'formaction' ||\n localName === 'data'\n ) {\n if (!isSafeSvgHref(rawValue)) {\n continue;\n }\n const escaped = rawValue.replace(/\"/g, '"');\n kept.push(`${rawName}=\"${escaped}\"`);\n continue;\n }\n\n if (localName === 'style') {\n const cleanStyle = sanitizeCssBlock(rawValue).replace(/\"/g, \"'\");\n if (cleanStyle.trim()) {\n kept.push(`style=\"${cleanStyle}\"`);\n }\n continue;\n }\n\n // Reject javascript: / data: / vbscript: inside any other attribute (e.g. fill=\"url(https://...)\")\n const decodedVal = decodeHtmlEntitiesForCheck(rawValue).toLowerCase();\n if (\n decodedVal.includes('javascript:') ||\n decodedVal.includes('vbscript:') ||\n decodedVal.includes('data:text/') ||\n decodedVal.includes('data:image/svg')\n ) {\n continue;\n }\n\n if (/url\\s*\\(/i.test(rawValue)) {\n const sanitizedUrlAttr = sanitizeCssBlock(rawValue).replace(/\"/g, '"');\n kept.push(`${rawName}=\"${sanitizedUrlAttr}\"`);\n continue;\n }\n\n if (match[2] !== undefined || match[3] !== undefined || match[4] !== undefined) {\n kept.push(`${rawName}=\"${rawValue.replace(/\"/g, '"')}\"`);\n } else {\n kept.push(rawName);\n }\n }\n\n return kept.length > 0 ? ` ${kept.join(' ')}` : '';\n}\n\nexport interface SanitizeSvgOptions {\n maxBytes?: number;\n}\n\n/**\n * Dependency-free SVG sanitizer.\n * Strips `<script>`, `<foreignObject>`, `<iframe|embed|object>`, `<!DOCTYPE>`/`<!ENTITY>`,\n * custom XML entities, `on*` event attributes, and non-fragment / non-raster-data `href`s.\n */\nexport function sanitizeSvg(\n input: Buffer | string,\n options: SanitizeSvgOptions = {},\n): Buffer {\n const maxBytes = options.maxBytes ?? DEFAULT_MAX_SVG_BYTES;\n const byteLength =\n typeof input === 'string' ? Buffer.byteLength(input, 'utf8') : input.length;\n\n if (byteLength > maxBytes) {\n throw new UploadValidationError(\n `SVG file size (${byteLength} bytes) exceeds maximum allowed SVG size of ${maxBytes} bytes`,\n );\n }\n\n let svg = typeof input === 'string' ? input : input.toString('utf8');\n svg = svg.replace(/^\\uFEFF/, '');\n\n // Strip <!DOCTYPE ... [ ... ]> and standalone <!ENTITY ...>\n svg = svg.replace(/<!DOCTYPE[^[>]*(?:\\[[\\s\\S]*?\\]\\s*)?>/gi, '');\n svg = svg.replace(/<!ENTITY[\\s\\S]*?>/gi, '');\n\n // Strip comments, CDATA, and non-xml processing instructions\n svg = svg.replace(/<!--[\\s\\S]*?-->/g, '');\n svg = svg.replace(/<!\\[CDATA\\[[\\s\\S]*?\\]\\]>/g, '');\n svg = svg.replace(/<\\?(?!xml\\b)[\\s\\S]*?\\?>/gi, '');\n\n // Strip custom / external XML entity references like &xxe;\n svg = svg.replace(/&([a-zA-Z_][\\w.-]*);/g, (full, name: string) =>\n SAFE_NAMED_ENTITIES.has(name) ? full : '',\n );\n\n // Iteratively strip forbidden elements and their inner subtrees\n const tagPattern = FORBIDDEN_ELEMENTS.join('|');\n const pairedRe = new RegExp(\n `<\\\\s*(?:[a-zA-Z0-9_-]+:)?(?:${tagPattern})\\\\b[^>]*>[\\\\s\\\\S]*?<\\\\s*\\\\/\\\\s*(?:[a-zA-Z0-9_-]+:)?(?:${tagPattern})\\\\s*>`,\n 'gi',\n );\n const singleRe = new RegExp(\n `<\\\\s*\\\\/?\\\\s*(?:[a-zA-Z0-9_-]+:)?(?:${tagPattern})\\\\b[^>]*\\\\/?>`,\n 'gi',\n );\n const htmlNamespaceRe =\n /<\\s*\\/?\\s*(?:xhtml|html):[a-zA-Z0-9_-]+\\b[^>]*\\/?>/gi;\n\n for (let pass = 0; pass < 4; pass++) {\n const prev = svg;\n svg = svg\n .replace(pairedRe, '')\n .replace(singleRe, '')\n .replace(htmlNamespaceRe, '');\n if (svg === prev) break;\n }\n\n // Sanitize <style> blocks\n svg = svg.replace(\n /(<\\s*style\\b[^>]*>)([\\s\\S]*?)(<\\s*\\/\\s*style\\s*>)/gi,\n (_m, open: string, body: string, close: string) =>\n `${open}${sanitizeCssBlock(body)}${close}`,\n );\n\n // Sanitize attributes on every remaining opening/self-closing tag\n svg = svg.replace(\n /<([a-zA-Z_:][\\w:.-]*)(\\s[^<>]*?)?(\\s*\\/?)>/g,\n (_full, tagName: string, attrs: string | undefined, selfClose: string) => {\n const cleanAttrs = attrs ? sanitizeTagAttributes(attrs) : '';\n return `<${tagName}${cleanAttrs}${selfClose}>`;\n },\n );\n\n if (!/<svg[\\s>/]/i.test(svg)) {\n throw new UploadValidationError(\n 'Invalid SVG: missing root <svg> element after sanitization',\n );\n }\n\n // Post-sanitization safety verification\n if (\n pairedRe.test(svg) ||\n singleRe.test(svg) ||\n /<!(?:DOCTYPE|ENTITY)\\b/i.test(svg) ||\n /\\bon[a-z]+\\s*=/i.test(svg) ||\n /(?:javascript|vbscript)\\s*:/i.test(svg)\n ) {\n throw new UploadValidationError(\n 'Invalid SVG: unsafe content remained after sanitization',\n );\n }\n\n return Buffer.from(svg.trim(), 'utf8');\n}\n","/**\n * Lazy loaders for the optional native peer dependencies (`sharp`,\n * `lqip-modern`). They are resolved on first use via dynamic `import()` so\n * that merely importing `img-upload-kit/server` (or bundling it) never\n * requires the native binaries to be present, and so that missing peers\n * produce an actionable error instead of an opaque module-resolution crash.\n */\nimport type LqipDefault from 'lqip-modern';\nimport type SharpDefault from 'sharp';\n\nexport type SharpFactory = typeof SharpDefault;\nexport type LqipFn = typeof LqipDefault;\n\nexport const SHARP_MISSING_MESSAGE =\n 'img-upload-kit/server requires `sharp` — run `npm i sharp`';\nexport const LQIP_MISSING_MESSAGE =\n 'img-upload-kit/server requires `lqip-modern` for LQIP generation — run `npm i lqip-modern`';\n\nlet sharpPromise: Promise<SharpFactory> | null = null;\nlet lqipPromise: Promise<LqipFn> | null = null;\n\nfunction unwrapDefault<T>(mod: unknown): T {\n const record = mod as { default?: unknown };\n return (record && record.default !== undefined ? record.default : mod) as T;\n}\n\n/** Resolves the `sharp` factory, throwing a descriptive error if it is not installed. */\nexport function loadSharp(): Promise<SharpFactory> {\n if (!sharpPromise) {\n sharpPromise = import('sharp').then(\n (mod) => unwrapDefault<SharpFactory>(mod),\n (error: unknown) => {\n sharpPromise = null;\n throw new Error(SHARP_MISSING_MESSAGE, { cause: error });\n },\n );\n }\n return sharpPromise;\n}\n\n/** Resolves the `lqip-modern` function, throwing a descriptive error if it is not installed. */\nexport function loadLqip(): Promise<LqipFn> {\n if (!lqipPromise) {\n lqipPromise = import('lqip-modern').then(\n (mod) => unwrapDefault<LqipFn>(mod),\n (error: unknown) => {\n lqipPromise = null;\n throw new Error(LQIP_MISSING_MESSAGE, { cause: error });\n },\n );\n }\n return lqipPromise;\n}\n","import { DEFAULT_IMAGE_DIMENSIONS } from '../../types';\nimport { UploadValidationError } from '../handler/responses';\nimport { sanitizeSvg } from '../security/sanitizeSvg';\nimport { loadSharp } from './loadSharp';\nimport {\n DEFAULT_LIMIT_INPUT_PIXELS,\n type OptimizedImageResult,\n type OptimizeImageOptions,\n PRIMARY_AVIF_EFFORT,\n RETRY_AVIF_EFFORT,\n} from './types';\n\nconst PASSTHROUGH_FORMATS = new Set(['jpeg', 'png', 'webp', 'avif']);\n\nfunction extractSvgDimensions(\n svgText: string,\n metaWidth?: number,\n metaHeight?: number,\n): { width: number; height: number } {\n let width = metaWidth;\n let height = metaHeight;\n\n if (!width || !height) {\n const svgTagMatch = svgText.match(/<svg\\b[^>]*>/i);\n if (svgTagMatch) {\n const tag = svgTagMatch[0];\n const wMatch = tag.match(/\\bwidth\\s*=\\s*[\"']\\s*([\\d.]+)(?:px)?\\s*[\"']/i);\n const hMatch = tag.match(/\\bheight\\s*=\\s*[\"']\\s*([\\d.]+)(?:px)?\\s*[\"']/i);\n if (!width && wMatch) width = Math.round(parseFloat(wMatch[1]));\n if (!height && hMatch) height = Math.round(parseFloat(hMatch[1]));\n }\n }\n\n if (!width || !height) {\n const viewBoxMatch = svgText.match(\n /viewBox\\s*=\\s*[\"']\\s*([\\d.-]+)[\\s,]+([\\d.-]+)[\\s,]+([\\d.-]+)[\\s,]+([\\d.-]+)\\s*[\"']/i,\n );\n if (viewBoxMatch) {\n if (!width) width = Math.round(parseFloat(viewBoxMatch[3]));\n if (!height) height = Math.round(parseFloat(viewBoxMatch[4]));\n }\n }\n\n return {\n width: width && width > 0 ? width : 600,\n height: height && height > 0 ? height : 600,\n };\n}\n\nexport async function optimizeImage(\n buffer: Buffer,\n options: OptimizeImageOptions = {},\n): Promise<OptimizedImageResult> {\n const sharp = await loadSharp();\n const maxDimensions = options.maxDimensions || DEFAULT_IMAGE_DIMENSIONS;\n const { outputFormat, quality } = options;\n const limitInputPixels =\n options.limitInputPixels ?? DEFAULT_LIMIT_INPUT_PIXELS;\n const primaryEffort = options.effort ?? PRIMARY_AVIF_EFFORT;\n const retryEffort =\n options.effort !== undefined\n ? Math.max(1, options.effort - 1)\n : RETRY_AVIF_EFFORT;\n\n let pipeline = sharp(buffer, {\n failOn: 'error',\n limitInputPixels,\n }).rotate();\n\n let metadata;\n try {\n metadata = await pipeline.metadata();\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n if (\n msg.toLowerCase().includes('pixel limit') ||\n msg.toLowerCase().includes('exceeds') ||\n msg.toLowerCase().includes('unsupported image format')\n ) {\n throw new UploadValidationError(msg);\n }\n throw err;\n }\n const originalFormat = metadata.format;\n\n if (originalFormat === 'svg') {\n const sanitizedBuffer = sanitizeSvg(buffer);\n const svgText = sanitizedBuffer.toString('utf8');\n const dims = extractSvgDimensions(svgText, metadata.width, metadata.height);\n\n return {\n buffer: sanitizedBuffer,\n width: dims.width,\n height: dims.height,\n format: 'svg',\n size: sanitizedBuffer.length,\n ...(quality !== undefined ? { quality } : {}),\n };\n }\n\n const isPhoto =\n originalFormat === 'jpeg' ||\n Boolean(metadata.density && metadata.density > 150);\n\n let baseQuality = quality ?? (isPhoto ? 85 : 88);\n baseQuality = Math.max(1, Math.min(100, baseQuality));\n\n pipeline = pipeline.resize(maxDimensions.width, maxDimensions.height, {\n fit: 'inside',\n withoutEnlargement: true,\n kernel: 'lanczos3',\n });\n\n if (\n outputFormat === 'jpeg' ||\n outputFormat === 'png' ||\n outputFormat === 'webp'\n ) {\n let cloned = pipeline.clone();\n if (outputFormat === 'jpeg') {\n cloned = cloned.jpeg({ quality: baseQuality, mozjpeg: true });\n } else if (outputFormat === 'png') {\n cloned = cloned.png();\n } else if (outputFormat === 'webp') {\n cloned = cloned.webp({ quality: baseQuality, effort: 4 });\n }\n\n const outputBuffer = await cloned.toBuffer({ resolveWithObject: true });\n\n return {\n buffer: outputBuffer.data,\n width: outputBuffer.info.width || maxDimensions.width,\n height: outputBuffer.info.height || maxDimensions.height,\n format: outputFormat,\n size: outputBuffer.info.size,\n quality: baseQuality,\n };\n }\n\n const avifBuffer = await pipeline\n .clone()\n .avif({\n quality: baseQuality,\n effort: primaryEffort,\n chromaSubsampling: '4:2:0',\n bitdepth: 8,\n })\n .toBuffer({ resolveWithObject: true });\n\n const avifSize = avifBuffer.info.size;\n const originalSize = buffer.length;\n\n if (avifSize <= originalSize || outputFormat === 'avif') {\n return {\n buffer: avifBuffer.data,\n width: avifBuffer.info.width || maxDimensions.width,\n height: avifBuffer.info.height || maxDimensions.height,\n format: 'avif',\n size: avifSize,\n quality: baseQuality,\n };\n }\n\n const scaledQuality = Math.max(\n 40,\n Math.round(baseQuality * Math.sqrt(originalSize / avifSize)),\n );\n\n const avifRetry = await pipeline\n .clone()\n .avif({\n quality: scaledQuality,\n effort: retryEffort,\n chromaSubsampling: '4:2:0',\n bitdepth: 8,\n })\n .toBuffer({ resolveWithObject: true });\n\n if (avifRetry.info.size <= originalSize) {\n return {\n buffer: avifRetry.data,\n width: avifRetry.info.width || maxDimensions.width,\n height: avifRetry.info.height || maxDimensions.height,\n format: 'avif',\n size: avifRetry.info.size,\n quality: scaledQuality,\n };\n }\n\n const isRotated90 =\n typeof metadata.orientation === 'number' &&\n metadata.orientation >= 5 &&\n metadata.orientation <= 8;\n const orientedWidth = isRotated90 ? metadata.height : metadata.width;\n const orientedHeight = isRotated90 ? metadata.width : metadata.height;\n\n const wasDimensionCapped =\n (orientedWidth ?? 0) > maxDimensions.width ||\n (orientedHeight ?? 0) > maxDimensions.height;\n\n if (!wasDimensionCapped && PASSTHROUGH_FORMATS.has(originalFormat ?? '')) {\n const srcFmt = originalFormat as 'jpeg' | 'png' | 'webp' | 'avif';\n let passthrough = pipeline.clone();\n if (srcFmt === 'jpeg') {\n passthrough = passthrough.jpeg({ quality: baseQuality, mozjpeg: true });\n } else if (srcFmt === 'png') {\n passthrough = passthrough.png({ compressionLevel: 9 });\n } else if (srcFmt === 'webp') {\n passthrough = passthrough.webp({ quality: baseQuality, effort: 4 });\n } else {\n passthrough = passthrough.avif({\n quality: baseQuality,\n effort: retryEffort,\n });\n }\n\n let passthroughOut = await passthrough.toBuffer({ resolveWithObject: true });\n if (srcFmt === 'jpeg' && passthroughOut.info.size > originalSize) {\n passthroughOut = await pipeline\n .clone()\n .jpeg({ quality: 10 })\n .toBuffer({ resolveWithObject: true });\n }\n\n return {\n buffer: passthroughOut.data,\n width: passthroughOut.info.width || orientedWidth || maxDimensions.width,\n height:\n passthroughOut.info.height || orientedHeight || maxDimensions.height,\n format: srcFmt,\n size: passthroughOut.info.size,\n quality: baseQuality,\n };\n }\n\n const webpBuffer = await pipeline\n .clone()\n .webp({ quality: baseQuality, effort: 6, smartSubsample: true })\n .toBuffer({ resolveWithObject: true });\n\n const useWebP = webpBuffer.info.size <= avifRetry.info.size;\n const winner = useWebP\n ? {\n buf: webpBuffer.data,\n fmt: 'webp' as const,\n sz: webpBuffer.info.size,\n w: webpBuffer.info.width,\n h: webpBuffer.info.height,\n q: baseQuality,\n }\n : {\n buf: avifRetry.data,\n fmt: 'avif' as const,\n sz: avifRetry.info.size,\n w: avifRetry.info.width,\n h: avifRetry.info.height,\n q: scaledQuality,\n };\n\n return {\n buffer: winner.buf,\n width: winner.w || maxDimensions.width,\n height: winner.h || maxDimensions.height,\n format: winner.fmt,\n size: winner.sz,\n quality: winner.q,\n };\n}\n","import { encode as encodeBlurHash } from 'blurhash';\nimport {\n blendEdgeColors,\n computeEdgeColorSet,\n extractEdgeColorsFromBuffer,\n} from './edgeColorExtractor';\nimport { loadSharp } from './loadSharp';\nimport {\n BLUR_PLACEHOLDER_FALLBACK_WIDTH,\n BLUR_PLACEHOLDER_MAX_CHARS,\n BLUR_PLACEHOLDER_QUALITY,\n BLUR_PLACEHOLDER_WIDTH,\n type BlurHashResult,\n type GenerateBlurOptions,\n} from './types';\n\nfunction encodeRawBlurHash(\n data: Buffer,\n width: number,\n height: number,\n componentX: number = 4,\n componentY: number = 3,\n): string {\n const clampedX = Math.max(1, Math.min(Math.round(componentX), width, 9));\n const clampedY = Math.max(1, Math.min(Math.round(componentY), height, 9));\n return encodeBlurHash(\n new Uint8ClampedArray(data),\n width,\n height,\n clampedX,\n clampedY,\n );\n}\n\nexport async function encodeBlurHashString(\n buffer: Buffer,\n componentX: number = 4,\n componentY: number = 3,\n): Promise<string> {\n const sharp = await loadSharp();\n const { data, info } = await sharp(buffer)\n .resize(32, 32, { fit: 'inside' })\n .ensureAlpha()\n .raw()\n .toBuffer({ resolveWithObject: true });\n\n return encodeRawBlurHash(\n data,\n info.width,\n info.height,\n componentX,\n componentY,\n );\n}\n\nexport async function generateBlurPlaceholder(\n buffer: Buffer,\n options: GenerateBlurOptions = {},\n): Promise<BlurHashResult> {\n const targetWidth = options.width ?? BLUR_PLACEHOLDER_WIDTH;\n const fallbackWidth =\n options.fallbackWidth ?? BLUR_PLACEHOLDER_FALLBACK_WIDTH;\n const quality = options.quality ?? BLUR_PLACEHOLDER_QUALITY;\n const maxChars = options.maxDataUrlChars ?? BLUR_PLACEHOLDER_MAX_CHARS;\n const sharp = await loadSharp();\n\n try {\n let processBuffer = buffer;\n const isSvg = /<svg[\\s>]/i.test(buffer.toString('utf8', 0, 1024));\n if (isSvg) {\n const normalizedSvg = buffer\n .toString('utf8')\n .replace(/<svg\\b/gi, '<svg')\n .replace(/<\\/svg\\s*>/gi, '</svg>');\n processBuffer = Buffer.from(normalizedSvg, 'utf8');\n }\n\n const baseSize = Math.max(targetWidth, 128);\n const rawSample = await sharp(processBuffer)\n .rotate()\n .resize(baseSize, baseSize, { fit: 'inside', withoutEnlargement: true })\n .ensureAlpha()\n .raw()\n .toBuffer({ resolveWithObject: true });\n\n const rawInput = {\n raw: {\n width: rawSample.info.width,\n height: rawSample.info.height,\n channels: 4 as const,\n },\n };\n\n const buildPlaceholderDataUrl = async (width: number): Promise<string> => {\n const webpBuffer = await sharp(rawSample.data, rawInput)\n .resize(width, width, { fit: 'inside', withoutEnlargement: true })\n .webp({ quality, effort: 6, smartSubsample: true })\n .toBuffer();\n return `data:image/webp;base64,${webpBuffer.toString('base64')}`;\n };\n\n let dataURL = await buildPlaceholderDataUrl(targetWidth);\n if (dataURL.length > maxChars) {\n dataURL = await buildPlaceholderDataUrl(fallbackWidth);\n }\n\n const edgeColors = computeEdgeColorSet(\n rawSample.data,\n rawSample.info.width,\n rawSample.info.height,\n );\n const color = blendEdgeColors(edgeColors);\n\n let blurHash: string | undefined;\n if (options.includeBlurHash) {\n try {\n const hashSample =\n rawSample.info.width <= 32 && rawSample.info.height <= 32\n ? rawSample\n : await sharp(rawSample.data, rawInput)\n .resize(32, 32, { fit: 'inside' })\n .ensureAlpha()\n .raw()\n .toBuffer({ resolveWithObject: true });\n blurHash = encodeRawBlurHash(\n hashSample.data,\n hashSample.info.width,\n hashSample.info.height,\n );\n } catch {\n blurHash = undefined;\n }\n }\n\n return {\n dataURL,\n color,\n ...(blurHash && { blurHash }),\n };\n } catch {\n return generateFallbackBlur(buffer, options.includeBlurHash);\n }\n}\n\nexport const generateBlurHash = generateBlurPlaceholder;\n\nasync function generateFallbackBlur(\n buffer: Buffer,\n includeBlurHash?: boolean,\n): Promise<BlurHashResult> {\n const sharp = await loadSharp();\n const tinyBuffer = await sharp(buffer)\n .resize(64, 64, { fit: 'cover', kernel: 'lanczos3' })\n .blur(1.0)\n .webp({\n quality: 75,\n effort: 6,\n smartSubsample: false,\n })\n .toBuffer();\n\n const dataURL = `data:image/webp;base64,${tinyBuffer.toString('base64')}`;\n const edgeColors = await extractEdgeColorsFromBuffer(buffer);\n const color = blendEdgeColors(edgeColors);\n\n let blurHash: string | undefined;\n if (includeBlurHash) {\n try {\n blurHash = await encodeBlurHashString(tinyBuffer);\n } catch {\n blurHash = undefined;\n }\n }\n\n return { dataURL, color, ...(blurHash && { blurHash }) };\n}\n","import { rgbToHex } from '../../utils/color';\nimport {\n type ColorSamplingMode,\n EDGE_COLOR_FALLBACK,\n EDGE_WHITE_FALLBACK,\n WHITE_DOMINANCE_RATIO,\n} from './types';\nimport { loadSharp } from './loadSharp';\n\nexport async function extractEnhancedColorFromBuffer(\n buffer: Buffer,\n mode: ColorSamplingMode = 'balanced',\n): Promise<string> {\n const sharp = await loadSharp();\n try {\n const metadata = await sharp(buffer).metadata();\n const maxSize = 400;\n const needsResize =\n metadata.width &&\n metadata.height &&\n (metadata.width > maxSize || metadata.height > maxSize);\n\n if (needsResize) {\n const resized = await sharp(buffer)\n .resize(maxSize, maxSize, {\n fit: 'inside',\n kernel: 'lanczos3',\n withoutEnlargement: true,\n })\n .ensureAlpha()\n .raw()\n .toBuffer({ resolveWithObject: true });\n\n return extractDominantColorHistogramAdvanced(\n resized.data,\n resized.info.width,\n resized.info.height,\n mode,\n );\n }\n\n const raw = await sharp(buffer)\n .ensureAlpha()\n .raw()\n .toBuffer({ resolveWithObject: true });\n\n return extractDominantColorHistogramAdvanced(\n raw.data,\n raw.info.width,\n raw.info.height,\n mode,\n );\n } catch {\n const stats = await sharp(buffer)\n .resize(64, 64, { fit: 'cover', kernel: 'lanczos3' })\n .ensureAlpha()\n .raw()\n .toBuffer({ resolveWithObject: true });\n return extractDominantColorHistogram(stats.data);\n }\n}\n\nfunction extractDominantColorHistogramAdvanced(\n data: Buffer,\n width: number,\n height: number,\n mode: ColorSamplingMode,\n): string {\n const colorMap = new Map<string, number>();\n const bucketSize = 16;\n\n const centerWeight = 1.5;\n const centerX = width / 2 || 1;\n const centerY = height / 2 || 1;\n let whiteWeight = 0;\n\n for (let i = 0; i < data.length; i += 4) {\n const alpha = data[i + 3];\n if (alpha !== undefined && alpha < 8) continue;\n\n const r = data[i];\n const g = data[i + 1];\n const b = data[i + 2];\n const brightness = (r + g + b) / 3;\n if (brightness < 10) continue;\n\n const pixelIndex = i / 4;\n const x = pixelIndex % width;\n const y = Math.floor(pixelIndex / width);\n const dx = (x - centerX) / centerX;\n const dy = (y - centerY) / centerY;\n const distanceFromCenter = Math.sqrt(dx * dx + dy * dy);\n let weight = 1.0;\n\n if (mode === 'edge') {\n const edgeThicknessX = Math.max(1, Math.floor(width * 0.12));\n const edgeThicknessY = Math.max(1, Math.floor(height * 0.12));\n\n const onLeftEdge = x < edgeThicknessX;\n const onRightEdge = x >= width - edgeThicknessX;\n const onTopEdge = y < edgeThicknessY;\n const onBottomEdge = y >= height - edgeThicknessY;\n\n if (!(onLeftEdge || onRightEdge || onTopEdge || onBottomEdge)) {\n continue;\n }\n\n const distanceToNearestEdge = Math.min(\n x,\n y,\n width - 1 - x,\n height - 1 - y,\n );\n const maxEdgeDistance = Math.max(edgeThicknessX, edgeThicknessY) || 1;\n const edgeFactor = 1 - distanceToNearestEdge / maxEdgeDistance;\n weight = 1 + edgeFactor * 3;\n } else {\n weight = distanceFromCenter < 0.5 ? centerWeight : 1.0;\n }\n\n const isNearWhite = r >= 245 && g >= 245 && b >= 245;\n if (isNearWhite) {\n whiteWeight += weight;\n continue;\n }\n\n const bucketR = Math.floor(r / bucketSize) * bucketSize;\n const bucketG = Math.floor(g / bucketSize) * bucketSize;\n const bucketB = Math.floor(b / bucketSize) * bucketSize;\n\n const key = `${bucketR},${bucketG},${bucketB}`;\n colorMap.set(key, (colorMap.get(key) || 0) + weight);\n }\n\n if (!colorMap.size) {\n return whiteWeight > 0 ? EDGE_WHITE_FALLBACK : EDGE_COLOR_FALLBACK;\n }\n\n let maxCount = 0;\n let dominantColor = '64,64,80';\n let totalColorWeight = 0;\n\n colorMap.forEach((count, color) => {\n totalColorWeight += count;\n if (count > maxCount) {\n maxCount = count;\n dominantColor = color;\n }\n });\n\n const whiteDominates =\n whiteWeight > 0 && whiteWeight >= totalColorWeight * WHITE_DOMINANCE_RATIO;\n if (whiteDominates) {\n return EDGE_WHITE_FALLBACK;\n }\n\n const [r, g, b] = dominantColor.split(',').map(Number);\n return rgbToHex(r, g, b);\n}\n\nfunction extractDominantColorHistogram(data: Buffer): string {\n const colorMap = new Map<string, number>();\n const bucketSize = 16;\n let whiteWeight = 0;\n\n for (let i = 0; i < data.length; i += 4) {\n const alpha = data[i + 3];\n if (alpha !== undefined && alpha < 8) continue;\n\n const r = Math.floor(data[i] / bucketSize) * bucketSize;\n const g = Math.floor(data[i + 1] / bucketSize) * bucketSize;\n const b = Math.floor(data[i + 2] / bucketSize) * bucketSize;\n\n if (r >= 240 && g >= 240 && b >= 240) {\n whiteWeight += 1;\n continue;\n }\n\n const key = `${r},${g},${b}`;\n colorMap.set(key, (colorMap.get(key) || 0) + 1);\n }\n\n if (!colorMap.size) {\n return whiteWeight > 0 ? EDGE_WHITE_FALLBACK : EDGE_COLOR_FALLBACK;\n }\n\n let maxCount = 0;\n let dominantColor = '64,64,80';\n let totalColorWeight = 0;\n\n colorMap.forEach((count, color) => {\n totalColorWeight += count;\n if (count > maxCount) {\n maxCount = count;\n dominantColor = color;\n }\n });\n\n const whiteDominates =\n whiteWeight > 0 && whiteWeight >= totalColorWeight * WHITE_DOMINANCE_RATIO;\n if (whiteDominates) {\n return EDGE_WHITE_FALLBACK;\n }\n\n const [r, g, b] = dominantColor.split(',').map(Number);\n return rgbToHex(r, g, b);\n}\n","import { hexToRgb, rgbToHex } from '../../utils/color';\nimport { extractEnhancedColorFromBuffer } from './colorHistogram';\nimport {\n EDGE_COLOR_FALLBACK,\n EDGE_WHITE_FALLBACK,\n type EdgeColorSet,\n type EdgeKey,\n WHITE_DOMINANCE_RATIO,\n} from './types';\nimport { loadSharp } from './loadSharp';\n\nexport async function extractEdgeColorsFromBuffer(\n buffer: Buffer,\n): Promise<EdgeColorSet> {\n const sharp = await loadSharp();\n try {\n const sample = await sharp(buffer)\n .resize(400, 400, {\n fit: 'inside',\n kernel: 'lanczos3',\n withoutEnlargement: true,\n })\n .ensureAlpha()\n .raw()\n .toBuffer({ resolveWithObject: true });\n\n return computeEdgeColorSet(\n sample.data,\n sample.info.width,\n sample.info.height,\n );\n } catch {\n try {\n const fallback = await extractEnhancedColorFromBuffer(buffer, 'edge');\n return {\n top: fallback,\n right: fallback,\n bottom: fallback,\n left: fallback,\n };\n } catch {\n return {\n top: EDGE_COLOR_FALLBACK,\n right: EDGE_COLOR_FALLBACK,\n bottom: EDGE_COLOR_FALLBACK,\n left: EDGE_COLOR_FALLBACK,\n };\n }\n }\n}\n\nexport function computeEdgeColorSet(\n data: Buffer,\n width: number,\n height: number,\n): EdgeColorSet {\n const thicknessX = Math.max(2, Math.floor(width * 0.12));\n const thicknessY = Math.max(2, Math.floor(height * 0.12));\n const bucketSize = 16;\n\n const edgeMaps: Record<EdgeKey, Map<string, number>> = {\n top: new Map(),\n right: new Map(),\n bottom: new Map(),\n left: new Map(),\n };\n\n const whiteEdgeStrength: Record<EdgeKey, number> = {\n top: 0,\n right: 0,\n bottom: 0,\n left: 0,\n };\n\n const accumulateEdgeSample = (\n edge: EdgeKey,\n weight: number,\n key: string,\n isWhiteSample: boolean,\n ) => {\n if (weight <= 0) return;\n if (isWhiteSample) {\n whiteEdgeStrength[edge] += weight;\n return;\n }\n edgeMaps[edge].set(key, (edgeMaps[edge].get(key) || 0) + weight);\n };\n\n for (let i = 0; i < data.length; i += 4) {\n const r = data[i];\n const g = data[i + 1];\n const b = data[i + 2];\n const alpha = data[i + 3];\n\n if (alpha !== undefined && alpha < 8) continue;\n\n const brightness = (r + g + b) / 3;\n if (brightness < 12) continue;\n\n const isNearWhite = r >= 245 && g >= 245 && b >= 245;\n\n const pixelIndex = i / 4;\n const x = pixelIndex % width;\n const y = Math.floor(pixelIndex / width);\n\n const bucketR = Math.floor(r / bucketSize) * bucketSize;\n const bucketG = Math.floor(g / bucketSize) * bucketSize;\n const bucketB = Math.floor(b / bucketSize) * bucketSize;\n const key = `${bucketR},${bucketG},${bucketB}`;\n\n const topWeight = y < thicknessY ? 1 + (thicknessY - y) / thicknessY : 0;\n if (topWeight > 0) {\n accumulateEdgeSample('top', topWeight, key, isNearWhite);\n }\n\n const bottomWeight =\n y >= height - thicknessY\n ? 1 + (y - (height - thicknessY)) / thicknessY\n : 0;\n if (bottomWeight > 0) {\n accumulateEdgeSample('bottom', bottomWeight, key, isNearWhite);\n }\n\n const leftWeight = x < thicknessX ? 1 + (thicknessX - x) / thicknessX : 0;\n if (leftWeight > 0) {\n accumulateEdgeSample('left', leftWeight, key, isNearWhite);\n }\n\n const rightWeight =\n x >= width - thicknessX\n ? 1 + (x - (width - thicknessX)) / thicknessX\n : 0;\n if (rightWeight > 0) {\n accumulateEdgeSample('right', rightWeight, key, isNearWhite);\n }\n }\n\n return {\n top: resolveEdgeColor(edgeMaps.top, whiteEdgeStrength.top),\n right: resolveEdgeColor(edgeMaps.right, whiteEdgeStrength.right),\n bottom: resolveEdgeColor(edgeMaps.bottom, whiteEdgeStrength.bottom),\n left: resolveEdgeColor(edgeMaps.left, whiteEdgeStrength.left),\n };\n}\n\nfunction resolveEdgeColor(\n map: Map<string, number>,\n whiteStrength: number,\n): string {\n if (!map.size) {\n return whiteStrength > 0 ? EDGE_WHITE_FALLBACK : EDGE_COLOR_FALLBACK;\n }\n\n let dominantColor = '';\n let maxCount = 0;\n let totalColorWeight = 0;\n\n map.forEach((count, color) => {\n totalColorWeight += count;\n if (count > maxCount) {\n maxCount = count;\n dominantColor = color;\n }\n });\n\n if (!dominantColor) {\n return whiteStrength > 0 ? EDGE_WHITE_FALLBACK : EDGE_COLOR_FALLBACK;\n }\n\n const whiteDominates =\n whiteStrength > 0 &&\n (totalColorWeight === 0 ||\n whiteStrength >= totalColorWeight * WHITE_DOMINANCE_RATIO);\n\n if (whiteDominates) {\n return EDGE_WHITE_FALLBACK;\n }\n\n if (dominantColor.startsWith('#')) {\n return dominantColor.toUpperCase();\n }\n\n const [r, g, b] = dominantColor.split(',').map(Number);\n return rgbToHex(r, g, b);\n}\n\nexport function blendEdgeColors(edgeColors: EdgeColorSet): string {\n const colors = Object.values(edgeColors);\n if (!colors.length) {\n return EDGE_COLOR_FALLBACK;\n }\n\n const totals = colors.reduce(\n (acc, hex) => {\n const { r, g, b } = hexToRgb(hex || EDGE_COLOR_FALLBACK);\n acc.r += r;\n acc.g += g;\n acc.b += b;\n return acc;\n },\n { r: 0, g: 0, b: 0 },\n );\n\n const count = colors.length;\n return rgbToHex(totals.r / count, totals.g / count, totals.b / count);\n}\n","import { UploadValidationError } from '../handler/responses';\n\nexport type SniffedImageFormat =\n | 'jpeg'\n | 'png'\n | 'gif'\n | 'webp'\n | 'avif'\n | 'heif'\n | 'tiff'\n | 'bmp'\n | 'ico'\n | 'svg';\n\nexport interface SniffedFormatResult {\n format: SniffedImageFormat;\n mime: string;\n}\n\nconst AVIF_BRANDS = new Set(['avif', 'avis']);\nconst HEIF_BRANDS = new Set(['heic', 'heix', 'hevc', 'hevx', 'mif1', 'msf1']);\n\nfunction readAscii(bytes: Uint8Array, start: number, end: number): string {\n let out = '';\n const limit = Math.min(bytes.length, end);\n for (let i = start; i < limit; i++) {\n out += String.fromCharCode(bytes[i]);\n }\n return out;\n}\n\nfunction sniffIsoBmff(bytes: Uint8Array): SniffedFormatResult | null {\n if (bytes.length < 12) return null;\n if (readAscii(bytes, 4, 8) !== 'ftyp') return null;\n\n const boxSize =\n ((bytes[0] << 24) | (bytes[1] << 16) | (bytes[2] << 8) | bytes[3]) >>> 0;\n const maxOffset = Math.min(\n bytes.length,\n boxSize >= 16 ? Math.min(boxSize, 128) : 64,\n );\n\n const majorBrand = readAscii(bytes, 8, 12).toLowerCase();\n if (AVIF_BRANDS.has(majorBrand)) {\n return { format: 'avif', mime: 'image/avif' };\n }\n\n const brands = [majorBrand];\n for (let offset = 16; offset + 4 <= maxOffset; offset += 4) {\n brands.push(readAscii(bytes, offset, offset + 4).toLowerCase());\n }\n\n if (brands.some((b) => AVIF_BRANDS.has(b))) {\n return { format: 'avif', mime: 'image/avif' };\n }\n if (brands.some((b) => HEIF_BRANDS.has(b))) {\n return { format: 'heif', mime: 'image/heif' };\n }\n\n return null;\n}\n\nfunction sniffTextSvg(bytes: Uint8Array): SniffedFormatResult | null {\n const sampleLength = Math.min(bytes.length, 4096);\n // Reject binary payloads containing NUL bytes in the text header\n for (let i = 0; i < Math.min(sampleLength, 512); i++) {\n if (bytes[i] === 0x00) return null;\n }\n\n const text = new TextDecoder('utf-8', { fatal: false })\n .decode(bytes.subarray(0, sampleLength))\n .replace(/^\\uFEFF/, '')\n .trimStart();\n\n if (!text.startsWith('<')) return null;\n\n // Strip XML prolog, comments, and DOCTYPE declarations before checking the root tag\n const stripped = text\n .replace(/^<\\?xml[\\s\\S]*?\\?>\\s*/i, '')\n .replace(/<!--[\\s\\S]*?-->\\s*/g, '')\n .replace(/<!DOCTYPE\\s+svg[\\s\\S]*?(?:\\]>|>)\\s*/i, '')\n .replace(/<!--[\\s\\S]*?-->\\s*/g, '')\n .trimStart();\n\n if (/^<svg[\\s>/]/i.test(stripped) || /<svg[\\s>/]/i.test(text)) {\n if (/^<!doctype\\s+html\\b/i.test(text) || /^<html[\\s>]/i.test(stripped)) {\n return null;\n }\n return { format: 'svg', mime: 'image/svg+xml' };\n }\n\n return null;\n}\n\n/**\n * Inspects magic bytes of a buffer to determine its true image format,\n * independent of any client-supplied MIME type or file extension.\n */\nexport function sniffImageFormat(\n input: Buffer | Uint8Array,\n): SniffedFormatResult | null {\n const bytes =\n input instanceof Uint8Array\n ? input\n : new Uint8Array(input as ArrayBufferLike);\n if (bytes.length < 4) return null;\n\n // JPEG: FF D8 FF\n if (bytes[0] === 0xff && bytes[1] === 0xd8 && bytes[2] === 0xff) {\n return { format: 'jpeg', mime: 'image/jpeg' };\n }\n\n // PNG: 89 50 4E 47 0D 0A 1A 0A\n if (\n bytes.length >= 8 &&\n bytes[0] === 0x89 &&\n bytes[1] === 0x50 &&\n bytes[2] === 0x4e &&\n bytes[3] === 0x47 &&\n bytes[4] === 0x0d &&\n bytes[5] === 0x0a &&\n bytes[6] === 0x1a &&\n bytes[7] === 0x0a\n ) {\n return { format: 'png', mime: 'image/png' };\n }\n\n // GIF: GIF87a or GIF89a\n if (bytes.length >= 6) {\n const header = readAscii(bytes, 0, 6);\n if (header === 'GIF87a' || header === 'GIF89a') {\n return { format: 'gif', mime: 'image/gif' };\n }\n }\n\n // WebP: RIFF....WEBP\n if (\n bytes.length >= 12 &&\n readAscii(bytes, 0, 4) === 'RIFF' &&\n readAscii(bytes, 8, 12) === 'WEBP'\n ) {\n return { format: 'webp', mime: 'image/webp' };\n }\n\n // ISO BMFF (AVIF / HEIC / HEIF)\n const bmff = sniffIsoBmff(bytes);\n if (bmff) return bmff;\n\n // TIFF: II*\\0 (little-endian) or MM\\0* (big-endian)\n if (\n (bytes[0] === 0x49 &&\n bytes[1] === 0x49 &&\n bytes[2] === 0x2a &&\n bytes[3] === 0x00) ||\n (bytes[0] === 0x4d &&\n bytes[1] === 0x4d &&\n bytes[2] === 0x00 &&\n bytes[3] === 0x2a)\n ) {\n return { format: 'tiff', mime: 'image/tiff' };\n }\n\n // BMP: BM\n if (bytes.length >= 14 && bytes[0] === 0x42 && bytes[1] === 0x4d) {\n return { format: 'bmp', mime: 'image/bmp' };\n }\n\n // ICO: 00 00 01 00\n if (\n bytes[0] === 0x00 &&\n bytes[1] === 0x00 &&\n bytes[2] === 0x01 &&\n bytes[3] === 0x00\n ) {\n return { format: 'ico', mime: 'image/x-icon' };\n }\n\n return sniffTextSvg(bytes);\n}\n\nexport function assertMagicBytesAllowed(\n buffer: Buffer | Uint8Array,\n allowedFormats: string[],\n allowSvg: boolean = false,\n): SniffedFormatResult {\n const sniffed = sniffImageFormat(buffer);\n if (!sniffed) {\n throw new UploadValidationError(\n 'Unsupported image format: file content is not a recognized image',\n );\n }\n\n if (sniffed.format === 'svg' && !allowSvg) {\n throw new UploadValidationError(\n 'File type image/svg+xml is not allowed unless allowSvg: true is set',\n );\n }\n\n if (allowedFormats.length > 0 && !allowedFormats.includes(sniffed.mime)) {\n throw new UploadValidationError(\n `File type ${sniffed.mime} is not allowed. Allowed: ${allowedFormats.join(', ')}`,\n );\n }\n\n return sniffed;\n}\n","export class SemaphoreQueueFullError extends Error {\n readonly status = 503;\n\n constructor(\n message: string = 'Server upload queue is full. Please try again later.',\n ) {\n super(message);\n this.name = 'SemaphoreQueueFullError';\n }\n}\n\nexport interface SemaphoreOptions {\n maxQueue?: number;\n}\n\nexport interface SemaphoreRunOptions {\n signal?: AbortSignal;\n timeoutMs?: number;\n label?: string;\n}\n\ninterface QueueEntry {\n grant: () => void;\n cancel: (reason: unknown) => void;\n}\n\ninterface ErrorWithPendingTask {\n pendingTask?: Promise<unknown>;\n}\n\nfunction createAbortError(signal?: AbortSignal): Error {\n if (signal?.reason instanceof Error) {\n return signal.reason;\n }\n const err = new Error(\n typeof signal?.reason === 'string' ? signal.reason : 'Operation aborted',\n );\n err.name = 'AbortError';\n return err;\n}\n\nexport class AsyncSemaphore {\n private activeCount = 0;\n private readonly maxQueue?: number;\n private readonly queue: QueueEntry[] = [];\n\n constructor(\n private readonly concurrency: number,\n options?: SemaphoreOptions | number,\n ) {\n if (concurrency < 1) {\n throw new Error('AsyncSemaphore concurrency must be >= 1');\n }\n if (typeof options === 'number') {\n this.maxQueue = options;\n } else if (options && typeof options === 'object') {\n this.maxQueue = options.maxQueue;\n }\n }\n\n get active(): number {\n return this.activeCount;\n }\n\n get pending(): number {\n return this.queue.length;\n }\n\n async run<T>(\n task: () => Promise<T>,\n options: SemaphoreRunOptions = {},\n ): Promise<T> {\n const { signal, timeoutMs, label = 'Semaphore task' } = options;\n await this.acquire(signal);\n\n let rawTaskPromise: Promise<T>;\n try {\n rawTaskPromise = Promise.resolve().then(task);\n } catch (syncError) {\n this.release();\n throw syncError;\n }\n\n let released = false;\n const releaseOnce = () => {\n if (!released) {\n released = true;\n this.release();\n }\n };\n\n void rawTaskPromise.then(\n () => releaseOnce(),\n (err: unknown) => {\n const pending =\n err && typeof err === 'object' && 'pendingTask' in err\n ? (err as ErrorWithPendingTask).pendingTask\n : undefined;\n if (pending && typeof pending.then === 'function') {\n void pending.then(releaseOnce, releaseOnce);\n } else {\n releaseOnce();\n }\n },\n );\n\n let callerPromise = rawTaskPromise;\n if (timeoutMs !== undefined && timeoutMs > 0) {\n callerPromise = withTimeout(callerPromise, timeoutMs, label);\n }\n if (signal) {\n callerPromise = raceWithAbort(callerPromise, signal);\n }\n\n return callerPromise;\n }\n\n private acquire(signal?: AbortSignal): Promise<void> {\n if (signal?.aborted) {\n return Promise.reject(createAbortError(signal));\n }\n\n if (this.activeCount < this.concurrency) {\n this.activeCount += 1;\n return Promise.resolve();\n }\n\n if (this.maxQueue !== undefined && this.queue.length >= this.maxQueue) {\n return Promise.reject(new SemaphoreQueueFullError());\n }\n\n return new Promise<void>((resolve, reject) => {\n const onAbort = () => {\n const idx = this.queue.indexOf(entry);\n if (idx !== -1) {\n this.queue.splice(idx, 1);\n }\n entry.cancel(createAbortError(signal));\n };\n\n const entry: QueueEntry = {\n grant: () => {\n signal?.removeEventListener('abort', onAbort);\n this.activeCount += 1;\n resolve();\n },\n cancel: (reason: unknown) => {\n signal?.removeEventListener('abort', onAbort);\n reject(reason);\n },\n };\n\n signal?.addEventListener('abort', onAbort, { once: true });\n this.queue.push(entry);\n });\n }\n\n private release(): void {\n this.activeCount = Math.max(0, this.activeCount - 1);\n const next = this.queue.shift();\n next?.grant();\n }\n}\n\nfunction raceWithAbort<T>(\n task: Promise<T>,\n signal: AbortSignal,\n): Promise<T> {\n if (signal.aborted) {\n const err = createAbortError(signal) as Error & ErrorWithPendingTask;\n err.pendingTask = task.then(\n () => {},\n () => {},\n );\n return Promise.reject(err);\n }\n\n return new Promise<T>((resolve, reject) => {\n const onAbort = () => {\n const err = createAbortError(signal) as Error & ErrorWithPendingTask;\n err.pendingTask = task.then(\n () => {},\n () => {},\n );\n reject(err);\n };\n\n signal.addEventListener('abort', onAbort, { once: true });\n task.then(\n (val) => {\n signal.removeEventListener('abort', onAbort);\n resolve(val);\n },\n (err) => {\n signal.removeEventListener('abort', onAbort);\n reject(err);\n },\n );\n });\n}\n\nexport async function withTimeout<T>(\n task: Promise<T>,\n timeoutMs: number,\n label: string,\n): Promise<T> {\n let timeoutHandle: ReturnType<typeof setTimeout> | null = null;\n const settledTask = task.then(\n () => {},\n () => {},\n );\n\n try {\n return await Promise.race([\n task,\n new Promise<never>((_, reject) => {\n timeoutHandle = setTimeout(() => {\n const err = new Error(\n `${label} timed out after ${timeoutMs}ms`,\n ) as Error & ErrorWithPendingTask;\n err.pendingTask = settledTask;\n reject(err);\n }, timeoutMs);\n }),\n ]);\n } finally {\n if (timeoutHandle) {\n clearTimeout(timeoutHandle);\n }\n }\n}\n","import { generateBlurPlaceholder, optimizeImage } from '../optimization';\nimport { withTimeout } from '../semaphore';\nimport type {\n ProcessedImageBufferResult,\n ProcessImageBufferOptions,\n} from './types';\n\nasync function computeSha256Hex(buffer: Uint8Array): Promise<string> {\n const bytes = new Uint8Array(buffer.byteLength);\n bytes.set(buffer);\n const digest = await globalThis.crypto.subtle.digest('SHA-256', bytes);\n return Array.from(new Uint8Array(digest))\n .map((b) => b.toString(16).padStart(2, '0'))\n .join('');\n}\n\nfunction throwIfAborted(signal?: AbortSignal): void {\n if (!signal?.aborted) return;\n if (signal.reason instanceof Error) throw signal.reason;\n const err = new Error(\n typeof signal.reason === 'string' ? signal.reason : 'Operation aborted',\n );\n err.name = 'AbortError';\n throw err;\n}\n\nexport async function processImageBuffer(\n originalBuffer: Buffer,\n options: ProcessImageBufferOptions = {},\n): Promise<ProcessedImageBufferResult> {\n const optTimeout = options.optimizationTimeoutMs ?? 60000;\n const blurTimeout = options.blurTimeoutMs ?? 30000;\n\n throwIfAborted(options.signal);\n\n const contentHash = await computeSha256Hex(originalBuffer);\n\n throwIfAborted(options.signal);\n\n const optimized = await withTimeout(\n optimizeImage(originalBuffer, {\n maxDimensions: options.maxDimensions,\n outputFormat: options.outputFormat,\n quality: options.quality,\n limitInputPixels: options.limitInputPixels,\n effort: options.effort,\n }),\n optTimeout,\n 'Image optimization',\n );\n\n if (!optimized || !optimized.buffer) {\n throw new Error('Image optimization returned invalid result');\n }\n\n if (!optimized.width || !optimized.height) {\n throw new Error(\n `Image dimensions missing: width=${optimized.width}, height=${optimized.height}`,\n );\n }\n\n throwIfAborted(options.signal);\n\n const blurData = await withTimeout(\n generateBlurPlaceholder(optimized.buffer, {\n includeBlurHash: options.includeBlurHash,\n }),\n blurTimeout,\n 'Blur generation',\n );\n\n return {\n optimized,\n blurData,\n contentHash,\n originalSize: originalBuffer.length,\n };\n}\n","import type { ImageOutputFormat } from '../../types';\nimport type {\n GeneratedStorageTarget,\n StoragePathContext,\n StoragePathGenerator,\n} from './types';\n\nfunction randomShortId(): string {\n if (\n typeof globalThis.crypto !== 'undefined' &&\n typeof globalThis.crypto.randomUUID === 'function'\n ) {\n return globalThis.crypto.randomUUID().split('-')[0];\n }\n return Math.random().toString(16).slice(2, 10).padEnd(8, '0');\n}\n\nexport function formatToExtension(format: ImageOutputFormat): string {\n switch (format) {\n case 'svg':\n return 'svg';\n case 'png':\n return 'png';\n case 'webp':\n return 'webp';\n case 'jpeg':\n return 'jpg';\n default:\n return 'avif';\n }\n}\n\nexport function sanitizeSegment(value: string): string {\n return value\n .replace(/\\\\/g, '/')\n .split('/')\n .map((part) => part.trim().replace(/[^a-zA-Z0-9._-]/g, '-'))\n .filter((part) => part && part !== '.' && part !== '..')\n .join('/');\n}\n\nexport function stripFilenameExtension(rawFilename: string): string {\n const leaf = rawFilename.replace(/^.*[\\\\/]/, '').trim();\n const dotIdx = leaf.lastIndexOf('.');\n const base = dotIdx > 0 ? leaf.slice(0, dotIdx) : leaf;\n const cleaned = base\n .replace(/[^a-zA-Z0-9._-]/g, '-')\n .replace(/^[.-]+|[.-]+$/g, '');\n return cleaned || 'image';\n}\n\nexport function createDefaultPathGenerator(): StoragePathGenerator {\n let imageCounter = 0;\n\n return (ctx: StoragePathContext): GeneratedStorageTarget => {\n const cleanFolder = ctx.folder ? sanitizeSegment(ctx.folder) : '';\n\n if (ctx.customFilename?.trim()) {\n const baseName = stripFilenameExtension(ctx.customFilename);\n const cleanName = `${baseName}.${ctx.extension}`;\n const fullPath = cleanFolder ? `${cleanFolder}/${cleanName}` : cleanName;\n return {\n bucket: ctx.bucket,\n path: fullPath,\n filename: cleanName,\n };\n }\n\n const date = new Date();\n const year = date.getFullYear();\n const month = String(date.getMonth() + 1).padStart(2, '0');\n const day = String(date.getDate()).padStart(2, '0');\n\n imageCounter = (imageCounter + 1) % 10000;\n const seq = String(imageCounter).padStart(4, '0');\n const timestamp = Date.now();\n const randomSuffix = randomShortId();\n\n const prefix = sanitizeSegment(\n ctx.preset || cleanFolder.split('/')[0] || 'img',\n );\n const filename = `${prefix}-${year}${month}${day}-${seq}-${timestamp}-${randomSuffix}.${ctx.extension}`;\n const fullPath = cleanFolder\n ? `${cleanFolder}/${year}/${month}/${filename}`\n : `${year}/${month}/${filename}`;\n\n return {\n bucket: ctx.bucket,\n path: fullPath,\n filename,\n };\n };\n}\n","import fs from 'node:fs/promises';\nimport path from 'node:path';\nimport type {\n StorageAdapter,\n StorageUploadResult,\n} from '../../storage/types';\nimport { stripFilenameExtension } from './pathGenerator';\nimport type {\n GeneratedStorageTarget,\n StoragePathContext,\n StoragePathGenerator,\n} from './types';\n\nexport interface UploadWithCollisionRetryParams {\n storage: StorageAdapter;\n buildPath: StoragePathGenerator;\n pathContext: StoragePathContext;\n data: Buffer | Uint8Array;\n contentType: string;\n maxRetries?: number;\n}\n\nexport interface UploadWithCollisionRetryResult {\n uploadResult: StorageUploadResult;\n storageTarget: GeneratedStorageTarget;\n}\n\nfunction randomRetrySuffix(): string {\n if (\n typeof globalThis.crypto !== 'undefined' &&\n typeof globalThis.crypto.randomUUID === 'function'\n ) {\n return globalThis.crypto.randomUUID().split('-')[0];\n }\n return Math.random().toString(16).slice(2, 10);\n}\n\n/**\n * Determines whether a storage error represents a filename or object collision.\n * Matches `already exists`, `EEXIST`, or HTTP 412 Precondition Failed, while strictly\n * excluding `does not exist` (e.g. non-existent buckets, directories, or missing keys).\n */\nexport function isCollisionError(e: unknown): boolean {\n if (!e) return false;\n\n const code =\n typeof e === 'object' && e !== null && 'code' in e\n ? String((e as { code: unknown }).code).toUpperCase()\n : '';\n const statusCode =\n typeof e === 'object' && e !== null && '$metadata' in e\n ? (e as { $metadata?: { httpStatusCode?: number } }).$metadata\n ?.httpStatusCode\n : typeof e === 'object' && e !== null && 'statusCode' in e\n ? Number((e as { statusCode: unknown }).statusCode)\n : undefined;\n\n if (code === 'EEXIST' || code === 'PRECONDITIONFAILED' || statusCode === 412) {\n return true;\n }\n if (code === 'ENOENT') {\n return false;\n }\n\n const msg =\n e instanceof Error ? e.message.toLowerCase() : String(e).toLowerCase();\n\n // Strictly exclude non-existence errors (missing bucket, directory, key)\n if (\n msg.includes('does not exist') ||\n msg.includes(\"doesn't exist\") ||\n msg.includes('not exist') ||\n msg.includes('enoent')\n ) {\n return false;\n }\n\n // Match genuine collision indicators\n return (\n msg.includes('already exists') ||\n msg.includes('already_exists') ||\n msg.includes('eexist') ||\n msg.includes('file exists') ||\n msg.includes('precondition failed')\n );\n}\n\n/**\n * Uploads optimized image bytes to the storage backend with automatic filename\n * collision retries. Server-side `customFilename` uses `upsert: true`, while\n * client-supplied `customFilename` (`isClientFilename: true`) never upserts and\n * appends a unique suffix on collision.\n */\nexport async function uploadWithCollisionRetry(\n params: UploadWithCollisionRetryParams,\n): Promise<UploadWithCollisionRetryResult> {\n const {\n storage,\n buildPath,\n pathContext,\n data,\n contentType,\n maxRetries = 3,\n } = params;\n\n const isServerCustomName =\n Boolean(pathContext.customFilename) && !pathContext.isClientFilename;\n\n let storageTarget = buildPath(pathContext);\n let uploadResult: StorageUploadResult | undefined;\n\n for (let attempt = 0; attempt < maxRetries; attempt++) {\n try {\n uploadResult = await storage.upload({\n bucket: storageTarget.bucket,\n path: storageTarget.path,\n data,\n contentType,\n upsert: isServerCustomName,\n contentHash: pathContext.contentHash,\n metadata: pathContext.metadata,\n });\n break;\n } catch (e) {\n if (isCollisionError(e)) {\n if (isServerCustomName) {\n uploadResult = await storage.upload({\n bucket: storageTarget.bucket,\n path: storageTarget.path,\n data,\n contentType,\n upsert: true,\n contentHash: pathContext.contentHash,\n metadata: pathContext.metadata,\n });\n break;\n }\n if (pathContext.customFilename && pathContext.isClientFilename) {\n const base = stripFilenameExtension(pathContext.customFilename);\n storageTarget = buildPath({\n ...pathContext,\n customFilename: `${base}-${randomRetrySuffix()}`,\n });\n continue;\n }\n storageTarget = buildPath({\n ...pathContext,\n customFilename: undefined,\n });\n continue;\n }\n throw e;\n }\n }\n\n if (!uploadResult) {\n throw new Error('Failed to upload image after multiple retries');\n }\n\n return { uploadResult, storageTarget };\n}\n\nexport interface MirrorBufferLocallyOptions {\n buffer: Buffer | Uint8Array;\n filename: string;\n storagePath?: string;\n fallbackUrl: string;\n mirrorDir?: string;\n publicUrlBase?: string;\n}\n\n/**\n * Mirrors an uploaded image buffer to a local directory when `mirrorDir` is configured.\n * Uses non-blocking `fs/promises` I/O, safely swallows read-only filesystem errors on\n * serverless runtimes, and resolves `publicUrlBase` when local mirroring succeeds.\n */\nexport async function mirrorBufferLocally(\n options: MirrorBufferLocallyOptions,\n): Promise<string> {\n const {\n buffer,\n filename,\n storagePath,\n fallbackUrl,\n mirrorDir,\n publicUrlBase,\n } = options;\n if (!mirrorDir) {\n return fallbackUrl;\n }\n\n const relativeTarget = (storagePath || filename).replace(/^\\/+/, '');\n\n try {\n const resolvedBase = path.resolve(mirrorDir);\n const destPath = path.resolve(resolvedBase, relativeTarget);\n const rel = path.relative(resolvedBase, destPath);\n if (rel.startsWith('..') || path.isAbsolute(rel)) {\n return fallbackUrl;\n }\n const destDir = path.dirname(destPath);\n await fs.mkdir(destDir, { recursive: true });\n await fs.writeFile(destPath, buffer);\n if (publicUrlBase) {\n return `${publicUrlBase.replace(/\\/+$/, '')}/${relativeTarget}`;\n }\n } catch {\n // Safely ignored on read-only serverless filesystems\n }\n\n return fallbackUrl;\n}\n\n/**\n * Deletes any locally mirrored copy of `storagePath` across configured `mirrorDirs`.\n */\nexport async function deleteMirroredFiles(\n mirrorDirs: string[],\n storagePath: string,\n): Promise<void> {\n if (!mirrorDirs.length || !storagePath) return;\n const relativeTarget = storagePath.replace(/^\\/+/, '');\n if (!relativeTarget) return;\n\n await Promise.all(\n mirrorDirs.map(async (dir) => {\n try {\n const resolvedBase = path.resolve(dir);\n const destPath = path.resolve(resolvedBase, relativeTarget);\n const rel = path.relative(resolvedBase, destPath);\n if (rel.startsWith('..') || path.isAbsolute(rel)) return;\n await fs.unlink(destPath);\n } catch {\n // Ignore ENOENT or read-only fs errors\n }\n }),\n );\n}\n","import type { StorageAdapter, UploadRecordHook } from '../../storage/types';\nimport type {\n ImageOutputFormat,\n ImageUploadRecord,\n ImageVariant,\n UploadPresetConfig,\n} from '../../types';\nimport { SVG_MIME_TYPE } from '../../types';\nimport {\n DEFAULT_LIMIT_INPUT_PIXELS,\n PRIMARY_AVIF_EFFORT,\n} from '../optimization';\nimport { loadSharp } from '../optimization/loadSharp';\nimport { deleteMirroredFiles, mirrorBufferLocally } from './uploadRetry';\n\nexport interface GenerateImageVariantsParams {\n sourceBuffer: Buffer;\n format: ImageOutputFormat;\n quality?: number;\n effort?: number;\n limitInputPixels?: number;\n mainWidth: number;\n mainHeight: number;\n mainUrl: string;\n baseStoragePath: string;\n baseFilename: string;\n bucket: string;\n storage: StorageAdapter;\n variantWidths?: number[];\n upsert?: boolean;\n contentHash?: string;\n metadata?: Record<string, string>;\n mirrorDir?: string;\n publicUrlBase?: string;\n}\n\nexport interface GeneratedVariantsResult {\n variants: ImageVariant[];\n srcSet?: string;\n}\n\nexport function buildVariantStoragePath(basePath: string, width: number): string {\n const dotIdx = basePath.lastIndexOf('.');\n const slashIdx = basePath.lastIndexOf('/');\n if (dotIdx > slashIdx && dotIdx > 0) {\n return `${basePath.slice(0, dotIdx)}-${width}w${basePath.slice(dotIdx)}`;\n }\n return `${basePath}-${width}w`;\n}\n\nexport function resolveEffectiveAllowedFormats(\n baseFormats: string[],\n allowSvg: boolean,\n explicitAllowSvg: boolean,\n): string[] {\n if (!allowSvg) return baseFormats.filter((fmt) => fmt !== SVG_MIME_TYPE);\n if (explicitAllowSvg && !baseFormats.includes(SVG_MIME_TYPE)) {\n return [...baseFormats, SVG_MIME_TYPE];\n }\n return baseFormats;\n}\n\nexport async function generateImageVariants(\n params: GenerateImageVariantsParams,\n): Promise<GeneratedVariantsResult> {\n const {\n sourceBuffer,\n format,\n quality,\n effort,\n limitInputPixels,\n mainWidth,\n mainHeight,\n mainUrl,\n baseStoragePath,\n baseFilename,\n bucket,\n storage,\n variantWidths,\n upsert = false,\n contentHash,\n metadata,\n mirrorDir,\n publicUrlBase,\n } = params;\n\n if (format === 'svg' || !variantWidths?.length) {\n return { variants: [] };\n }\n\n const targetWidths = [\n ...new Set(\n variantWidths\n .map((w) => Math.floor(w))\n .filter((w) => Number.isFinite(w) && w > 0 && w < mainWidth),\n ),\n ].sort((a, b) => a - b);\n\n if (targetWidths.length === 0) {\n return { variants: [] };\n }\n\n const sharp = await loadSharp();\n const baseQuality = Math.max(1, Math.min(100, quality ?? 85));\n const avifEffort = effort ?? PRIMARY_AVIF_EFFORT;\n const basePipeline = sharp(sourceBuffer, {\n failOn: 'error',\n limitInputPixels: limitInputPixels ?? DEFAULT_LIMIT_INPUT_PIXELS,\n }).rotate();\n\n const variants = await Promise.all(\n targetWidths.map(async (w): Promise<ImageVariant> => {\n let branch = basePipeline.clone().resize({\n width: w,\n withoutEnlargement: true,\n kernel: 'lanczos3',\n });\n\n if (format === 'jpeg') {\n branch = branch.jpeg({ quality: baseQuality, mozjpeg: true });\n } else if (format === 'png') {\n branch = branch.png({ compressionLevel: 9 });\n } else if (format === 'webp') {\n branch = branch.webp({ quality: baseQuality, effort: 4 });\n } else {\n branch = branch.avif({\n quality: baseQuality,\n effort: avifEffort,\n chromaSubsampling: '4:2:0',\n bitdepth: 8,\n });\n }\n\n const out = await branch.toBuffer({ resolveWithObject: true });\n const variantPath = buildVariantStoragePath(baseStoragePath, w);\n const variantFilename = buildVariantStoragePath(baseFilename, w);\n\n const uploaded = await storage.upload({\n bucket,\n path: variantPath,\n data: out.data,\n contentType: `image/${format}`,\n upsert,\n contentHash,\n metadata,\n });\n\n const resolvedUrl = await mirrorBufferLocally({\n buffer: out.data,\n filename: variantFilename,\n storagePath: uploaded.path,\n fallbackUrl: uploaded.url,\n mirrorDir,\n publicUrlBase,\n });\n\n return {\n width: out.info.width || w,\n height:\n out.info.height ||\n Math.max(1, Math.round((mainHeight / Math.max(1, mainWidth)) * w)),\n url: resolvedUrl,\n size: out.info.size,\n storagePath: uploaded.path,\n };\n }),\n );\n\n const srcSet = [\n ...variants.map((v) => `${v.url} ${v.width}w`),\n `${mainUrl} ${mainWidth}w`,\n ].join(', ');\n\n return { variants, srcSet };\n}\n\nexport function collectCandidateVariantWidths(\n presets: Record<string, UploadPresetConfig>,\n extraWidths?: Iterable<number>,\n): number[] {\n const widths = new Set<number>(extraWidths);\n for (const preset of Object.values(presets)) {\n if (preset?.variantWidths) {\n for (const w of preset.variantWidths) {\n if (Number.isFinite(w) && w > 0) widths.add(Math.floor(w));\n }\n }\n }\n return [...widths];\n}\n\nexport async function deleteStoredVariants(params: {\n storage: StorageAdapter;\n bucket: string;\n basePath: string;\n mirrorDirs: string[];\n knownVariantPaths?: string[];\n candidateWidths?: number[];\n}): Promise<void> {\n const {\n storage,\n bucket,\n basePath,\n mirrorDirs,\n knownVariantPaths = [],\n candidateWidths = [],\n } = params;\n\n const paths = new Set<string>(knownVariantPaths);\n for (const w of candidateWidths) {\n paths.add(buildVariantStoragePath(basePath, w));\n }\n\n if (paths.size === 0) return;\n\n await Promise.all(\n [...paths].map(async (vPath) => {\n await storage.delete(bucket, vPath).catch(() => {});\n await deleteMirroredFiles(mirrorDirs, vPath);\n }),\n );\n}\n\nexport async function invokeRecordHookWithRollback(params: {\n onUploadRecord?: UploadRecordHook;\n awaitRecordHook: boolean;\n record: ImageUploadRecord;\n storage: StorageAdapter;\n bucket: string;\n mainPath: string;\n variantPaths: string[];\n mirrorDirs: string[];\n onError?: (error: unknown, ctx: { action: 'recordHook' | 'mirrorCleanup' }) => void;\n}): Promise<void> {\n const {\n onUploadRecord,\n awaitRecordHook,\n record,\n storage,\n bucket,\n mainPath,\n variantPaths,\n mirrorDirs,\n onError,\n } = params;\n if (!onUploadRecord) return;\n\n if (awaitRecordHook) {\n try {\n await onUploadRecord(record);\n } catch (hookError) {\n await storage.delete(bucket, mainPath).catch(() => {});\n await deleteMirroredFiles(mirrorDirs, mainPath);\n await deleteStoredVariants({\n storage,\n bucket,\n basePath: mainPath,\n mirrorDirs,\n knownVariantPaths: variantPaths,\n });\n throw hookError;\n }\n } else {\n Promise.resolve(onUploadRecord(record)).catch((err: unknown) => {\n onError?.(err, { action: 'recordHook' });\n });\n }\n}\n","import type {\n ImageUploadOptions,\n ImageUploadRecord,\n UploadedImageData,\n UploadPresetConfig,\n} from '../../types';\nimport {\n DEFAULT_ALLOWED_FORMATS,\n DEFAULT_IMAGE_DIMENSIONS,\n STANDARD_PRESETS,\n SVG_MIME_TYPE,\n} from '../../types';\nimport { validateImageFileStrict } from '../../utils/validators';\nimport { UploadValidationError } from '../handler/responses';\nimport { assertMagicBytesAllowed, sanitizeSvg } from '../security';\nimport { AsyncSemaphore, SemaphoreQueueFullError } from '../semaphore';\nimport { processImageBuffer } from './bufferProcessor';\nimport { createDefaultPathGenerator, formatToExtension } from './pathGenerator';\nimport type {\n ImageUploader,\n ImageUploaderOptions,\n InferredPresetKey,\n ProcessedImageBufferResult,\n ProcessImageBufferOptions,\n} from './types';\nimport {\n deleteMirroredFiles,\n mirrorBufferLocally,\n uploadWithCollisionRetry,\n} from './uploadRetry';\nimport {\n collectCandidateVariantWidths,\n deleteStoredVariants,\n generateImageVariants,\n invokeRecordHookWithRollback,\n resolveEffectiveAllowedFormats,\n} from './variantGenerator';\n\nexport function createImageUploader<\n TPresets extends Record<string, UploadPresetConfig> = Record<string, UploadPresetConfig>,\n>(\n options: ImageUploaderOptions<TPresets>,\n): ImageUploader<InferredPresetKey<TPresets>> {\n const {\n storage,\n defaultBucket = 'images',\n defaultFolder = '',\n defaultMaxSizeMB = 10,\n defaultAllowedFormats = DEFAULT_ALLOWED_FORMATS,\n defaultMaxDimensions = DEFAULT_IMAGE_DIMENSIONS,\n allowSvg: defaultAllowSvg = false,\n limitInputPixels: defaultLimitInputPixels,\n effort: defaultEffort,\n presets: customPresets,\n includeStandardPresets = true,\n pathGenerator,\n onUploadRecord,\n awaitRecordHook = false,\n onError,\n concurrency = 2,\n maxQueue,\n optimizationTimeoutMs = 60000,\n blurTimeoutMs = 30000,\n includeBlurHash: defaultIncludeBlurHash = false,\n } = options;\n\n const mergedPresets: Record<string, UploadPresetConfig> = {\n ...(includeStandardPresets ? STANDARD_PRESETS : {}),\n ...(customPresets || {}),\n };\n\n const semaphore = new AsyncSemaphore(concurrency, { maxQueue });\n const buildPath = pathGenerator || createDefaultPathGenerator();\n const trackedVariants = new Map<string, string[]>();\n const observedWidths = new Set<number>();\n\n const resolvePreset = (name?: string): UploadPresetConfig | undefined =>\n name ? mergedPresets[name] : undefined;\n\n const getAllowedBuckets = (): string[] => {\n const buckets = new Set<string>([defaultBucket]);\n for (const preset of Object.values(mergedPresets)) {\n if (preset?.bucket) buckets.add(preset.bucket);\n }\n return [...buckets];\n };\n\n const getMirrorDirs = (): string[] =>\n [...new Set(Object.values(mergedPresets).map((p) => p?.mirrorDir).filter(Boolean) as string[])];\n\n const getMaxSizeMB = (allowedPresets?: string[]): number => {\n let maxMB = defaultMaxSizeMB;\n const keys = allowedPresets?.length ? allowedPresets : Object.keys(mergedPresets);\n for (const key of keys) {\n const p = mergedPresets[key];\n if (p?.maxSizeMB && p.maxSizeMB > maxMB) maxMB = p.maxSizeMB;\n }\n return maxMB;\n };\n\n const cleanupVariantsFor = async (bucket: string, basePath: string): Promise<void> => {\n const key = `${bucket}:${basePath}`;\n const knownVariantPaths = trackedVariants.get(key);\n trackedVariants.delete(key);\n await deleteStoredVariants({\n storage, bucket, basePath, mirrorDirs: getMirrorDirs(), knownVariantPaths,\n candidateWidths: collectCandidateVariantWidths(mergedPresets, observedWidths),\n });\n };\n\n return {\n defaultBucket,\n resolvePreset,\n getAllowedBuckets,\n getMaxSizeMB,\n parseUrl: (url: string) => (storage.parseUrl ? storage.parseUrl(url) : null),\n\n async processBuffer(\n buffer: Buffer,\n procOptions: ProcessImageBufferOptions = {},\n ): Promise<ProcessedImageBufferResult> {\n return semaphore.run(\n () =>\n processImageBuffer(buffer, {\n maxDimensions: defaultMaxDimensions, optimizationTimeoutMs, blurTimeoutMs,\n includeBlurHash: defaultIncludeBlurHash, limitInputPixels: defaultLimitInputPixels,\n effort: defaultEffort, ...procOptions,\n }),\n { signal: procOptions.signal },\n );\n },\n\n async uploadImage(\n input,\n uploadOptions: ImageUploadOptions<InferredPresetKey<TPresets>> = {},\n ): Promise<UploadedImageData> {\n const presetConfig = resolvePreset(uploadOptions.preset);\n if (uploadOptions.preset && !presetConfig) {\n throw new UploadValidationError(`Invalid preset \"${uploadOptions.preset}\".`);\n }\n\n const bucket = uploadOptions.bucket || presetConfig?.bucket || defaultBucket;\n const folder = uploadOptions.folder ?? presetConfig?.folder ?? defaultFolder;\n const maxSizeMB = uploadOptions.maxSizeMB ?? presetConfig?.maxSizeMB ?? defaultMaxSizeMB;\n const allowSvg = uploadOptions.allowSvg ?? presetConfig?.allowSvg ?? defaultAllowSvg;\n const explicitAllowSvg = Boolean(\n uploadOptions.allowSvg ??\n presetConfig?.allowSvg ??\n (defaultAllowSvg && !uploadOptions.allowedFormats && !presetConfig?.allowedFormats),\n );\n const allowedFormats = resolveEffectiveAllowedFormats(\n uploadOptions.allowedFormats ?? presetConfig?.allowedFormats ?? defaultAllowedFormats,\n allowSvg, explicitAllowSvg,\n );\n const maxDimensions = uploadOptions.maxDimensions ?? presetConfig?.maxDimensions ?? defaultMaxDimensions;\n const outputFormat = uploadOptions.outputFormat ?? presetConfig?.outputFormat;\n const quality = uploadOptions.quality ?? presetConfig?.quality;\n const includeBlurHash = uploadOptions.includeBlurHash ?? presetConfig?.includeBlurHash ?? defaultIncludeBlurHash;\n const limitInputPixels = uploadOptions.limitInputPixels ?? presetConfig?.limitInputPixels ?? defaultLimitInputPixels;\n const variantWidths = uploadOptions.variantWidths ?? presetConfig?.variantWidths;\n\n const isWebFile = typeof (input as File).arrayBuffer === 'function';\n if (isWebFile) {\n const pre = validateImageFileStrict({ size: (input as File).size, type: input.type }, maxSizeMB, allowedFormats);\n if (!pre.valid) throw new UploadValidationError(pre.error!);\n }\n\n try {\n let originalBuffer = isWebFile\n ? Buffer.from(await (input as File).arrayBuffer())\n : (input as { buffer: Buffer }).buffer;\n if (!originalBuffer || originalBuffer.length === 0) throw new UploadValidationError('File is empty');\n\n const validation = validateImageFileStrict({ size: originalBuffer.length, type: input.type }, maxSizeMB, allowedFormats);\n if (!validation.valid) throw new UploadValidationError(validation.error!);\n\n const sniffed = assertMagicBytesAllowed(originalBuffer, allowedFormats, allowSvg);\n if (sniffed.format === 'svg') originalBuffer = sanitizeSvg(originalBuffer);\n\n const { optimized, blurData, contentHash, originalSize } = await semaphore.run(\n () =>\n processImageBuffer(originalBuffer, {\n maxDimensions, outputFormat, quality, includeBlurHash,\n optimizationTimeoutMs, blurTimeoutMs, limitInputPixels,\n effort: defaultEffort, allowSvg, signal: uploadOptions.signal,\n }),\n { signal: uploadOptions.signal },\n );\n\n const mainFormat = optimized.format;\n const { uploadResult, storageTarget } = await uploadWithCollisionRetry({\n storage, buildPath,\n pathContext: {\n bucket, folder, preset: uploadOptions.preset, format: mainFormat,\n extension: formatToExtension(mainFormat),\n customFilename: uploadOptions.customFilename,\n isClientFilename: uploadOptions.isClientFilename,\n contentHash, originalName: input.name, metadata: uploadOptions.metadata,\n },\n data: optimized.buffer,\n contentType: mainFormat === 'svg' ? SVG_MIME_TYPE : `image/${mainFormat}`,\n });\n\n const resolvedUrl = await mirrorBufferLocally({\n buffer: optimized.buffer, filename: storageTarget.filename,\n storagePath: uploadResult.path, fallbackUrl: uploadResult.url,\n mirrorDir: presetConfig?.mirrorDir, publicUrlBase: presetConfig?.publicUrlBase,\n });\n\n const { variants, srcSet } =\n variantWidths?.length && mainFormat !== 'svg'\n ? await semaphore.run(\n () =>\n generateImageVariants({\n sourceBuffer: originalBuffer, format: mainFormat,\n quality: optimized.quality ?? quality, effort: defaultEffort, limitInputPixels,\n mainWidth: optimized.width, mainHeight: optimized.height, mainUrl: resolvedUrl,\n baseStoragePath: uploadResult.path, baseFilename: storageTarget.filename,\n bucket: storageTarget.bucket, storage, variantWidths,\n upsert: Boolean(uploadOptions.customFilename) && !uploadOptions.isClientFilename,\n contentHash, metadata: uploadOptions.metadata,\n mirrorDir: presetConfig?.mirrorDir, publicUrlBase: presetConfig?.publicUrlBase,\n }),\n { signal: uploadOptions.signal },\n )\n : { variants: [], srcSet: undefined };\n\n const variantPaths = variants.map((v) => v.storagePath).filter(Boolean) as string[];\n if (variantPaths.length > 0) {\n trackedVariants.set(`${storageTarget.bucket}:${uploadResult.path}`, variantPaths);\n variants.forEach((v) => observedWidths.add(v.width));\n }\n\n const result: UploadedImageData = {\n url: resolvedUrl, blurDataUrl: blurData.dataURL, blurColor: blurData.color,\n ...(blurData.blurHash && { blurHash: blurData.blurHash }),\n altText: uploadOptions.altText || '',\n width: optimized.width, height: optimized.height, format: optimized.format,\n size: optimized.size, originalSize, contentHash,\n storagePath: uploadResult.path, bucket: storageTarget.bucket,\n ...(uploadOptions.preset && { preset: uploadOptions.preset }),\n ...(folder && { folder }),\n ...(uploadOptions.metadata && { metadata: uploadOptions.metadata }),\n ...(variants.length > 0 && { variants }),\n ...(srcSet && { srcSet }),\n uploadedAt: new Date().toISOString(),\n };\n\n const record: ImageUploadRecord = { ...result, quality: optimized.quality ?? quality ?? 85 };\n await invokeRecordHookWithRollback({\n onUploadRecord, awaitRecordHook, record, storage, bucket: storageTarget.bucket,\n mainPath: uploadResult.path, variantPaths, mirrorDirs: getMirrorDirs(), onError,\n });\n return result;\n } catch (error) {\n if (error instanceof UploadValidationError || error instanceof SemaphoreQueueFullError) {\n throw error;\n }\n throw new Error(`Image upload failed: ${error instanceof Error ? error.message : 'Unknown error'}`);\n }\n },\n\n async deleteImage(targetPath: string, bucket?: string): Promise<void> {\n const targetBucket = bucket || defaultBucket;\n try {\n await storage.delete(targetBucket, targetPath);\n await deleteMirroredFiles(getMirrorDirs(), targetPath);\n await cleanupVariantsFor(targetBucket, targetPath);\n } catch (error) {\n throw new Error(`Image deletion failed: ${error instanceof Error ? error.message : 'Unknown error'}`);\n }\n },\n\n async deleteByUrl(url: string): Promise<boolean> {\n const parsed = storage.parseUrl?.(url);\n const deleted = storage.deleteByUrl ? await storage.deleteByUrl(url) : false;\n if (deleted && parsed?.path) {\n await deleteMirroredFiles(getMirrorDirs(), parsed.path);\n await cleanupVariantsFor(parsed.bucket || defaultBucket, parsed.path);\n }\n return deleted;\n },\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAkCO,IAAM,6BAA6B;AAcnC,IAAM,sBAAsB;AAC5B,IAAM,oBAAoB;AAE1B,IAAM,yBAAyB;AAC/B,IAAM,kCAAkC;AACxC,IAAM,2BAA2B;AACjC,IAAM,6BAA6B;AAEnC,IAAM,sBAAsB;AAC5B,IAAM,sBAAsB;AAC5B,IAAM,wBAAwB;;;ACxD9B,IAAM,wBAAwB,OAAO;AAE5C,IAAM,qBAAqB;AAAA,EACzB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,IAAM,sBAAsB,oBAAI,IAAI,CAAC,OAAO,MAAM,MAAM,QAAQ,MAAM,CAAC;AAEvE,IAAM,wBAAwB;AAC9B,IAAM,qBACJ;AAEF,SAAS,qBAAqB,KAAqB;AACjD,MAAI,MAAM;AACV,WAAS,IAAI,GAAG,IAAI,IAAI,QAAQ,KAAK;AACnC,QAAI,IAAI,WAAW,CAAC,IAAI,GAAM,QAAO,IAAI,CAAC;AAAA,EAC5C;AACA,SAAO;AACT;AAEA,SAAS,2BAA2B,OAAuB;AACzD,QAAM,UAAU,MACb;AAAA,IAAQ;AAAA,IAAwB,CAAC,GAAG,QACnC,OAAO,cAAc,OAAO,SAAS,KAAK,EAAE,KAAK,CAAC;AAAA,EACpD,EACC;AAAA,IAAQ;AAAA,IAAc,CAAC,GAAG,QACzB,OAAO,cAAc,OAAO,SAAS,KAAK,EAAE,KAAK,CAAC;AAAA,EACpD;AACF,SAAO,qBAAqB,OAAO;AACrC;AAEA,SAAS,cAAc,UAA2B;AAChD,QAAM,UAAU,SAAS,KAAK;AAC9B,MAAI,sBAAsB,KAAK,OAAO,EAAG,QAAO;AAChD,QAAM,UAAU,2BAA2B,OAAO;AAClD,MAAI,sBAAsB,KAAK,OAAO,EAAG,QAAO;AAChD,MAAI,mBAAmB,KAAK,OAAO,KAAK,mBAAmB,KAAK,OAAO,GAAG;AACxE,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAEA,SAAS,iBAAiB,KAAqB;AAC7C,SAAO,IACJ,QAAQ,6BAA6B,EAAE,EACvC,QAAQ,4BAA4B,EAAE,EACtC,QAAQ,8CAA8C,EAAE,EACxD,QAAQ,8BAA8B,EAAE,EACxC,QAAQ,0BAA0B,EAAE,EACpC,QAAQ,oCAAoC,CAAC,MAAM,IAAI,WAAmB;AACzE,UAAM,UAAU,2BAA2B,OAAO,KAAK,CAAC;AACxD,WAAO,sBAAsB,KAAK,OAAO,IAAI,OAAO;AAAA,EACtD,CAAC;AACL;AAEA,SAAS,sBAAsB,OAAuB;AACpD,QAAM,SACJ;AAEF,QAAM,OAAiB,CAAC;AACxB,aAAW,SAAS,MAAM,SAAS,MAAM,GAAG;AAC1C,UAAM,UAAU,MAAM,CAAC;AACvB,UAAM,YAAY,QAAQ,YAAY;AACtC,UAAM,YAAY,UAAU,SAAS,GAAG,IACpC,UAAU,MAAM,GAAG,EAAE,CAAC,IACtB;AACJ,UAAM,WAAW,MAAM,CAAC,KAAK,MAAM,CAAC,KAAK,MAAM,CAAC,KAAK;AAGrD,QAAI,UAAU,WAAW,IAAI,KAAK,UAAU,WAAW,IAAI,GAAG;AAC5D;AAAA,IACF;AAGA,QACE,cAAc,UACd,cAAc,gBACd,cAAc,SACd,cAAc,YACd,cAAc,gBACd,cAAc,QACd;AACA,UAAI,CAAC,cAAc,QAAQ,GAAG;AAC5B;AAAA,MACF;AACA,YAAM,UAAU,SAAS,QAAQ,MAAM,QAAQ;AAC/C,WAAK,KAAK,GAAG,OAAO,KAAK,OAAO,GAAG;AACnC;AAAA,IACF;AAEA,QAAI,cAAc,SAAS;AACzB,YAAM,aAAa,iBAAiB,QAAQ,EAAE,QAAQ,MAAM,GAAG;AAC/D,UAAI,WAAW,KAAK,GAAG;AACrB,aAAK,KAAK,UAAU,UAAU,GAAG;AAAA,MACnC;AACA;AAAA,IACF;AAGA,UAAM,aAAa,2BAA2B,QAAQ,EAAE,YAAY;AACpE,QACE,WAAW,SAAS,aAAa,KACjC,WAAW,SAAS,WAAW,KAC/B,WAAW,SAAS,YAAY,KAChC,WAAW,SAAS,gBAAgB,GACpC;AACA;AAAA,IACF;AAEA,QAAI,YAAY,KAAK,QAAQ,GAAG;AAC9B,YAAM,mBAAmB,iBAAiB,QAAQ,EAAE,QAAQ,MAAM,QAAQ;AAC1E,WAAK,KAAK,GAAG,OAAO,KAAK,gBAAgB,GAAG;AAC5C;AAAA,IACF;AAEA,QAAI,MAAM,CAAC,MAAM,UAAa,MAAM,CAAC,MAAM,UAAa,MAAM,CAAC,MAAM,QAAW;AAC9E,WAAK,KAAK,GAAG,OAAO,KAAK,SAAS,QAAQ,MAAM,QAAQ,CAAC,GAAG;AAAA,IAC9D,OAAO;AACL,WAAK,KAAK,OAAO;AAAA,IACnB;AAAA,EACF;AAEA,SAAO,KAAK,SAAS,IAAI,IAAI,KAAK,KAAK,GAAG,CAAC,KAAK;AAClD;AAWO,SAAS,YACd,OACA,UAA8B,CAAC,GACvB;AACR,QAAM,WAAW,QAAQ,YAAY;AACrC,QAAM,aACJ,OAAO,UAAU,WAAW,OAAO,WAAW,OAAO,MAAM,IAAI,MAAM;AAEvE,MAAI,aAAa,UAAU;AACzB,UAAM,IAAI;AAAA,MACR,kBAAkB,UAAU,+CAA+C,QAAQ;AAAA,IACrF;AAAA,EACF;AAEA,MAAI,MAAM,OAAO,UAAU,WAAW,QAAQ,MAAM,SAAS,MAAM;AACnE,QAAM,IAAI,QAAQ,WAAW,EAAE;AAG/B,QAAM,IAAI,QAAQ,0CAA0C,EAAE;AAC9D,QAAM,IAAI,QAAQ,uBAAuB,EAAE;AAG3C,QAAM,IAAI,QAAQ,oBAAoB,EAAE;AACxC,QAAM,IAAI,QAAQ,6BAA6B,EAAE;AACjD,QAAM,IAAI,QAAQ,6BAA6B,EAAE;AAGjD,QAAM,IAAI;AAAA,IAAQ;AAAA,IAAyB,CAAC,MAAM,SAChD,oBAAoB,IAAI,IAAI,IAAI,OAAO;AAAA,EACzC;AAGA,QAAM,aAAa,mBAAmB,KAAK,GAAG;AAC9C,QAAM,WAAW,IAAI;AAAA,IACnB,+BAA+B,UAAU,0DAA0D,UAAU;AAAA,IAC7G;AAAA,EACF;AACA,QAAM,WAAW,IAAI;AAAA,IACnB,uCAAuC,UAAU;AAAA,IACjD;AAAA,EACF;AACA,QAAM,kBACJ;AAEF,WAAS,OAAO,GAAG,OAAO,GAAG,QAAQ;AACnC,UAAM,OAAO;AACb,UAAM,IACH,QAAQ,UAAU,EAAE,EACpB,QAAQ,UAAU,EAAE,EACpB,QAAQ,iBAAiB,EAAE;AAC9B,QAAI,QAAQ,KAAM;AAAA,EACpB;AAGA,QAAM,IAAI;AAAA,IACR;AAAA,IACA,CAAC,IAAI,MAAc,MAAc,UAC/B,GAAG,IAAI,GAAG,iBAAiB,IAAI,CAAC,GAAG,KAAK;AAAA,EAC5C;AAGA,QAAM,IAAI;AAAA,IACR;AAAA,IACA,CAAC,OAAO,SAAiB,OAA2B,cAAsB;AACxE,YAAM,aAAa,QAAQ,sBAAsB,KAAK,IAAI;AAC1D,aAAO,IAAI,OAAO,GAAG,UAAU,GAAG,SAAS;AAAA,IAC7C;AAAA,EACF;AAEA,MAAI,CAAC,cAAc,KAAK,GAAG,GAAG;AAC5B,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAGA,MACE,SAAS,KAAK,GAAG,KACjB,SAAS,KAAK,GAAG,KACjB,0BAA0B,KAAK,GAAG,KAClC,kBAAkB,KAAK,GAAG,KAC1B,+BAA+B,KAAK,GAAG,GACvC;AACA,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAEA,SAAO,OAAO,KAAK,IAAI,KAAK,GAAG,MAAM;AACvC;;;ACtOO,IAAM,wBACX;AAIF,IAAI,eAA6C;AAGjD,SAAS,cAAiB,KAAiB;AACzC,QAAM,SAAS;AACf,SAAQ,UAAU,OAAO,YAAY,SAAY,OAAO,UAAU;AACpE;AAGO,SAAS,YAAmC;AACjD,MAAI,CAAC,cAAc;AACjB,mBAAe,OAAO,OAAO,EAAE;AAAA,MAC7B,CAAC,QAAQ,cAA4B,GAAG;AAAA,MACxC,CAAC,UAAmB;AAClB,uBAAe;AACf,cAAM,IAAI,MAAM,uBAAuB,EAAE,OAAO,MAAM,CAAC;AAAA,MACzD;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;;;AC1BA,IAAM,sBAAsB,oBAAI,IAAI,CAAC,QAAQ,OAAO,QAAQ,MAAM,CAAC;AAEnE,SAAS,qBACP,SACA,WACA,YACmC;AACnC,MAAI,QAAQ;AACZ,MAAI,SAAS;AAEb,MAAI,CAAC,SAAS,CAAC,QAAQ;AACrB,UAAM,cAAc,QAAQ,MAAM,eAAe;AACjD,QAAI,aAAa;AACf,YAAM,MAAM,YAAY,CAAC;AACzB,YAAM,SAAS,IAAI,MAAM,8CAA8C;AACvE,YAAM,SAAS,IAAI,MAAM,+CAA+C;AACxE,UAAI,CAAC,SAAS,OAAQ,SAAQ,KAAK,MAAM,WAAW,OAAO,CAAC,CAAC,CAAC;AAC9D,UAAI,CAAC,UAAU,OAAQ,UAAS,KAAK,MAAM,WAAW,OAAO,CAAC,CAAC,CAAC;AAAA,IAClE;AAAA,EACF;AAEA,MAAI,CAAC,SAAS,CAAC,QAAQ;AACrB,UAAM,eAAe,QAAQ;AAAA,MAC3B;AAAA,IACF;AACA,QAAI,cAAc;AAChB,UAAI,CAAC,MAAO,SAAQ,KAAK,MAAM,WAAW,aAAa,CAAC,CAAC,CAAC;AAC1D,UAAI,CAAC,OAAQ,UAAS,KAAK,MAAM,WAAW,aAAa,CAAC,CAAC,CAAC;AAAA,IAC9D;AAAA,EACF;AAEA,SAAO;AAAA,IACL,OAAO,SAAS,QAAQ,IAAI,QAAQ;AAAA,IACpC,QAAQ,UAAU,SAAS,IAAI,SAAS;AAAA,EAC1C;AACF;AAEA,eAAsB,cACpB,QACA,UAAgC,CAAC,GACF;AAC/B,QAAM,QAAQ,MAAM,UAAU;AAC9B,QAAM,gBAAgB,QAAQ,iBAAiB;AAC/C,QAAM,EAAE,cAAc,QAAQ,IAAI;AAClC,QAAM,mBACJ,QAAQ,oBAAoB;AAC9B,QAAM,gBAAgB,QAAQ,UAAU;AACxC,QAAM,cACJ,QAAQ,WAAW,SACf,KAAK,IAAI,GAAG,QAAQ,SAAS,CAAC,IAC9B;AAEN,MAAI,WAAW,MAAM,QAAQ;AAAA,IAC3B,QAAQ;AAAA,IACR;AAAA,EACF,CAAC,EAAE,OAAO;AAEV,MAAI;AACJ,MAAI;AACF,eAAW,MAAM,SAAS,SAAS;AAAA,EACrC,SAAS,KAAK;AACZ,UAAM,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC3D,QACE,IAAI,YAAY,EAAE,SAAS,aAAa,KACxC,IAAI,YAAY,EAAE,SAAS,SAAS,KACpC,IAAI,YAAY,EAAE,SAAS,0BAA0B,GACrD;AACA,YAAM,IAAI,sBAAsB,GAAG;AAAA,IACrC;AACA,UAAM;AAAA,EACR;AACA,QAAM,iBAAiB,SAAS;AAEhC,MAAI,mBAAmB,OAAO;AAC5B,UAAM,kBAAkB,YAAY,MAAM;AAC1C,UAAM,UAAU,gBAAgB,SAAS,MAAM;AAC/C,UAAM,OAAO,qBAAqB,SAAS,SAAS,OAAO,SAAS,MAAM;AAE1E,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,OAAO,KAAK;AAAA,MACZ,QAAQ,KAAK;AAAA,MACb,QAAQ;AAAA,MACR,MAAM,gBAAgB;AAAA,MACtB,GAAI,YAAY,SAAY,EAAE,QAAQ,IAAI,CAAC;AAAA,IAC7C;AAAA,EACF;AAEA,QAAM,UACJ,mBAAmB,UACnB,QAAQ,SAAS,WAAW,SAAS,UAAU,GAAG;AAEpD,MAAI,cAAc,YAAY,UAAU,KAAK;AAC7C,gBAAc,KAAK,IAAI,GAAG,KAAK,IAAI,KAAK,WAAW,CAAC;AAEpD,aAAW,SAAS,OAAO,cAAc,OAAO,cAAc,QAAQ;AAAA,IACpE,KAAK;AAAA,IACL,oBAAoB;AAAA,IACpB,QAAQ;AAAA,EACV,CAAC;AAED,MACE,iBAAiB,UACjB,iBAAiB,SACjB,iBAAiB,QACjB;AACA,QAAI,SAAS,SAAS,MAAM;AAC5B,QAAI,iBAAiB,QAAQ;AAC3B,eAAS,OAAO,KAAK,EAAE,SAAS,aAAa,SAAS,KAAK,CAAC;AAAA,IAC9D,WAAW,iBAAiB,OAAO;AACjC,eAAS,OAAO,IAAI;AAAA,IACtB,WAAW,iBAAiB,QAAQ;AAClC,eAAS,OAAO,KAAK,EAAE,SAAS,aAAa,QAAQ,EAAE,CAAC;AAAA,IAC1D;AAEA,UAAM,eAAe,MAAM,OAAO,SAAS,EAAE,mBAAmB,KAAK,CAAC;AAEtE,WAAO;AAAA,MACL,QAAQ,aAAa;AAAA,MACrB,OAAO,aAAa,KAAK,SAAS,cAAc;AAAA,MAChD,QAAQ,aAAa,KAAK,UAAU,cAAc;AAAA,MAClD,QAAQ;AAAA,MACR,MAAM,aAAa,KAAK;AAAA,MACxB,SAAS;AAAA,IACX;AAAA,EACF;AAEA,QAAM,aAAa,MAAM,SACtB,MAAM,EACN,KAAK;AAAA,IACJ,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,mBAAmB;AAAA,IACnB,UAAU;AAAA,EACZ,CAAC,EACA,SAAS,EAAE,mBAAmB,KAAK,CAAC;AAEvC,QAAM,WAAW,WAAW,KAAK;AACjC,QAAM,eAAe,OAAO;AAE5B,MAAI,YAAY,gBAAgB,iBAAiB,QAAQ;AACvD,WAAO;AAAA,MACL,QAAQ,WAAW;AAAA,MACnB,OAAO,WAAW,KAAK,SAAS,cAAc;AAAA,MAC9C,QAAQ,WAAW,KAAK,UAAU,cAAc;AAAA,MAChD,QAAQ;AAAA,MACR,MAAM;AAAA,MACN,SAAS;AAAA,IACX;AAAA,EACF;AAEA,QAAM,gBAAgB,KAAK;AAAA,IACzB;AAAA,IACA,KAAK,MAAM,cAAc,KAAK,KAAK,eAAe,QAAQ,CAAC;AAAA,EAC7D;AAEA,QAAM,YAAY,MAAM,SACrB,MAAM,EACN,KAAK;AAAA,IACJ,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,mBAAmB;AAAA,IACnB,UAAU;AAAA,EACZ,CAAC,EACA,SAAS,EAAE,mBAAmB,KAAK,CAAC;AAEvC,MAAI,UAAU,KAAK,QAAQ,cAAc;AACvC,WAAO;AAAA,MACL,QAAQ,UAAU;AAAA,MAClB,OAAO,UAAU,KAAK,SAAS,cAAc;AAAA,MAC7C,QAAQ,UAAU,KAAK,UAAU,cAAc;AAAA,MAC/C,QAAQ;AAAA,MACR,MAAM,UAAU,KAAK;AAAA,MACrB,SAAS;AAAA,IACX;AAAA,EACF;AAEA,QAAM,cACJ,OAAO,SAAS,gBAAgB,YAChC,SAAS,eAAe,KACxB,SAAS,eAAe;AAC1B,QAAM,gBAAgB,cAAc,SAAS,SAAS,SAAS;AAC/D,QAAM,iBAAiB,cAAc,SAAS,QAAQ,SAAS;AAE/D,QAAM,sBACH,iBAAiB,KAAK,cAAc,UACpC,kBAAkB,KAAK,cAAc;AAExC,MAAI,CAAC,sBAAsB,oBAAoB,IAAI,kBAAkB,EAAE,GAAG;AACxE,UAAM,SAAS;AACf,QAAI,cAAc,SAAS,MAAM;AACjC,QAAI,WAAW,QAAQ;AACrB,oBAAc,YAAY,KAAK,EAAE,SAAS,aAAa,SAAS,KAAK,CAAC;AAAA,IACxE,WAAW,WAAW,OAAO;AAC3B,oBAAc,YAAY,IAAI,EAAE,kBAAkB,EAAE,CAAC;AAAA,IACvD,WAAW,WAAW,QAAQ;AAC5B,oBAAc,YAAY,KAAK,EAAE,SAAS,aAAa,QAAQ,EAAE,CAAC;AAAA,IACpE,OAAO;AACL,oBAAc,YAAY,KAAK;AAAA,QAC7B,SAAS;AAAA,QACT,QAAQ;AAAA,MACV,CAAC;AAAA,IACH;AAEA,QAAI,iBAAiB,MAAM,YAAY,SAAS,EAAE,mBAAmB,KAAK,CAAC;AAC3E,QAAI,WAAW,UAAU,eAAe,KAAK,OAAO,cAAc;AAChE,uBAAiB,MAAM,SACpB,MAAM,EACN,KAAK,EAAE,SAAS,GAAG,CAAC,EACpB,SAAS,EAAE,mBAAmB,KAAK,CAAC;AAAA,IACzC;AAEA,WAAO;AAAA,MACL,QAAQ,eAAe;AAAA,MACvB,OAAO,eAAe,KAAK,SAAS,iBAAiB,cAAc;AAAA,MACnE,QACE,eAAe,KAAK,UAAU,kBAAkB,cAAc;AAAA,MAChE,QAAQ;AAAA,MACR,MAAM,eAAe,KAAK;AAAA,MAC1B,SAAS;AAAA,IACX;AAAA,EACF;AAEA,QAAM,aAAa,MAAM,SACtB,MAAM,EACN,KAAK,EAAE,SAAS,aAAa,QAAQ,GAAG,gBAAgB,KAAK,CAAC,EAC9D,SAAS,EAAE,mBAAmB,KAAK,CAAC;AAEvC,QAAM,UAAU,WAAW,KAAK,QAAQ,UAAU,KAAK;AACvD,QAAM,SAAS,UACX;AAAA,IACE,KAAK,WAAW;AAAA,IAChB,KAAK;AAAA,IACL,IAAI,WAAW,KAAK;AAAA,IACpB,GAAG,WAAW,KAAK;AAAA,IACnB,GAAG,WAAW,KAAK;AAAA,IACnB,GAAG;AAAA,EACL,IACA;AAAA,IACE,KAAK,UAAU;AAAA,IACf,KAAK;AAAA,IACL,IAAI,UAAU,KAAK;AAAA,IACnB,GAAG,UAAU,KAAK;AAAA,IAClB,GAAG,UAAU,KAAK;AAAA,IAClB,GAAG;AAAA,EACL;AAEJ,SAAO;AAAA,IACL,QAAQ,OAAO;AAAA,IACf,OAAO,OAAO,KAAK,cAAc;AAAA,IACjC,QAAQ,OAAO,KAAK,cAAc;AAAA,IAClC,QAAQ,OAAO;AAAA,IACf,MAAM,OAAO;AAAA,IACb,SAAS,OAAO;AAAA,EAClB;AACF;;;AC3QA,SAAS,UAAU,sBAAsB;;;ACSzC,eAAsB,+BACpB,QACA,OAA0B,YACT;AACjB,QAAM,QAAQ,MAAM,UAAU;AAC9B,MAAI;AACF,UAAM,WAAW,MAAM,MAAM,MAAM,EAAE,SAAS;AAC9C,UAAM,UAAU;AAChB,UAAM,cACJ,SAAS,SACT,SAAS,WACR,SAAS,QAAQ,WAAW,SAAS,SAAS;AAEjD,QAAI,aAAa;AACf,YAAM,UAAU,MAAM,MAAM,MAAM,EAC/B,OAAO,SAAS,SAAS;AAAA,QACxB,KAAK;AAAA,QACL,QAAQ;AAAA,QACR,oBAAoB;AAAA,MACtB,CAAC,EACA,YAAY,EACZ,IAAI,EACJ,SAAS,EAAE,mBAAmB,KAAK,CAAC;AAEvC,aAAO;AAAA,QACL,QAAQ;AAAA,QACR,QAAQ,KAAK;AAAA,QACb,QAAQ,KAAK;AAAA,QACb;AAAA,MACF;AAAA,IACF;AAEA,UAAM,MAAM,MAAM,MAAM,MAAM,EAC3B,YAAY,EACZ,IAAI,EACJ,SAAS,EAAE,mBAAmB,KAAK,CAAC;AAEvC,WAAO;AAAA,MACL,IAAI;AAAA,MACJ,IAAI,KAAK;AAAA,MACT,IAAI,KAAK;AAAA,MACT;AAAA,IACF;AAAA,EACF,QAAQ;AACN,UAAM,QAAQ,MAAM,MAAM,MAAM,EAC7B,OAAO,IAAI,IAAI,EAAE,KAAK,SAAS,QAAQ,WAAW,CAAC,EACnD,YAAY,EACZ,IAAI,EACJ,SAAS,EAAE,mBAAmB,KAAK,CAAC;AACvC,WAAO,8BAA8B,MAAM,IAAI;AAAA,EACjD;AACF;AAEA,SAAS,sCACP,MACA,OACA,QACA,MACQ;AACR,QAAM,WAAW,oBAAI,IAAoB;AACzC,QAAM,aAAa;AAEnB,QAAM,eAAe;AACrB,QAAM,UAAU,QAAQ,KAAK;AAC7B,QAAM,UAAU,SAAS,KAAK;AAC9B,MAAI,cAAc;AAElB,WAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK,GAAG;AACvC,UAAM,QAAQ,KAAK,IAAI,CAAC;AACxB,QAAI,UAAU,UAAa,QAAQ,EAAG;AAEtC,UAAMA,KAAI,KAAK,CAAC;AAChB,UAAMC,KAAI,KAAK,IAAI,CAAC;AACpB,UAAMC,KAAI,KAAK,IAAI,CAAC;AACpB,UAAM,cAAcF,KAAIC,KAAIC,MAAK;AACjC,QAAI,aAAa,GAAI;AAErB,UAAM,aAAa,IAAI;AACvB,UAAM,IAAI,aAAa;AACvB,UAAM,IAAI,KAAK,MAAM,aAAa,KAAK;AACvC,UAAM,MAAM,IAAI,WAAW;AAC3B,UAAM,MAAM,IAAI,WAAW;AAC3B,UAAM,qBAAqB,KAAK,KAAK,KAAK,KAAK,KAAK,EAAE;AACtD,QAAI,SAAS;AAEb,QAAI,SAAS,QAAQ;AACnB,YAAM,iBAAiB,KAAK,IAAI,GAAG,KAAK,MAAM,QAAQ,IAAI,CAAC;AAC3D,YAAM,iBAAiB,KAAK,IAAI,GAAG,KAAK,MAAM,SAAS,IAAI,CAAC;AAE5D,YAAM,aAAa,IAAI;AACvB,YAAM,cAAc,KAAK,QAAQ;AACjC,YAAM,YAAY,IAAI;AACtB,YAAM,eAAe,KAAK,SAAS;AAEnC,UAAI,EAAE,cAAc,eAAe,aAAa,eAAe;AAC7D;AAAA,MACF;AAEA,YAAM,wBAAwB,KAAK;AAAA,QACjC;AAAA,QACA;AAAA,QACA,QAAQ,IAAI;AAAA,QACZ,SAAS,IAAI;AAAA,MACf;AACA,YAAM,kBAAkB,KAAK,IAAI,gBAAgB,cAAc,KAAK;AACpE,YAAM,aAAa,IAAI,wBAAwB;AAC/C,eAAS,IAAI,aAAa;AAAA,IAC5B,OAAO;AACL,eAAS,qBAAqB,MAAM,eAAe;AAAA,IACrD;AAEA,UAAM,cAAcF,MAAK,OAAOC,MAAK,OAAOC,MAAK;AACjD,QAAI,aAAa;AACf,qBAAe;AACf;AAAA,IACF;AAEA,UAAM,UAAU,KAAK,MAAMF,KAAI,UAAU,IAAI;AAC7C,UAAM,UAAU,KAAK,MAAMC,KAAI,UAAU,IAAI;AAC7C,UAAM,UAAU,KAAK,MAAMC,KAAI,UAAU,IAAI;AAE7C,UAAM,MAAM,GAAG,OAAO,IAAI,OAAO,IAAI,OAAO;AAC5C,aAAS,IAAI,MAAM,SAAS,IAAI,GAAG,KAAK,KAAK,MAAM;AAAA,EACrD;AAEA,MAAI,CAAC,SAAS,MAAM;AAClB,WAAO,cAAc,IAAI,sBAAsB;AAAA,EACjD;AAEA,MAAI,WAAW;AACf,MAAI,gBAAgB;AACpB,MAAI,mBAAmB;AAEvB,WAAS,QAAQ,CAAC,OAAO,UAAU;AACjC,wBAAoB;AACpB,QAAI,QAAQ,UAAU;AACpB,iBAAW;AACX,sBAAgB;AAAA,IAClB;AAAA,EACF,CAAC;AAED,QAAM,iBACJ,cAAc,KAAK,eAAe,mBAAmB;AACvD,MAAI,gBAAgB;AAClB,WAAO;AAAA,EACT;AAEA,QAAM,CAAC,GAAG,GAAG,CAAC,IAAI,cAAc,MAAM,GAAG,EAAE,IAAI,MAAM;AACrD,SAAO,SAAS,GAAG,GAAG,CAAC;AACzB;AAEA,SAAS,8BAA8B,MAAsB;AAC3D,QAAM,WAAW,oBAAI,IAAoB;AACzC,QAAM,aAAa;AACnB,MAAI,cAAc;AAElB,WAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK,GAAG;AACvC,UAAM,QAAQ,KAAK,IAAI,CAAC;AACxB,QAAI,UAAU,UAAa,QAAQ,EAAG;AAEtC,UAAMF,KAAI,KAAK,MAAM,KAAK,CAAC,IAAI,UAAU,IAAI;AAC7C,UAAMC,KAAI,KAAK,MAAM,KAAK,IAAI,CAAC,IAAI,UAAU,IAAI;AACjD,UAAMC,KAAI,KAAK,MAAM,KAAK,IAAI,CAAC,IAAI,UAAU,IAAI;AAEjD,QAAIF,MAAK,OAAOC,MAAK,OAAOC,MAAK,KAAK;AACpC,qBAAe;AACf;AAAA,IACF;AAEA,UAAM,MAAM,GAAGF,EAAC,IAAIC,EAAC,IAAIC,EAAC;AAC1B,aAAS,IAAI,MAAM,SAAS,IAAI,GAAG,KAAK,KAAK,CAAC;AAAA,EAChD;AAEA,MAAI,CAAC,SAAS,MAAM;AAClB,WAAO,cAAc,IAAI,sBAAsB;AAAA,EACjD;AAEA,MAAI,WAAW;AACf,MAAI,gBAAgB;AACpB,MAAI,mBAAmB;AAEvB,WAAS,QAAQ,CAAC,OAAO,UAAU;AACjC,wBAAoB;AACpB,QAAI,QAAQ,UAAU;AACpB,iBAAW;AACX,sBAAgB;AAAA,IAClB;AAAA,EACF,CAAC;AAED,QAAM,iBACJ,cAAc,KAAK,eAAe,mBAAmB;AACvD,MAAI,gBAAgB;AAClB,WAAO;AAAA,EACT;AAEA,QAAM,CAAC,GAAG,GAAG,CAAC,IAAI,cAAc,MAAM,GAAG,EAAE,IAAI,MAAM;AACrD,SAAO,SAAS,GAAG,GAAG,CAAC;AACzB;;;ACnMA,eAAsB,4BACpB,QACuB;AACvB,QAAM,QAAQ,MAAM,UAAU;AAC9B,MAAI;AACF,UAAM,SAAS,MAAM,MAAM,MAAM,EAC9B,OAAO,KAAK,KAAK;AAAA,MAChB,KAAK;AAAA,MACL,QAAQ;AAAA,MACR,oBAAoB;AAAA,IACtB,CAAC,EACA,YAAY,EACZ,IAAI,EACJ,SAAS,EAAE,mBAAmB,KAAK,CAAC;AAEvC,WAAO;AAAA,MACL,OAAO;AAAA,MACP,OAAO,KAAK;AAAA,MACZ,OAAO,KAAK;AAAA,IACd;AAAA,EACF,QAAQ;AACN,QAAI;AACF,YAAM,WAAW,MAAM,+BAA+B,QAAQ,MAAM;AACpE,aAAO;AAAA,QACL,KAAK;AAAA,QACL,OAAO;AAAA,QACP,QAAQ;AAAA,QACR,MAAM;AAAA,MACR;AAAA,IACF,QAAQ;AACN,aAAO;AAAA,QACL,KAAK;AAAA,QACL,OAAO;AAAA,QACP,QAAQ;AAAA,QACR,MAAM;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACF;AAEO,SAAS,oBACd,MACA,OACA,QACc;AACd,QAAM,aAAa,KAAK,IAAI,GAAG,KAAK,MAAM,QAAQ,IAAI,CAAC;AACvD,QAAM,aAAa,KAAK,IAAI,GAAG,KAAK,MAAM,SAAS,IAAI,CAAC;AACxD,QAAM,aAAa;AAEnB,QAAM,WAAiD;AAAA,IACrD,KAAK,oBAAI,IAAI;AAAA,IACb,OAAO,oBAAI,IAAI;AAAA,IACf,QAAQ,oBAAI,IAAI;AAAA,IAChB,MAAM,oBAAI,IAAI;AAAA,EAChB;AAEA,QAAM,oBAA6C;AAAA,IACjD,KAAK;AAAA,IACL,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,MAAM;AAAA,EACR;AAEA,QAAM,uBAAuB,CAC3B,MACA,QACA,KACA,kBACG;AACH,QAAI,UAAU,EAAG;AACjB,QAAI,eAAe;AACjB,wBAAkB,IAAI,KAAK;AAC3B;AAAA,IACF;AACA,aAAS,IAAI,EAAE,IAAI,MAAM,SAAS,IAAI,EAAE,IAAI,GAAG,KAAK,KAAK,MAAM;AAAA,EACjE;AAEA,WAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK,GAAG;AACvC,UAAM,IAAI,KAAK,CAAC;AAChB,UAAM,IAAI,KAAK,IAAI,CAAC;AACpB,UAAM,IAAI,KAAK,IAAI,CAAC;AACpB,UAAM,QAAQ,KAAK,IAAI,CAAC;AAExB,QAAI,UAAU,UAAa,QAAQ,EAAG;AAEtC,UAAM,cAAc,IAAI,IAAI,KAAK;AACjC,QAAI,aAAa,GAAI;AAErB,UAAM,cAAc,KAAK,OAAO,KAAK,OAAO,KAAK;AAEjD,UAAM,aAAa,IAAI;AACvB,UAAM,IAAI,aAAa;AACvB,UAAM,IAAI,KAAK,MAAM,aAAa,KAAK;AAEvC,UAAM,UAAU,KAAK,MAAM,IAAI,UAAU,IAAI;AAC7C,UAAM,UAAU,KAAK,MAAM,IAAI,UAAU,IAAI;AAC7C,UAAM,UAAU,KAAK,MAAM,IAAI,UAAU,IAAI;AAC7C,UAAM,MAAM,GAAG,OAAO,IAAI,OAAO,IAAI,OAAO;AAE5C,UAAM,YAAY,IAAI,aAAa,KAAK,aAAa,KAAK,aAAa;AACvE,QAAI,YAAY,GAAG;AACjB,2BAAqB,OAAO,WAAW,KAAK,WAAW;AAAA,IACzD;AAEA,UAAM,eACJ,KAAK,SAAS,aACV,KAAK,KAAK,SAAS,eAAe,aAClC;AACN,QAAI,eAAe,GAAG;AACpB,2BAAqB,UAAU,cAAc,KAAK,WAAW;AAAA,IAC/D;AAEA,UAAM,aAAa,IAAI,aAAa,KAAK,aAAa,KAAK,aAAa;AACxE,QAAI,aAAa,GAAG;AAClB,2BAAqB,QAAQ,YAAY,KAAK,WAAW;AAAA,IAC3D;AAEA,UAAM,cACJ,KAAK,QAAQ,aACT,KAAK,KAAK,QAAQ,eAAe,aACjC;AACN,QAAI,cAAc,GAAG;AACnB,2BAAqB,SAAS,aAAa,KAAK,WAAW;AAAA,IAC7D;AAAA,EACF;AAEA,SAAO;AAAA,IACL,KAAK,iBAAiB,SAAS,KAAK,kBAAkB,GAAG;AAAA,IACzD,OAAO,iBAAiB,SAAS,OAAO,kBAAkB,KAAK;AAAA,IAC/D,QAAQ,iBAAiB,SAAS,QAAQ,kBAAkB,MAAM;AAAA,IAClE,MAAM,iBAAiB,SAAS,MAAM,kBAAkB,IAAI;AAAA,EAC9D;AACF;AAEA,SAAS,iBACP,KACA,eACQ;AACR,MAAI,CAAC,IAAI,MAAM;AACb,WAAO,gBAAgB,IAAI,sBAAsB;AAAA,EACnD;AAEA,MAAI,gBAAgB;AACpB,MAAI,WAAW;AACf,MAAI,mBAAmB;AAEvB,MAAI,QAAQ,CAAC,OAAO,UAAU;AAC5B,wBAAoB;AACpB,QAAI,QAAQ,UAAU;AACpB,iBAAW;AACX,sBAAgB;AAAA,IAClB;AAAA,EACF,CAAC;AAED,MAAI,CAAC,eAAe;AAClB,WAAO,gBAAgB,IAAI,sBAAsB;AAAA,EACnD;AAEA,QAAM,iBACJ,gBAAgB,MACf,qBAAqB,KACpB,iBAAiB,mBAAmB;AAExC,MAAI,gBAAgB;AAClB,WAAO;AAAA,EACT;AAEA,MAAI,cAAc,WAAW,GAAG,GAAG;AACjC,WAAO,cAAc,YAAY;AAAA,EACnC;AAEA,QAAM,CAAC,GAAG,GAAG,CAAC,IAAI,cAAc,MAAM,GAAG,EAAE,IAAI,MAAM;AACrD,SAAO,SAAS,GAAG,GAAG,CAAC;AACzB;AAEO,SAAS,gBAAgB,YAAkC;AAChE,QAAM,SAAS,OAAO,OAAO,UAAU;AACvC,MAAI,CAAC,OAAO,QAAQ;AAClB,WAAO;AAAA,EACT;AAEA,QAAM,SAAS,OAAO;AAAA,IACpB,CAAC,KAAK,QAAQ;AACZ,YAAM,EAAE,GAAG,GAAG,EAAE,IAAI,SAAS,OAAO,mBAAmB;AACvD,UAAI,KAAK;AACT,UAAI,KAAK;AACT,UAAI,KAAK;AACT,aAAO;AAAA,IACT;AAAA,IACA,EAAE,GAAG,GAAG,GAAG,GAAG,GAAG,EAAE;AAAA,EACrB;AAEA,QAAM,QAAQ,OAAO;AACrB,SAAO,SAAS,OAAO,IAAI,OAAO,OAAO,IAAI,OAAO,OAAO,IAAI,KAAK;AACtE;;;AF7LA,SAAS,kBACP,MACA,OACA,QACA,aAAqB,GACrB,aAAqB,GACb;AACR,QAAM,WAAW,KAAK,IAAI,GAAG,KAAK,IAAI,KAAK,MAAM,UAAU,GAAG,OAAO,CAAC,CAAC;AACvE,QAAM,WAAW,KAAK,IAAI,GAAG,KAAK,IAAI,KAAK,MAAM,UAAU,GAAG,QAAQ,CAAC,CAAC;AACxE,SAAO;AAAA,IACL,IAAI,kBAAkB,IAAI;AAAA,IAC1B;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAEA,eAAsB,qBACpB,QACA,aAAqB,GACrB,aAAqB,GACJ;AACjB,QAAM,QAAQ,MAAM,UAAU;AAC9B,QAAM,EAAE,MAAM,KAAK,IAAI,MAAM,MAAM,MAAM,EACtC,OAAO,IAAI,IAAI,EAAE,KAAK,SAAS,CAAC,EAChC,YAAY,EACZ,IAAI,EACJ,SAAS,EAAE,mBAAmB,KAAK,CAAC;AAEvC,SAAO;AAAA,IACL;AAAA,IACA,KAAK;AAAA,IACL,KAAK;AAAA,IACL;AAAA,IACA;AAAA,EACF;AACF;AAEA,eAAsB,wBACpB,QACA,UAA+B,CAAC,GACP;AACzB,QAAM,cAAc,QAAQ,SAAS;AACrC,QAAM,gBACJ,QAAQ,iBAAiB;AAC3B,QAAM,UAAU,QAAQ,WAAW;AACnC,QAAM,WAAW,QAAQ,mBAAmB;AAC5C,QAAM,QAAQ,MAAM,UAAU;AAE9B,MAAI;AACF,QAAI,gBAAgB;AACpB,UAAM,QAAQ,aAAa,KAAK,OAAO,SAAS,QAAQ,GAAG,IAAI,CAAC;AAChE,QAAI,OAAO;AACT,YAAM,gBAAgB,OACnB,SAAS,MAAM,EACf,QAAQ,YAAY,MAAM,EAC1B,QAAQ,gBAAgB,QAAQ;AACnC,sBAAgB,OAAO,KAAK,eAAe,MAAM;AAAA,IACnD;AAEA,UAAM,WAAW,KAAK,IAAI,aAAa,GAAG;AAC1C,UAAM,YAAY,MAAM,MAAM,aAAa,EACxC,OAAO,EACP,OAAO,UAAU,UAAU,EAAE,KAAK,UAAU,oBAAoB,KAAK,CAAC,EACtE,YAAY,EACZ,IAAI,EACJ,SAAS,EAAE,mBAAmB,KAAK,CAAC;AAEvC,UAAM,WAAW;AAAA,MACf,KAAK;AAAA,QACH,OAAO,UAAU,KAAK;AAAA,QACtB,QAAQ,UAAU,KAAK;AAAA,QACvB,UAAU;AAAA,MACZ;AAAA,IACF;AAEA,UAAM,0BAA0B,OAAO,UAAmC;AACxE,YAAM,aAAa,MAAM,MAAM,UAAU,MAAM,QAAQ,EACpD,OAAO,OAAO,OAAO,EAAE,KAAK,UAAU,oBAAoB,KAAK,CAAC,EAChE,KAAK,EAAE,SAAS,QAAQ,GAAG,gBAAgB,KAAK,CAAC,EACjD,SAAS;AACZ,aAAO,0BAA0B,WAAW,SAAS,QAAQ,CAAC;AAAA,IAChE;AAEA,QAAI,UAAU,MAAM,wBAAwB,WAAW;AACvD,QAAI,QAAQ,SAAS,UAAU;AAC7B,gBAAU,MAAM,wBAAwB,aAAa;AAAA,IACvD;AAEA,UAAM,aAAa;AAAA,MACjB,UAAU;AAAA,MACV,UAAU,KAAK;AAAA,MACf,UAAU,KAAK;AAAA,IACjB;AACA,UAAM,QAAQ,gBAAgB,UAAU;AAExC,QAAI;AACJ,QAAI,QAAQ,iBAAiB;AAC3B,UAAI;AACF,cAAM,aACJ,UAAU,KAAK,SAAS,MAAM,UAAU,KAAK,UAAU,KACnD,YACA,MAAM,MAAM,UAAU,MAAM,QAAQ,EACjC,OAAO,IAAI,IAAI,EAAE,KAAK,SAAS,CAAC,EAChC,YAAY,EACZ,IAAI,EACJ,SAAS,EAAE,mBAAmB,KAAK,CAAC;AAC7C,mBAAW;AAAA,UACT,WAAW;AAAA,UACX,WAAW,KAAK;AAAA,UAChB,WAAW,KAAK;AAAA,QAClB;AAAA,MACF,QAAQ;AACN,mBAAW;AAAA,MACb;AAAA,IACF;AAEA,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA,GAAI,YAAY,EAAE,SAAS;AAAA,IAC7B;AAAA,EACF,QAAQ;AACN,WAAO,qBAAqB,QAAQ,QAAQ,eAAe;AAAA,EAC7D;AACF;AAEO,IAAM,mBAAmB;AAEhC,eAAe,qBACb,QACA,iBACyB;AACzB,QAAM,QAAQ,MAAM,UAAU;AAC9B,QAAM,aAAa,MAAM,MAAM,MAAM,EAClC,OAAO,IAAI,IAAI,EAAE,KAAK,SAAS,QAAQ,WAAW,CAAC,EACnD,KAAK,CAAG,EACR,KAAK;AAAA,IACJ,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,gBAAgB;AAAA,EAClB,CAAC,EACA,SAAS;AAEZ,QAAM,UAAU,0BAA0B,WAAW,SAAS,QAAQ,CAAC;AACvE,QAAM,aAAa,MAAM,4BAA4B,MAAM;AAC3D,QAAM,QAAQ,gBAAgB,UAAU;AAExC,MAAI;AACJ,MAAI,iBAAiB;AACnB,QAAI;AACF,iBAAW,MAAM,qBAAqB,UAAU;AAAA,IAClD,QAAQ;AACN,iBAAW;AAAA,IACb;AAAA,EACF;AAEA,SAAO,EAAE,SAAS,OAAO,GAAI,YAAY,EAAE,SAAS,EAAG;AACzD;;;AG5JA,IAAM,cAAc,oBAAI,IAAI,CAAC,QAAQ,MAAM,CAAC;AAC5C,IAAM,cAAc,oBAAI,IAAI,CAAC,QAAQ,QAAQ,QAAQ,QAAQ,QAAQ,MAAM,CAAC;AAE5E,SAAS,UAAU,OAAmB,OAAe,KAAqB;AACxE,MAAI,MAAM;AACV,QAAM,QAAQ,KAAK,IAAI,MAAM,QAAQ,GAAG;AACxC,WAAS,IAAI,OAAO,IAAI,OAAO,KAAK;AAClC,WAAO,OAAO,aAAa,MAAM,CAAC,CAAC;AAAA,EACrC;AACA,SAAO;AACT;AAEA,SAAS,aAAa,OAA+C;AACnE,MAAI,MAAM,SAAS,GAAI,QAAO;AAC9B,MAAI,UAAU,OAAO,GAAG,CAAC,MAAM,OAAQ,QAAO;AAE9C,QAAM,WACF,MAAM,CAAC,KAAK,KAAO,MAAM,CAAC,KAAK,KAAO,MAAM,CAAC,KAAK,IAAK,MAAM,CAAC,OAAO;AACzE,QAAM,YAAY,KAAK;AAAA,IACrB,MAAM;AAAA,IACN,WAAW,KAAK,KAAK,IAAI,SAAS,GAAG,IAAI;AAAA,EAC3C;AAEA,QAAM,aAAa,UAAU,OAAO,GAAG,EAAE,EAAE,YAAY;AACvD,MAAI,YAAY,IAAI,UAAU,GAAG;AAC/B,WAAO,EAAE,QAAQ,QAAQ,MAAM,aAAa;AAAA,EAC9C;AAEA,QAAM,SAAS,CAAC,UAAU;AAC1B,WAAS,SAAS,IAAI,SAAS,KAAK,WAAW,UAAU,GAAG;AAC1D,WAAO,KAAK,UAAU,OAAO,QAAQ,SAAS,CAAC,EAAE,YAAY,CAAC;AAAA,EAChE;AAEA,MAAI,OAAO,KAAK,CAAC,MAAM,YAAY,IAAI,CAAC,CAAC,GAAG;AAC1C,WAAO,EAAE,QAAQ,QAAQ,MAAM,aAAa;AAAA,EAC9C;AACA,MAAI,OAAO,KAAK,CAAC,MAAM,YAAY,IAAI,CAAC,CAAC,GAAG;AAC1C,WAAO,EAAE,QAAQ,QAAQ,MAAM,aAAa;AAAA,EAC9C;AAEA,SAAO;AACT;AAEA,SAAS,aAAa,OAA+C;AACnE,QAAM,eAAe,KAAK,IAAI,MAAM,QAAQ,IAAI;AAEhD,WAAS,IAAI,GAAG,IAAI,KAAK,IAAI,cAAc,GAAG,GAAG,KAAK;AACpD,QAAI,MAAM,CAAC,MAAM,EAAM,QAAO;AAAA,EAChC;AAEA,QAAM,OAAO,IAAI,YAAY,SAAS,EAAE,OAAO,MAAM,CAAC,EACnD,OAAO,MAAM,SAAS,GAAG,YAAY,CAAC,EACtC,QAAQ,WAAW,EAAE,EACrB,UAAU;AAEb,MAAI,CAAC,KAAK,WAAW,GAAG,EAAG,QAAO;AAGlC,QAAM,WAAW,KACd,QAAQ,0BAA0B,EAAE,EACpC,QAAQ,uBAAuB,EAAE,EACjC,QAAQ,wCAAwC,EAAE,EAClD,QAAQ,uBAAuB,EAAE,EACjC,UAAU;AAEb,MAAI,eAAe,KAAK,QAAQ,KAAK,cAAc,KAAK,IAAI,GAAG;AAC7D,QAAI,uBAAuB,KAAK,IAAI,KAAK,eAAe,KAAK,QAAQ,GAAG;AACtE,aAAO;AAAA,IACT;AACA,WAAO,EAAE,QAAQ,OAAO,MAAM,gBAAgB;AAAA,EAChD;AAEA,SAAO;AACT;AAMO,SAAS,iBACd,OAC4B;AAC5B,QAAM,QACJ,iBAAiB,aACb,QACA,IAAI,WAAW,KAAwB;AAC7C,MAAI,MAAM,SAAS,EAAG,QAAO;AAG7B,MAAI,MAAM,CAAC,MAAM,OAAQ,MAAM,CAAC,MAAM,OAAQ,MAAM,CAAC,MAAM,KAAM;AAC/D,WAAO,EAAE,QAAQ,QAAQ,MAAM,aAAa;AAAA,EAC9C;AAGA,MACE,MAAM,UAAU,KAChB,MAAM,CAAC,MAAM,OACb,MAAM,CAAC,MAAM,MACb,MAAM,CAAC,MAAM,MACb,MAAM,CAAC,MAAM,MACb,MAAM,CAAC,MAAM,MACb,MAAM,CAAC,MAAM,MACb,MAAM,CAAC,MAAM,MACb,MAAM,CAAC,MAAM,IACb;AACA,WAAO,EAAE,QAAQ,OAAO,MAAM,YAAY;AAAA,EAC5C;AAGA,MAAI,MAAM,UAAU,GAAG;AACrB,UAAM,SAAS,UAAU,OAAO,GAAG,CAAC;AACpC,QAAI,WAAW,YAAY,WAAW,UAAU;AAC9C,aAAO,EAAE,QAAQ,OAAO,MAAM,YAAY;AAAA,IAC5C;AAAA,EACF;AAGA,MACE,MAAM,UAAU,MAChB,UAAU,OAAO,GAAG,CAAC,MAAM,UAC3B,UAAU,OAAO,GAAG,EAAE,MAAM,QAC5B;AACA,WAAO,EAAE,QAAQ,QAAQ,MAAM,aAAa;AAAA,EAC9C;AAGA,QAAM,OAAO,aAAa,KAAK;AAC/B,MAAI,KAAM,QAAO;AAGjB,MACG,MAAM,CAAC,MAAM,MACZ,MAAM,CAAC,MAAM,MACb,MAAM,CAAC,MAAM,MACb,MAAM,CAAC,MAAM,KACd,MAAM,CAAC,MAAM,MACZ,MAAM,CAAC,MAAM,MACb,MAAM,CAAC,MAAM,KACb,MAAM,CAAC,MAAM,IACf;AACA,WAAO,EAAE,QAAQ,QAAQ,MAAM,aAAa;AAAA,EAC9C;AAGA,MAAI,MAAM,UAAU,MAAM,MAAM,CAAC,MAAM,MAAQ,MAAM,CAAC,MAAM,IAAM;AAChE,WAAO,EAAE,QAAQ,OAAO,MAAM,YAAY;AAAA,EAC5C;AAGA,MACE,MAAM,CAAC,MAAM,KACb,MAAM,CAAC,MAAM,KACb,MAAM,CAAC,MAAM,KACb,MAAM,CAAC,MAAM,GACb;AACA,WAAO,EAAE,QAAQ,OAAO,MAAM,eAAe;AAAA,EAC/C;AAEA,SAAO,aAAa,KAAK;AAC3B;AAEO,SAAS,wBACd,QACA,gBACA,WAAoB,OACC;AACrB,QAAM,UAAU,iBAAiB,MAAM;AACvC,MAAI,CAAC,SAAS;AACZ,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAEA,MAAI,QAAQ,WAAW,SAAS,CAAC,UAAU;AACzC,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAEA,MAAI,eAAe,SAAS,KAAK,CAAC,eAAe,SAAS,QAAQ,IAAI,GAAG;AACvE,UAAM,IAAI;AAAA,MACR,aAAa,QAAQ,IAAI,6BAA6B,eAAe,KAAK,IAAI,CAAC;AAAA,IACjF;AAAA,EACF;AAEA,SAAO;AACT;;;AC7MO,IAAM,0BAAN,cAAsC,MAAM;AAAA,EACxC,SAAS;AAAA,EAElB,YACE,UAAkB,wDAClB;AACA,UAAM,OAAO;AACb,SAAK,OAAO;AAAA,EACd;AACF;AAqBA,SAAS,iBAAiB,QAA6B;AACrD,MAAI,QAAQ,kBAAkB,OAAO;AACnC,WAAO,OAAO;AAAA,EAChB;AACA,QAAM,MAAM,IAAI;AAAA,IACd,OAAO,QAAQ,WAAW,WAAW,OAAO,SAAS;AAAA,EACvD;AACA,MAAI,OAAO;AACX,SAAO;AACT;AAEO,IAAM,iBAAN,MAAqB;AAAA,EAK1B,YACmB,aACjB,SACA;AAFiB;AAGjB,QAAI,cAAc,GAAG;AACnB,YAAM,IAAI,MAAM,yCAAyC;AAAA,IAC3D;AACA,QAAI,OAAO,YAAY,UAAU;AAC/B,WAAK,WAAW;AAAA,IAClB,WAAW,WAAW,OAAO,YAAY,UAAU;AACjD,WAAK,WAAW,QAAQ;AAAA,IAC1B;AAAA,EACF;AAAA,EAXmB;AAAA,EALX,cAAc;AAAA,EACL;AAAA,EACA,QAAsB,CAAC;AAAA,EAgBxC,IAAI,SAAiB;AACnB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,IAAI,UAAkB;AACpB,WAAO,KAAK,MAAM;AAAA,EACpB;AAAA,EAEA,MAAM,IACJ,MACA,UAA+B,CAAC,GACpB;AACZ,UAAM,EAAE,QAAQ,WAAW,QAAQ,iBAAiB,IAAI;AACxD,UAAM,KAAK,QAAQ,MAAM;AAEzB,QAAI;AACJ,QAAI;AACF,uBAAiB,QAAQ,QAAQ,EAAE,KAAK,IAAI;AAAA,IAC9C,SAAS,WAAW;AAClB,WAAK,QAAQ;AACb,YAAM;AAAA,IACR;AAEA,QAAI,WAAW;AACf,UAAM,cAAc,MAAM;AACxB,UAAI,CAAC,UAAU;AACb,mBAAW;AACX,aAAK,QAAQ;AAAA,MACf;AAAA,IACF;AAEA,SAAK,eAAe;AAAA,MAClB,MAAM,YAAY;AAAA,MAClB,CAAC,QAAiB;AAChB,cAAM,UACJ,OAAO,OAAO,QAAQ,YAAY,iBAAiB,MAC9C,IAA6B,cAC9B;AACN,YAAI,WAAW,OAAO,QAAQ,SAAS,YAAY;AACjD,eAAK,QAAQ,KAAK,aAAa,WAAW;AAAA,QAC5C,OAAO;AACL,sBAAY;AAAA,QACd;AAAA,MACF;AAAA,IACF;AAEA,QAAI,gBAAgB;AACpB,QAAI,cAAc,UAAa,YAAY,GAAG;AAC5C,sBAAgB,YAAY,eAAe,WAAW,KAAK;AAAA,IAC7D;AACA,QAAI,QAAQ;AACV,sBAAgB,cAAc,eAAe,MAAM;AAAA,IACrD;AAEA,WAAO;AAAA,EACT;AAAA,EAEQ,QAAQ,QAAqC;AACnD,QAAI,QAAQ,SAAS;AACnB,aAAO,QAAQ,OAAO,iBAAiB,MAAM,CAAC;AAAA,IAChD;AAEA,QAAI,KAAK,cAAc,KAAK,aAAa;AACvC,WAAK,eAAe;AACpB,aAAO,QAAQ,QAAQ;AAAA,IACzB;AAEA,QAAI,KAAK,aAAa,UAAa,KAAK,MAAM,UAAU,KAAK,UAAU;AACrE,aAAO,QAAQ,OAAO,IAAI,wBAAwB,CAAC;AAAA,IACrD;AAEA,WAAO,IAAI,QAAc,CAAC,SAAS,WAAW;AAC5C,YAAM,UAAU,MAAM;AACpB,cAAM,MAAM,KAAK,MAAM,QAAQ,KAAK;AACpC,YAAI,QAAQ,IAAI;AACd,eAAK,MAAM,OAAO,KAAK,CAAC;AAAA,QAC1B;AACA,cAAM,OAAO,iBAAiB,MAAM,CAAC;AAAA,MACvC;AAEA,YAAM,QAAoB;AAAA,QACxB,OAAO,MAAM;AACX,kBAAQ,oBAAoB,SAAS,OAAO;AAC5C,eAAK,eAAe;AACpB,kBAAQ;AAAA,QACV;AAAA,QACA,QAAQ,CAAC,WAAoB;AAC3B,kBAAQ,oBAAoB,SAAS,OAAO;AAC5C,iBAAO,MAAM;AAAA,QACf;AAAA,MACF;AAEA,cAAQ,iBAAiB,SAAS,SAAS,EAAE,MAAM,KAAK,CAAC;AACzD,WAAK,MAAM,KAAK,KAAK;AAAA,IACvB,CAAC;AAAA,EACH;AAAA,EAEQ,UAAgB;AACtB,SAAK,cAAc,KAAK,IAAI,GAAG,KAAK,cAAc,CAAC;AACnD,UAAM,OAAO,KAAK,MAAM,MAAM;AAC9B,UAAM,MAAM;AAAA,EACd;AACF;AAEA,SAAS,cACP,MACA,QACY;AACZ,MAAI,OAAO,SAAS;AAClB,UAAM,MAAM,iBAAiB,MAAM;AACnC,QAAI,cAAc,KAAK;AAAA,MACrB,MAAM;AAAA,MAAC;AAAA,MACP,MAAM;AAAA,MAAC;AAAA,IACT;AACA,WAAO,QAAQ,OAAO,GAAG;AAAA,EAC3B;AAEA,SAAO,IAAI,QAAW,CAAC,SAAS,WAAW;AACzC,UAAM,UAAU,MAAM;AACpB,YAAM,MAAM,iBAAiB,MAAM;AACnC,UAAI,cAAc,KAAK;AAAA,QACrB,MAAM;AAAA,QAAC;AAAA,QACP,MAAM;AAAA,QAAC;AAAA,MACT;AACA,aAAO,GAAG;AAAA,IACZ;AAEA,WAAO,iBAAiB,SAAS,SAAS,EAAE,MAAM,KAAK,CAAC;AACxD,SAAK;AAAA,MACH,CAAC,QAAQ;AACP,eAAO,oBAAoB,SAAS,OAAO;AAC3C,gBAAQ,GAAG;AAAA,MACb;AAAA,MACA,CAAC,QAAQ;AACP,eAAO,oBAAoB,SAAS,OAAO;AAC3C,eAAO,GAAG;AAAA,MACZ;AAAA,IACF;AAAA,EACF,CAAC;AACH;AAEA,eAAsB,YACpB,MACA,WACA,OACY;AACZ,MAAI,gBAAsD;AAC1D,QAAM,cAAc,KAAK;AAAA,IACvB,MAAM;AAAA,IAAC;AAAA,IACP,MAAM;AAAA,IAAC;AAAA,EACT;AAEA,MAAI;AACF,WAAO,MAAM,QAAQ,KAAK;AAAA,MACxB;AAAA,MACA,IAAI,QAAe,CAAC,GAAG,WAAW;AAChC,wBAAgB,WAAW,MAAM;AAC/B,gBAAM,MAAM,IAAI;AAAA,YACd,GAAG,KAAK,oBAAoB,SAAS;AAAA,UACvC;AACA,cAAI,cAAc;AAClB,iBAAO,GAAG;AAAA,QACZ,GAAG,SAAS;AAAA,MACd,CAAC;AAAA,IACH,CAAC;AAAA,EACH,UAAE;AACA,QAAI,eAAe;AACjB,mBAAa,aAAa;AAAA,IAC5B;AAAA,EACF;AACF;;;AC/NA,eAAe,iBAAiB,QAAqC;AACnE,QAAM,QAAQ,IAAI,WAAW,OAAO,UAAU;AAC9C,QAAM,IAAI,MAAM;AAChB,QAAM,SAAS,MAAM,WAAW,OAAO,OAAO,OAAO,WAAW,KAAK;AACrE,SAAO,MAAM,KAAK,IAAI,WAAW,MAAM,CAAC,EACrC,IAAI,CAAC,MAAM,EAAE,SAAS,EAAE,EAAE,SAAS,GAAG,GAAG,CAAC,EAC1C,KAAK,EAAE;AACZ;AAEA,SAAS,eAAe,QAA4B;AAClD,MAAI,CAAC,QAAQ,QAAS;AACtB,MAAI,OAAO,kBAAkB,MAAO,OAAM,OAAO;AACjD,QAAM,MAAM,IAAI;AAAA,IACd,OAAO,OAAO,WAAW,WAAW,OAAO,SAAS;AAAA,EACtD;AACA,MAAI,OAAO;AACX,QAAM;AACR;AAEA,eAAsB,mBACpB,gBACA,UAAqC,CAAC,GACD;AACrC,QAAM,aAAa,QAAQ,yBAAyB;AACpD,QAAM,cAAc,QAAQ,iBAAiB;AAE7C,iBAAe,QAAQ,MAAM;AAE7B,QAAM,cAAc,MAAM,iBAAiB,cAAc;AAEzD,iBAAe,QAAQ,MAAM;AAE7B,QAAM,YAAY,MAAM;AAAA,IACtB,cAAc,gBAAgB;AAAA,MAC5B,eAAe,QAAQ;AAAA,MACvB,cAAc,QAAQ;AAAA,MACtB,SAAS,QAAQ;AAAA,MACjB,kBAAkB,QAAQ;AAAA,MAC1B,QAAQ,QAAQ;AAAA,IAClB,CAAC;AAAA,IACD;AAAA,IACA;AAAA,EACF;AAEA,MAAI,CAAC,aAAa,CAAC,UAAU,QAAQ;AACnC,UAAM,IAAI,MAAM,4CAA4C;AAAA,EAC9D;AAEA,MAAI,CAAC,UAAU,SAAS,CAAC,UAAU,QAAQ;AACzC,UAAM,IAAI;AAAA,MACR,mCAAmC,UAAU,KAAK,YAAY,UAAU,MAAM;AAAA,IAChF;AAAA,EACF;AAEA,iBAAe,QAAQ,MAAM;AAE7B,QAAM,WAAW,MAAM;AAAA,IACrB,wBAAwB,UAAU,QAAQ;AAAA,MACxC,iBAAiB,QAAQ;AAAA,IAC3B,CAAC;AAAA,IACD;AAAA,IACA;AAAA,EACF;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA,cAAc,eAAe;AAAA,EAC/B;AACF;;;ACtEA,SAAS,gBAAwB;AAC/B,MACE,OAAO,WAAW,WAAW,eAC7B,OAAO,WAAW,OAAO,eAAe,YACxC;AACA,WAAO,WAAW,OAAO,WAAW,EAAE,MAAM,GAAG,EAAE,CAAC;AAAA,EACpD;AACA,SAAO,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,GAAG,EAAE,EAAE,OAAO,GAAG,GAAG;AAC9D;AAEO,SAAS,kBAAkB,QAAmC;AACnE,UAAQ,QAAQ;AAAA,IACd,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT;AACE,aAAO;AAAA,EACX;AACF;AAEO,SAAS,gBAAgB,OAAuB;AACrD,SAAO,MACJ,QAAQ,OAAO,GAAG,EAClB,MAAM,GAAG,EACT,IAAI,CAAC,SAAS,KAAK,KAAK,EAAE,QAAQ,oBAAoB,GAAG,CAAC,EAC1D,OAAO,CAAC,SAAS,QAAQ,SAAS,OAAO,SAAS,IAAI,EACtD,KAAK,GAAG;AACb;AAEO,SAAS,uBAAuB,aAA6B;AAClE,QAAM,OAAO,YAAY,QAAQ,YAAY,EAAE,EAAE,KAAK;AACtD,QAAM,SAAS,KAAK,YAAY,GAAG;AACnC,QAAM,OAAO,SAAS,IAAI,KAAK,MAAM,GAAG,MAAM,IAAI;AAClD,QAAM,UAAU,KACb,QAAQ,oBAAoB,GAAG,EAC/B,QAAQ,kBAAkB,EAAE;AAC/B,SAAO,WAAW;AACpB;AAEO,SAAS,6BAAmD;AACjE,MAAI,eAAe;AAEnB,SAAO,CAAC,QAAoD;AAC1D,UAAM,cAAc,IAAI,SAAS,gBAAgB,IAAI,MAAM,IAAI;AAE/D,QAAI,IAAI,gBAAgB,KAAK,GAAG;AAC9B,YAAM,WAAW,uBAAuB,IAAI,cAAc;AAC1D,YAAM,YAAY,GAAG,QAAQ,IAAI,IAAI,SAAS;AAC9C,YAAMC,YAAW,cAAc,GAAG,WAAW,IAAI,SAAS,KAAK;AAC/D,aAAO;AAAA,QACL,QAAQ,IAAI;AAAA,QACZ,MAAMA;AAAA,QACN,UAAU;AAAA,MACZ;AAAA,IACF;AAEA,UAAM,OAAO,oBAAI,KAAK;AACtB,UAAM,OAAO,KAAK,YAAY;AAC9B,UAAM,QAAQ,OAAO,KAAK,SAAS,IAAI,CAAC,EAAE,SAAS,GAAG,GAAG;AACzD,UAAM,MAAM,OAAO,KAAK,QAAQ,CAAC,EAAE,SAAS,GAAG,GAAG;AAElD,oBAAgB,eAAe,KAAK;AACpC,UAAM,MAAM,OAAO,YAAY,EAAE,SAAS,GAAG,GAAG;AAChD,UAAM,YAAY,KAAK,IAAI;AAC3B,UAAM,eAAe,cAAc;AAEnC,UAAM,SAAS;AAAA,MACb,IAAI,UAAU,YAAY,MAAM,GAAG,EAAE,CAAC,KAAK;AAAA,IAC7C;AACA,UAAM,WAAW,GAAG,MAAM,IAAI,IAAI,GAAG,KAAK,GAAG,GAAG,IAAI,GAAG,IAAI,SAAS,IAAI,YAAY,IAAI,IAAI,SAAS;AACrG,UAAM,WAAW,cACb,GAAG,WAAW,IAAI,IAAI,IAAI,KAAK,IAAI,QAAQ,KAC3C,GAAG,IAAI,IAAI,KAAK,IAAI,QAAQ;AAEhC,WAAO;AAAA,MACL,QAAQ,IAAI;AAAA,MACZ,MAAM;AAAA,MACN;AAAA,IACF;AAAA,EACF;AACF;;;AC5FA,OAAO,QAAQ;AACf,OAAO,UAAU;AA0BjB,SAAS,oBAA4B;AACnC,MACE,OAAO,WAAW,WAAW,eAC7B,OAAO,WAAW,OAAO,eAAe,YACxC;AACA,WAAO,WAAW,OAAO,WAAW,EAAE,MAAM,GAAG,EAAE,CAAC;AAAA,EACpD;AACA,SAAO,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,GAAG,EAAE;AAC/C;AAOO,SAAS,iBAAiB,GAAqB;AACpD,MAAI,CAAC,EAAG,QAAO;AAEf,QAAM,OACJ,OAAO,MAAM,YAAY,MAAM,QAAQ,UAAU,IAC7C,OAAQ,EAAwB,IAAI,EAAE,YAAY,IAClD;AACN,QAAM,aACJ,OAAO,MAAM,YAAY,MAAM,QAAQ,eAAe,IACjD,EAAkD,WAC/C,iBACJ,OAAO,MAAM,YAAY,MAAM,QAAQ,gBAAgB,IACrD,OAAQ,EAA8B,UAAU,IAChD;AAER,MAAI,SAAS,YAAY,SAAS,wBAAwB,eAAe,KAAK;AAC5E,WAAO;AAAA,EACT;AACA,MAAI,SAAS,UAAU;AACrB,WAAO;AAAA,EACT;AAEA,QAAM,MACJ,aAAa,QAAQ,EAAE,QAAQ,YAAY,IAAI,OAAO,CAAC,EAAE,YAAY;AAGvE,MACE,IAAI,SAAS,gBAAgB,KAC7B,IAAI,SAAS,eAAe,KAC5B,IAAI,SAAS,WAAW,KACxB,IAAI,SAAS,QAAQ,GACrB;AACA,WAAO;AAAA,EACT;AAGA,SACE,IAAI,SAAS,gBAAgB,KAC7B,IAAI,SAAS,gBAAgB,KAC7B,IAAI,SAAS,QAAQ,KACrB,IAAI,SAAS,aAAa,KAC1B,IAAI,SAAS,qBAAqB;AAEtC;AAQA,eAAsB,yBACpB,QACyC;AACzC,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,aAAa;AAAA,EACf,IAAI;AAEJ,QAAM,qBACJ,QAAQ,YAAY,cAAc,KAAK,CAAC,YAAY;AAEtD,MAAI,gBAAgB,UAAU,WAAW;AACzC,MAAI;AAEJ,WAAS,UAAU,GAAG,UAAU,YAAY,WAAW;AACrD,QAAI;AACF,qBAAe,MAAM,QAAQ,OAAO;AAAA,QAClC,QAAQ,cAAc;AAAA,QACtB,MAAM,cAAc;AAAA,QACpB;AAAA,QACA;AAAA,QACA,QAAQ;AAAA,QACR,aAAa,YAAY;AAAA,QACzB,UAAU,YAAY;AAAA,MACxB,CAAC;AACD;AAAA,IACF,SAAS,GAAG;AACV,UAAI,iBAAiB,CAAC,GAAG;AACvB,YAAI,oBAAoB;AACtB,yBAAe,MAAM,QAAQ,OAAO;AAAA,YAClC,QAAQ,cAAc;AAAA,YACtB,MAAM,cAAc;AAAA,YACpB;AAAA,YACA;AAAA,YACA,QAAQ;AAAA,YACR,aAAa,YAAY;AAAA,YACzB,UAAU,YAAY;AAAA,UACxB,CAAC;AACD;AAAA,QACF;AACA,YAAI,YAAY,kBAAkB,YAAY,kBAAkB;AAC9D,gBAAM,OAAO,uBAAuB,YAAY,cAAc;AAC9D,0BAAgB,UAAU;AAAA,YACxB,GAAG;AAAA,YACH,gBAAgB,GAAG,IAAI,IAAI,kBAAkB,CAAC;AAAA,UAChD,CAAC;AACD;AAAA,QACF;AACA,wBAAgB,UAAU;AAAA,UACxB,GAAG;AAAA,UACH,gBAAgB;AAAA,QAClB,CAAC;AACD;AAAA,MACF;AACA,YAAM;AAAA,IACR;AAAA,EACF;AAEA,MAAI,CAAC,cAAc;AACjB,UAAM,IAAI,MAAM,+CAA+C;AAAA,EACjE;AAEA,SAAO,EAAE,cAAc,cAAc;AACvC;AAgBA,eAAsB,oBACpB,SACiB;AACjB,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI;AACJ,MAAI,CAAC,WAAW;AACd,WAAO;AAAA,EACT;AAEA,QAAM,kBAAkB,eAAe,UAAU,QAAQ,QAAQ,EAAE;AAEnE,MAAI;AACF,UAAM,eAAe,KAAK,QAAQ,SAAS;AAC3C,UAAM,WAAW,KAAK,QAAQ,cAAc,cAAc;AAC1D,UAAM,MAAM,KAAK,SAAS,cAAc,QAAQ;AAChD,QAAI,IAAI,WAAW,IAAI,KAAK,KAAK,WAAW,GAAG,GAAG;AAChD,aAAO;AAAA,IACT;AACA,UAAM,UAAU,KAAK,QAAQ,QAAQ;AACrC,UAAM,GAAG,MAAM,SAAS,EAAE,WAAW,KAAK,CAAC;AAC3C,UAAM,GAAG,UAAU,UAAU,MAAM;AACnC,QAAI,eAAe;AACjB,aAAO,GAAG,cAAc,QAAQ,QAAQ,EAAE,CAAC,IAAI,cAAc;AAAA,IAC/D;AAAA,EACF,QAAQ;AAAA,EAER;AAEA,SAAO;AACT;AAKA,eAAsB,oBACpB,YACA,aACe;AACf,MAAI,CAAC,WAAW,UAAU,CAAC,YAAa;AACxC,QAAM,iBAAiB,YAAY,QAAQ,QAAQ,EAAE;AACrD,MAAI,CAAC,eAAgB;AAErB,QAAM,QAAQ;AAAA,IACZ,WAAW,IAAI,OAAO,QAAQ;AAC5B,UAAI;AACF,cAAM,eAAe,KAAK,QAAQ,GAAG;AACrC,cAAM,WAAW,KAAK,QAAQ,cAAc,cAAc;AAC1D,cAAM,MAAM,KAAK,SAAS,cAAc,QAAQ;AAChD,YAAI,IAAI,WAAW,IAAI,KAAK,KAAK,WAAW,GAAG,EAAG;AAClD,cAAM,GAAG,OAAO,QAAQ;AAAA,MAC1B,QAAQ;AAAA,MAER;AAAA,IACF,CAAC;AAAA,EACH;AACF;;;ACpMO,SAAS,wBAAwB,UAAkB,OAAuB;AAC/E,QAAM,SAAS,SAAS,YAAY,GAAG;AACvC,QAAM,WAAW,SAAS,YAAY,GAAG;AACzC,MAAI,SAAS,YAAY,SAAS,GAAG;AACnC,WAAO,GAAG,SAAS,MAAM,GAAG,MAAM,CAAC,IAAI,KAAK,IAAI,SAAS,MAAM,MAAM,CAAC;AAAA,EACxE;AACA,SAAO,GAAG,QAAQ,IAAI,KAAK;AAC7B;AAEO,SAAS,+BACd,aACA,UACA,kBACU;AACV,MAAI,CAAC,SAAU,QAAO,YAAY,OAAO,CAAC,QAAQ,QAAQ,aAAa;AACvE,MAAI,oBAAoB,CAAC,YAAY,SAAS,aAAa,GAAG;AAC5D,WAAO,CAAC,GAAG,aAAa,aAAa;AAAA,EACvC;AACA,SAAO;AACT;AAEA,eAAsB,sBACpB,QACkC;AAClC,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,SAAS;AAAA,IACT;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI;AAEJ,MAAI,WAAW,SAAS,CAAC,eAAe,QAAQ;AAC9C,WAAO,EAAE,UAAU,CAAC,EAAE;AAAA,EACxB;AAEA,QAAM,eAAe;AAAA,IACnB,GAAG,IAAI;AAAA,MACL,cACG,IAAI,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC,EACxB,OAAO,CAAC,MAAM,OAAO,SAAS,CAAC,KAAK,IAAI,KAAK,IAAI,SAAS;AAAA,IAC/D;AAAA,EACF,EAAE,KAAK,CAAC,GAAG,MAAM,IAAI,CAAC;AAEtB,MAAI,aAAa,WAAW,GAAG;AAC7B,WAAO,EAAE,UAAU,CAAC,EAAE;AAAA,EACxB;AAEA,QAAM,QAAQ,MAAM,UAAU;AAC9B,QAAM,cAAc,KAAK,IAAI,GAAG,KAAK,IAAI,KAAK,WAAW,EAAE,CAAC;AAC5D,QAAM,aAAa,UAAU;AAC7B,QAAM,eAAe,MAAM,cAAc;AAAA,IACvC,QAAQ;AAAA,IACR,kBAAkB,oBAAoB;AAAA,EACxC,CAAC,EAAE,OAAO;AAEV,QAAM,WAAW,MAAM,QAAQ;AAAA,IAC7B,aAAa,IAAI,OAAO,MAA6B;AACnD,UAAI,SAAS,aAAa,MAAM,EAAE,OAAO;AAAA,QACvC,OAAO;AAAA,QACP,oBAAoB;AAAA,QACpB,QAAQ;AAAA,MACV,CAAC;AAED,UAAI,WAAW,QAAQ;AACrB,iBAAS,OAAO,KAAK,EAAE,SAAS,aAAa,SAAS,KAAK,CAAC;AAAA,MAC9D,WAAW,WAAW,OAAO;AAC3B,iBAAS,OAAO,IAAI,EAAE,kBAAkB,EAAE,CAAC;AAAA,MAC7C,WAAW,WAAW,QAAQ;AAC5B,iBAAS,OAAO,KAAK,EAAE,SAAS,aAAa,QAAQ,EAAE,CAAC;AAAA,MAC1D,OAAO;AACL,iBAAS,OAAO,KAAK;AAAA,UACnB,SAAS;AAAA,UACT,QAAQ;AAAA,UACR,mBAAmB;AAAA,UACnB,UAAU;AAAA,QACZ,CAAC;AAAA,MACH;AAEA,YAAM,MAAM,MAAM,OAAO,SAAS,EAAE,mBAAmB,KAAK,CAAC;AAC7D,YAAM,cAAc,wBAAwB,iBAAiB,CAAC;AAC9D,YAAM,kBAAkB,wBAAwB,cAAc,CAAC;AAE/D,YAAM,WAAW,MAAM,QAAQ,OAAO;AAAA,QACpC;AAAA,QACA,MAAM;AAAA,QACN,MAAM,IAAI;AAAA,QACV,aAAa,SAAS,MAAM;AAAA,QAC5B;AAAA,QACA;AAAA,QACA;AAAA,MACF,CAAC;AAED,YAAM,cAAc,MAAM,oBAAoB;AAAA,QAC5C,QAAQ,IAAI;AAAA,QACZ,UAAU;AAAA,QACV,aAAa,SAAS;AAAA,QACtB,aAAa,SAAS;AAAA,QACtB;AAAA,QACA;AAAA,MACF,CAAC;AAED,aAAO;AAAA,QACL,OAAO,IAAI,KAAK,SAAS;AAAA,QACzB,QACE,IAAI,KAAK,UACT,KAAK,IAAI,GAAG,KAAK,MAAO,aAAa,KAAK,IAAI,GAAG,SAAS,IAAK,CAAC,CAAC;AAAA,QACnE,KAAK;AAAA,QACL,MAAM,IAAI,KAAK;AAAA,QACf,aAAa,SAAS;AAAA,MACxB;AAAA,IACF,CAAC;AAAA,EACH;AAEA,QAAM,SAAS;AAAA,IACb,GAAG,SAAS,IAAI,CAAC,MAAM,GAAG,EAAE,GAAG,IAAI,EAAE,KAAK,GAAG;AAAA,IAC7C,GAAG,OAAO,IAAI,SAAS;AAAA,EACzB,EAAE,KAAK,IAAI;AAEX,SAAO,EAAE,UAAU,OAAO;AAC5B;AAEO,SAAS,8BACd,SACA,aACU;AACV,QAAM,SAAS,IAAI,IAAY,WAAW;AAC1C,aAAW,UAAU,OAAO,OAAO,OAAO,GAAG;AAC3C,QAAI,QAAQ,eAAe;AACzB,iBAAW,KAAK,OAAO,eAAe;AACpC,YAAI,OAAO,SAAS,CAAC,KAAK,IAAI,EAAG,QAAO,IAAI,KAAK,MAAM,CAAC,CAAC;AAAA,MAC3D;AAAA,IACF;AAAA,EACF;AACA,SAAO,CAAC,GAAG,MAAM;AACnB;AAEA,eAAsB,qBAAqB,QAOzB;AAChB,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,oBAAoB,CAAC;AAAA,IACrB,kBAAkB,CAAC;AAAA,EACrB,IAAI;AAEJ,QAAM,QAAQ,IAAI,IAAY,iBAAiB;AAC/C,aAAW,KAAK,iBAAiB;AAC/B,UAAM,IAAI,wBAAwB,UAAU,CAAC,CAAC;AAAA,EAChD;AAEA,MAAI,MAAM,SAAS,EAAG;AAEtB,QAAM,QAAQ;AAAA,IACZ,CAAC,GAAG,KAAK,EAAE,IAAI,OAAO,UAAU;AAC9B,YAAM,QAAQ,OAAO,QAAQ,KAAK,EAAE,MAAM,MAAM;AAAA,MAAC,CAAC;AAClD,YAAM,oBAAoB,YAAY,KAAK;AAAA,IAC7C,CAAC;AAAA,EACH;AACF;AAEA,eAAsB,6BAA6B,QAUjC;AAChB,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI;AACJ,MAAI,CAAC,eAAgB;AAErB,MAAI,iBAAiB;AACnB,QAAI;AACF,YAAM,eAAe,MAAM;AAAA,IAC7B,SAAS,WAAW;AAClB,YAAM,QAAQ,OAAO,QAAQ,QAAQ,EAAE,MAAM,MAAM;AAAA,MAAC,CAAC;AACrD,YAAM,oBAAoB,YAAY,QAAQ;AAC9C,YAAM,qBAAqB;AAAA,QACzB;AAAA,QACA;AAAA,QACA,UAAU;AAAA,QACV;AAAA,QACA,mBAAmB;AAAA,MACrB,CAAC;AACD,YAAM;AAAA,IACR;AAAA,EACF,OAAO;AACL,YAAQ,QAAQ,eAAe,MAAM,CAAC,EAAE,MAAM,CAAC,QAAiB;AAC9D,gBAAU,KAAK,EAAE,QAAQ,aAAa,CAAC;AAAA,IACzC,CAAC;AAAA,EACH;AACF;;;ACrOO,SAAS,oBAGd,SAC4C;AAC5C,QAAM;AAAA,IACJ;AAAA,IACA,gBAAgB;AAAA,IAChB,gBAAgB;AAAA,IAChB,mBAAmB;AAAA,IACnB,wBAAwB;AAAA,IACxB,uBAAuB;AAAA,IACvB,UAAU,kBAAkB;AAAA,IAC5B,kBAAkB;AAAA,IAClB,QAAQ;AAAA,IACR,SAAS;AAAA,IACT,yBAAyB;AAAA,IACzB;AAAA,IACA;AAAA,IACA,kBAAkB;AAAA,IAClB;AAAA,IACA,cAAc;AAAA,IACd;AAAA,IACA,wBAAwB;AAAA,IACxB,gBAAgB;AAAA,IAChB,iBAAiB,yBAAyB;AAAA,EAC5C,IAAI;AAEJ,QAAM,gBAAoD;AAAA,IACxD,GAAI,yBAAyB,mBAAmB,CAAC;AAAA,IACjD,GAAI,iBAAiB,CAAC;AAAA,EACxB;AAEA,QAAM,YAAY,IAAI,eAAe,aAAa,EAAE,SAAS,CAAC;AAC9D,QAAM,YAAY,iBAAiB,2BAA2B;AAC9D,QAAM,kBAAkB,oBAAI,IAAsB;AAClD,QAAM,iBAAiB,oBAAI,IAAY;AAEvC,QAAM,gBAAgB,CAAC,SACrB,OAAO,cAAc,IAAI,IAAI;AAE/B,QAAM,oBAAoB,MAAgB;AACxC,UAAM,UAAU,oBAAI,IAAY,CAAC,aAAa,CAAC;AAC/C,eAAW,UAAU,OAAO,OAAO,aAAa,GAAG;AACjD,UAAI,QAAQ,OAAQ,SAAQ,IAAI,OAAO,MAAM;AAAA,IAC/C;AACA,WAAO,CAAC,GAAG,OAAO;AAAA,EACpB;AAEA,QAAM,gBAAgB,MACpB,CAAC,GAAG,IAAI,IAAI,OAAO,OAAO,aAAa,EAAE,IAAI,CAAC,MAAM,GAAG,SAAS,EAAE,OAAO,OAAO,CAAa,CAAC;AAEhG,QAAM,eAAe,CAAC,mBAAsC;AAC1D,QAAI,QAAQ;AACZ,UAAM,OAAO,gBAAgB,SAAS,iBAAiB,OAAO,KAAK,aAAa;AAChF,eAAW,OAAO,MAAM;AACtB,YAAM,IAAI,cAAc,GAAG;AAC3B,UAAI,GAAG,aAAa,EAAE,YAAY,MAAO,SAAQ,EAAE;AAAA,IACrD;AACA,WAAO;AAAA,EACT;AAEA,QAAM,qBAAqB,OAAO,QAAgB,aAAoC;AACpF,UAAM,MAAM,GAAG,MAAM,IAAI,QAAQ;AACjC,UAAM,oBAAoB,gBAAgB,IAAI,GAAG;AACjD,oBAAgB,OAAO,GAAG;AAC1B,UAAM,qBAAqB;AAAA,MACzB;AAAA,MAAS;AAAA,MAAQ;AAAA,MAAU,YAAY,cAAc;AAAA,MAAG;AAAA,MACxD,iBAAiB,8BAA8B,eAAe,cAAc;AAAA,IAC9E,CAAC;AAAA,EACH;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,UAAU,CAAC,QAAiB,QAAQ,WAAW,QAAQ,SAAS,GAAG,IAAI;AAAA,IAEvE,MAAM,cACJ,QACA,cAAyC,CAAC,GACL;AACrC,aAAO,UAAU;AAAA,QACf,MACE,mBAAmB,QAAQ;AAAA,UACzB,eAAe;AAAA,UAAsB;AAAA,UAAuB;AAAA,UAC5D,iBAAiB;AAAA,UAAwB,kBAAkB;AAAA,UAC3D,QAAQ;AAAA,UAAe,GAAG;AAAA,QAC5B,CAAC;AAAA,QACH,EAAE,QAAQ,YAAY,OAAO;AAAA,MAC/B;AAAA,IACF;AAAA,IAEA,MAAM,YACJ,OACA,gBAAiE,CAAC,GACtC;AAC5B,YAAM,eAAe,cAAc,cAAc,MAAM;AACvD,UAAI,cAAc,UAAU,CAAC,cAAc;AACzC,cAAM,IAAI,sBAAsB,mBAAmB,cAAc,MAAM,IAAI;AAAA,MAC7E;AAEA,YAAM,SAAS,cAAc,UAAU,cAAc,UAAU;AAC/D,YAAM,SAAS,cAAc,UAAU,cAAc,UAAU;AAC/D,YAAM,YAAY,cAAc,aAAa,cAAc,aAAa;AACxE,YAAM,WAAW,cAAc,YAAY,cAAc,YAAY;AACrE,YAAM,mBAAmB;AAAA,QACvB,cAAc,YACZ,cAAc,aACb,mBAAmB,CAAC,cAAc,kBAAkB,CAAC,cAAc;AAAA,MACxE;AACA,YAAM,iBAAiB;AAAA,QACrB,cAAc,kBAAkB,cAAc,kBAAkB;AAAA,QAChE;AAAA,QAAU;AAAA,MACZ;AACA,YAAM,gBAAgB,cAAc,iBAAiB,cAAc,iBAAiB;AACpF,YAAM,eAAe,cAAc,gBAAgB,cAAc;AACjE,YAAM,UAAU,cAAc,WAAW,cAAc;AACvD,YAAM,kBAAkB,cAAc,mBAAmB,cAAc,mBAAmB;AAC1F,YAAM,mBAAmB,cAAc,oBAAoB,cAAc,oBAAoB;AAC7F,YAAM,gBAAgB,cAAc,iBAAiB,cAAc;AAEnE,YAAM,YAAY,OAAQ,MAAe,gBAAgB;AACzD,UAAI,WAAW;AACb,cAAM,MAAM,wBAAwB,EAAE,MAAO,MAAe,MAAM,MAAM,MAAM,KAAK,GAAG,WAAW,cAAc;AAC/G,YAAI,CAAC,IAAI,MAAO,OAAM,IAAI,sBAAsB,IAAI,KAAM;AAAA,MAC5D;AAEA,UAAI;AACF,YAAI,iBAAiB,YACjB,OAAO,KAAK,MAAO,MAAe,YAAY,CAAC,IAC9C,MAA6B;AAClC,YAAI,CAAC,kBAAkB,eAAe,WAAW,EAAG,OAAM,IAAI,sBAAsB,eAAe;AAEnG,cAAM,aAAa,wBAAwB,EAAE,MAAM,eAAe,QAAQ,MAAM,MAAM,KAAK,GAAG,WAAW,cAAc;AACvH,YAAI,CAAC,WAAW,MAAO,OAAM,IAAI,sBAAsB,WAAW,KAAM;AAExE,cAAM,UAAU,wBAAwB,gBAAgB,gBAAgB,QAAQ;AAChF,YAAI,QAAQ,WAAW,MAAO,kBAAiB,YAAY,cAAc;AAEzE,cAAM,EAAE,WAAW,UAAU,aAAa,aAAa,IAAI,MAAM,UAAU;AAAA,UACzE,MACE,mBAAmB,gBAAgB;AAAA,YACjC;AAAA,YAAe;AAAA,YAAc;AAAA,YAAS;AAAA,YACtC;AAAA,YAAuB;AAAA,YAAe;AAAA,YACtC,QAAQ;AAAA,YAAe;AAAA,YAAU,QAAQ,cAAc;AAAA,UACzD,CAAC;AAAA,UACH,EAAE,QAAQ,cAAc,OAAO;AAAA,QACjC;AAEA,cAAM,aAAa,UAAU;AAC7B,cAAM,EAAE,cAAc,cAAc,IAAI,MAAM,yBAAyB;AAAA,UACrE;AAAA,UAAS;AAAA,UACT,aAAa;AAAA,YACX;AAAA,YAAQ;AAAA,YAAQ,QAAQ,cAAc;AAAA,YAAQ,QAAQ;AAAA,YACtD,WAAW,kBAAkB,UAAU;AAAA,YACvC,gBAAgB,cAAc;AAAA,YAC9B,kBAAkB,cAAc;AAAA,YAChC;AAAA,YAAa,cAAc,MAAM;AAAA,YAAM,UAAU,cAAc;AAAA,UACjE;AAAA,UACA,MAAM,UAAU;AAAA,UAChB,aAAa,eAAe,QAAQ,gBAAgB,SAAS,UAAU;AAAA,QACzE,CAAC;AAED,cAAM,cAAc,MAAM,oBAAoB;AAAA,UAC5C,QAAQ,UAAU;AAAA,UAAQ,UAAU,cAAc;AAAA,UAClD,aAAa,aAAa;AAAA,UAAM,aAAa,aAAa;AAAA,UAC1D,WAAW,cAAc;AAAA,UAAW,eAAe,cAAc;AAAA,QACnE,CAAC;AAED,cAAM,EAAE,UAAU,OAAO,IACvB,eAAe,UAAU,eAAe,QACpC,MAAM,UAAU;AAAA,UACd,MACE,sBAAsB;AAAA,YACpB,cAAc;AAAA,YAAgB,QAAQ;AAAA,YACtC,SAAS,UAAU,WAAW;AAAA,YAAS,QAAQ;AAAA,YAAe;AAAA,YAC9D,WAAW,UAAU;AAAA,YAAO,YAAY,UAAU;AAAA,YAAQ,SAAS;AAAA,YACnE,iBAAiB,aAAa;AAAA,YAAM,cAAc,cAAc;AAAA,YAChE,QAAQ,cAAc;AAAA,YAAQ;AAAA,YAAS;AAAA,YACvC,QAAQ,QAAQ,cAAc,cAAc,KAAK,CAAC,cAAc;AAAA,YAChE;AAAA,YAAa,UAAU,cAAc;AAAA,YACrC,WAAW,cAAc;AAAA,YAAW,eAAe,cAAc;AAAA,UACnE,CAAC;AAAA,UACH,EAAE,QAAQ,cAAc,OAAO;AAAA,QACjC,IACA,EAAE,UAAU,CAAC,GAAG,QAAQ,OAAU;AAExC,cAAM,eAAe,SAAS,IAAI,CAAC,MAAM,EAAE,WAAW,EAAE,OAAO,OAAO;AACtE,YAAI,aAAa,SAAS,GAAG;AAC3B,0BAAgB,IAAI,GAAG,cAAc,MAAM,IAAI,aAAa,IAAI,IAAI,YAAY;AAChF,mBAAS,QAAQ,CAAC,MAAM,eAAe,IAAI,EAAE,KAAK,CAAC;AAAA,QACrD;AAEA,cAAM,SAA4B;AAAA,UAChC,KAAK;AAAA,UAAa,aAAa,SAAS;AAAA,UAAS,WAAW,SAAS;AAAA,UACrE,GAAI,SAAS,YAAY,EAAE,UAAU,SAAS,SAAS;AAAA,UACvD,SAAS,cAAc,WAAW;AAAA,UAClC,OAAO,UAAU;AAAA,UAAO,QAAQ,UAAU;AAAA,UAAQ,QAAQ,UAAU;AAAA,UACpE,MAAM,UAAU;AAAA,UAAM;AAAA,UAAc;AAAA,UACpC,aAAa,aAAa;AAAA,UAAM,QAAQ,cAAc;AAAA,UACtD,GAAI,cAAc,UAAU,EAAE,QAAQ,cAAc,OAAO;AAAA,UAC3D,GAAI,UAAU,EAAE,OAAO;AAAA,UACvB,GAAI,cAAc,YAAY,EAAE,UAAU,cAAc,SAAS;AAAA,UACjE,GAAI,SAAS,SAAS,KAAK,EAAE,SAAS;AAAA,UACtC,GAAI,UAAU,EAAE,OAAO;AAAA,UACvB,aAAY,oBAAI,KAAK,GAAE,YAAY;AAAA,QACrC;AAEA,cAAM,SAA4B,EAAE,GAAG,QAAQ,SAAS,UAAU,WAAW,WAAW,GAAG;AAC3F,cAAM,6BAA6B;AAAA,UACjC;AAAA,UAAgB;AAAA,UAAiB;AAAA,UAAQ;AAAA,UAAS,QAAQ,cAAc;AAAA,UACxE,UAAU,aAAa;AAAA,UAAM;AAAA,UAAc,YAAY,cAAc;AAAA,UAAG;AAAA,QAC1E,CAAC;AACD,eAAO;AAAA,MACT,SAAS,OAAO;AACd,YAAI,iBAAiB,yBAAyB,iBAAiB,yBAAyB;AACtF,gBAAM;AAAA,QACR;AACA,cAAM,IAAI,MAAM,wBAAwB,iBAAiB,QAAQ,MAAM,UAAU,eAAe,EAAE;AAAA,MACpG;AAAA,IACF;AAAA,IAEA,MAAM,YAAY,YAAoB,QAAgC;AACpE,YAAM,eAAe,UAAU;AAC/B,UAAI;AACF,cAAM,QAAQ,OAAO,cAAc,UAAU;AAC7C,cAAM,oBAAoB,cAAc,GAAG,UAAU;AACrD,cAAM,mBAAmB,cAAc,UAAU;AAAA,MACnD,SAAS,OAAO;AACd,cAAM,IAAI,MAAM,0BAA0B,iBAAiB,QAAQ,MAAM,UAAU,eAAe,EAAE;AAAA,MACtG;AAAA,IACF;AAAA,IAEA,MAAM,YAAY,KAA+B;AAC/C,YAAM,SAAS,QAAQ,WAAW,GAAG;AACrC,YAAM,UAAU,QAAQ,cAAc,MAAM,QAAQ,YAAY,GAAG,IAAI;AACvE,UAAI,WAAW,QAAQ,MAAM;AAC3B,cAAM,oBAAoB,cAAc,GAAG,OAAO,IAAI;AACtD,cAAM,mBAAmB,OAAO,UAAU,eAAe,OAAO,IAAI;AAAA,MACtE;AACA,aAAO;AAAA,IACT;AAAA,EACF;AACF;","names":["r","g","b","fullPath"]}
|