diff --git a/src/lib/server/ai/image-preprocess.ts b/src/lib/server/ai/image-preprocess.ts index f69a91f..62474f0 100644 --- a/src/lib/server/ai/image-preprocess.ts +++ b/src/lib/server/ai/image-preprocess.ts @@ -1,4 +1,5 @@ import type SharpType from 'sharp'; +import { createRequire } from 'node:module'; const MAX_EDGE = 1600; const JPEG_QUALITY = 85; @@ -8,20 +9,25 @@ export type PreprocessedImage = { mimeType: 'image/jpeg'; }; -// Dynamic import: adapter-node bundelt server-code via Rollup/@rollup/plugin-commonjs, -// und das packt sharp's dynamic-require fuer die native Plattform-.node-Binary -// kaputt ins Bundle. Mit import() via Vite's Hint-Kommentar kann Rollup sharp -// nicht auflösen und laesst es zur Laufzeit regulaer aus node_modules laden. -async function loadSharp(): Promise { - const mod = await import(/* @vite-ignore */ 'sharp'); - return (mod as unknown as { default: typeof SharpType }).default ?? (mod as unknown as typeof SharpType); +// sharp per Node-Runtime-require laden, nicht via ES-Import: adapter-node +// bundelt ES-Imports (auch dynamische, auch mit @vite-ignore) ins Server- +// Bundle, was sharp's internes dynamic-require fuer die Plattform-.node-Binary +// zerstoert. createRequire + require() ist pure Node-Runtime-Logik, die +// Rollup nicht anfasst -- sharp wird regulaer aus node_modules geladen. +const nodeRequire = createRequire(import.meta.url); +let sharpModule: typeof SharpType | null = null; +function loadSharp(): typeof SharpType { + if (!sharpModule) { + sharpModule = nodeRequire('sharp') as typeof SharpType; + } + return sharpModule; } // Resize auf max 1600px lange Kante, JPEG re-encode, Metadata strippen. // sharp liest HEIC/HEIF transparent, wenn libheif im libvips-Build enthalten ist // (in Alpine's vips-dev + in den offiziellen sharp-Prebuilds). export async function preprocessImage(input: Buffer): Promise { - const sharp = await loadSharp(); + const sharp = loadSharp(); const pipeline = sharp(input, { failOn: 'error' }).rotate(); // respect EXIF orientation const meta = await pipeline.metadata(); if (!meta.width || !meta.height) {