{"version":3,"file":"image-endpoint.mjs","names":["genericGET"],"sources":["../../src/astro/image-endpoint.ts"],"sourcesContent":["/**\n * Node image endpoint -- the `image.endpoint` EmDash installs on non-Cloudflare\n * platforms whose image service is local (sharp).\n *\n * It wraps Astro's generic endpoint: for an EmDash media URL it loads the source\n * bytes straight from the storage adapter (no HTTP, so it works behind any auth\n * gate) and runs the configured image service's `transform`; every other image\n * is delegated to the stock endpoint unchanged.\n */\n\nimport type { APIRoute } from \"astro\";\n// @ts-ignore - astro/assets internal endpoint, resolved by the consumer's Astro build\nimport { GET as genericGET } from \"astro/assets/endpoint/generic\";\n// @ts-ignore - astro:assets is resolved by the consumer's Astro build\nimport { getConfiguredImageService, imageConfig } from \"astro:assets\";\n\nimport {\n\tIMMUTABLE_IMAGE_CACHE,\n\tmatchInternalMediaKey,\n\toriginalMediaHeaders,\n} from \"../media/image-endpoint.js\";\n\nexport const prerender = false;\n\nconst FORMAT_MIME: Record<string, string> = {\n\twebp: \"image/webp\",\n\tavif: \"image/avif\",\n\tpng: \"image/png\",\n\tjpeg: \"image/jpeg\",\n\tjpg: \"image/jpeg\",\n\tgif: \"image/gif\",\n};\n\nfunction isNotFound(error: unknown): boolean {\n\treturn (\n\t\terror instanceof Error &&\n\t\t(error.message.includes(\"not found\") || error.message.includes(\"NOT_FOUND\"))\n\t);\n}\n\nfunction streamOriginal(body: ReadableStream<Uint8Array>, contentType: string): Response {\n\treturn new Response(body, { status: 200, headers: originalMediaHeaders(contentType) });\n}\n\nexport const GET: APIRoute = async (ctx) => {\n\tconst url = new URL(ctx.request.url);\n\tconst key = matchInternalMediaKey(url.searchParams.get(\"href\"));\n\tconst storage = ctx.locals.emdash?.storage;\n\n\t// Not EmDash media, or storage unavailable: let the stock endpoint handle it\n\t// (bundled assets, allowed remote, `publicUrl` media).\n\tif (!key || !storage) return genericGET(ctx);\n\n\tconst service = await getConfiguredImageService();\n\tif (!(\"transform\" in service)) return genericGET(ctx);\n\n\ttry {\n\t\tconst source = await storage.download(key);\n\n\t\t// Only raster images are transformable; serve anything else unchanged.\n\t\tif (!source.contentType.startsWith(\"image/\")) {\n\t\t\treturn streamOriginal(source.body, source.contentType);\n\t\t}\n\n\t\tconst transform = await service.parseURL(url, imageConfig);\n\t\tif (!transform) return streamOriginal(source.body, source.contentType);\n\n\t\tconst inputBuffer = new Uint8Array(await new Response(source.body).arrayBuffer());\n\t\tconst { data, format } = await service.transform(inputBuffer, transform, imageConfig);\n\n\t\treturn new Response(data, {\n\t\t\tstatus: 200,\n\t\t\theaders: {\n\t\t\t\t\"Content-Type\": FORMAT_MIME[format] ?? source.contentType,\n\t\t\t\t\"Cache-Control\": IMMUTABLE_IMAGE_CACHE,\n\t\t\t\t\"X-Content-Type-Options\": \"nosniff\",\n\t\t\t},\n\t\t});\n\t} catch (error) {\n\t\tif (isNotFound(error)) return new Response(\"Not Found\", { status: 404 });\n\t\tconsole.error(\"[emdash] image transform failed:\", error);\n\t\treturn new Response(\"Internal Server Error\", { status: 500 });\n\t}\n};\n"],"mappings":";;;;;AAsBA,MAAa,YAAY;AAEzB,MAAM,cAAsC;CAC3C,MAAM;CACN,MAAM;CACN,KAAK;CACL,MAAM;CACN,KAAK;CACL,KAAK;CACL;AAED,SAAS,WAAW,OAAyB;AAC5C,QACC,iBAAiB,UAChB,MAAM,QAAQ,SAAS,YAAY,IAAI,MAAM,QAAQ,SAAS,YAAY;;AAI7E,SAAS,eAAe,MAAkC,aAA+B;AACxF,QAAO,IAAI,SAAS,MAAM;EAAE,QAAQ;EAAK,SAAS,qBAAqB,YAAY;EAAE,CAAC;;AAGvF,MAAa,MAAgB,OAAO,QAAQ;CAC3C,MAAM,MAAM,IAAI,IAAI,IAAI,QAAQ,IAAI;CACpC,MAAM,MAAM,sBAAsB,IAAI,aAAa,IAAI,OAAO,CAAC;CAC/D,MAAM,UAAU,IAAI,OAAO,QAAQ;AAInC,KAAI,CAAC,OAAO,CAAC,QAAS,QAAOA,MAAW,IAAI;CAE5C,MAAM,UAAU,MAAM,2BAA2B;AACjD,KAAI,EAAE,eAAe,SAAU,QAAOA,MAAW,IAAI;AAErD,KAAI;EACH,MAAM,SAAS,MAAM,QAAQ,SAAS,IAAI;AAG1C,MAAI,CAAC,OAAO,YAAY,WAAW,SAAS,CAC3C,QAAO,eAAe,OAAO,MAAM,OAAO,YAAY;EAGvD,MAAM,YAAY,MAAM,QAAQ,SAAS,KAAK,YAAY;AAC1D,MAAI,CAAC,UAAW,QAAO,eAAe,OAAO,MAAM,OAAO,YAAY;EAEtE,MAAM,cAAc,IAAI,WAAW,MAAM,IAAI,SAAS,OAAO,KAAK,CAAC,aAAa,CAAC;EACjF,MAAM,EAAE,MAAM,WAAW,MAAM,QAAQ,UAAU,aAAa,WAAW,YAAY;AAErF,SAAO,IAAI,SAAS,MAAM;GACzB,QAAQ;GACR,SAAS;IACR,gBAAgB,YAAY,WAAW,OAAO;IAC9C,iBAAiB;IACjB,0BAA0B;IAC1B;GACD,CAAC;UACM,OAAO;AACf,MAAI,WAAW,MAAM,CAAE,QAAO,IAAI,SAAS,aAAa,EAAE,QAAQ,KAAK,CAAC;AACxE,UAAQ,MAAM,oCAAoC,MAAM;AACxD,SAAO,IAAI,SAAS,yBAAyB,EAAE,QAAQ,KAAK,CAAC"}