/** * apps/worker — sharp accessor + a minimal structural type for the surface * the files pipeline uses. * * sharp ships CJS types (`export =`) plus a separate ESM `dist/index` type * surface (nodenext resolution) that lags the runtime API (e.g. no * `limitInputPixels` on the ESM `Sharp` type). Rather than couple the * pipeline to sharp's type churn, we consume a small structural interface — * the exact methods we call — and resolve the callable once (ESM * `import("sharp")` puts the callable on `.default`). */ /** The pipeline's view of a sharp pipeline instance. */ export interface SharpInstance { rotate(): SharpInstance; resize(opts: { width: number; withoutEnlargement?: boolean }): SharpInstance; metadata(): Promise<{ width?: number; height?: number; orientation?: number }>; toFormat(name: string): SharpInstance; png(): SharpInstance; toBuffer(): Promise; } /** Sharp constructor options the pipeline uses. `limitInputPixels` is a * CONSTRUCTOR option (input memory cap), NOT a pipeline method. */ export interface SharpOptions { limitInputPixels?: number; } export type SharpConstructor = (input: string | Buffer, options?: SharpOptions) => SharpInstance; let cached: SharpConstructor | null = null; export async function getSharp(): Promise { if (cached) return cached; // eslint-disable-next-line @typescript-eslint/no-explicit-any const mod: any = await import("sharp"); const fn: SharpConstructor = (mod?.default ?? mod) as SharpConstructor; cached = fn; return fn; }