/** * Lazy, guarded loader for wasm-vips (libvips compiled to WASM — the same engine * as `sharp`). It's used as a progressive enhancement for high-quality (lanczos3) * downscaling. Initialization is attempted once; on any failure — or in browsers * without cross-origin isolation / SharedArrayBuffer — we resolve to null and the * caller falls back to the canvas resampler. */ // wasm-vips ships rich types, but we treat it loosely at this dynamic boundary. type Vips = any; let vipsPromise: Promise | null = null; function withTimeout(promise: Promise, ms: number, label: string): Promise { return new Promise((resolve, reject) => { const timer = setTimeout(() => reject(new Error(`${label} timed out after ${ms}ms`)), ms); promise.then( (value) => { clearTimeout(timer); resolve(value); }, (err) => { clearTimeout(timer); reject(err); }, ); }); } export function loadVips(): Promise { if (vipsPromise) return vipsPromise; vipsPromise = (async () => { try { const mod: any = await import("wasm-vips"); const factory = (mod.default ?? mod) as (opts?: unknown) => Promise; // dynamicLibraries: [] skips the optional HEIF/JXL/SVG modules we don't need. const vips = await withTimeout(factory({ dynamicLibraries: [] }), 20_000, "wasm-vips init"); return vips ?? null; } catch (err) { console.warn("[wimp] wasm-vips unavailable — falling back to the canvas engine.", err); return null; } })(); return vipsPromise; }