diff --git a/.changeset/ten-sloths-invent.md b/.changeset/ten-sloths-invent.md new file mode 100644 index 000000000000..12c5bdf5fe2e --- /dev/null +++ b/.changeset/ten-sloths-invent.md @@ -0,0 +1,7 @@ +--- +'astro': patch +--- + +Use UInt8Array instead of Buffer for both the input and return values of the `transform()` hook of the Image Service API to ensure compatibility with non-Node runtimes. + +This change is unlikely to affect you, but if you were previously relying on the return value being a Buffer, you may convert an `UInt8Array` to a `Buffer` using `Buffer.from(your_array)`. diff --git a/packages/astro/src/assets/build/generate.ts b/packages/astro/src/assets/build/generate.ts index c34e136ddd52..be637c26da7a 100644 --- a/packages/astro/src/assets/build/generate.ts +++ b/packages/astro/src/assets/build/generate.ts @@ -41,7 +41,7 @@ type AssetEnv = { assetsFolder: AstroConfig['build']['assets']; }; -type ImageData = { data: Buffer; expires: number }; +type ImageData = { data: Uint8Array; expires: number }; export async function prepareAssetsGenerationEnv( pipeline: BuildPipeline, diff --git a/packages/astro/src/assets/endpoint/generic.ts b/packages/astro/src/assets/endpoint/generic.ts index 140189fe088c..a158448edbcf 100644 --- a/packages/astro/src/assets/endpoint/generic.ts +++ b/packages/astro/src/assets/endpoint/generic.ts @@ -14,7 +14,7 @@ async function loadRemoteImage(src: URL) { return undefined; } - return Buffer.from(await res.arrayBuffer()); + return await res.arrayBuffer(); } catch (err: unknown) { return undefined; } @@ -38,7 +38,7 @@ export const GET: APIRoute = async ({ request }) => { throw new Error('Incorrect transform returned by `parseURL`'); } - let inputBuffer: Buffer | undefined = undefined; + let inputBuffer: ArrayBuffer | undefined = undefined; const sourceUrl = isRemotePath(transform.src) ? new URL(transform.src) @@ -54,7 +54,11 @@ export const GET: APIRoute = async ({ request }) => { return new Response('Not Found', { status: 404 }); } - const { data, format } = await imageService.transform(inputBuffer, transform, imageConfig); + const { data, format } = await imageService.transform( + new Uint8Array(inputBuffer), + transform, + imageConfig + ); return new Response(data, { status: 200, diff --git a/packages/astro/src/assets/services/service.ts b/packages/astro/src/assets/services/service.ts index 5a063d4670ae..ab647b7107a0 100644 --- a/packages/astro/src/assets/services/service.ts +++ b/packages/astro/src/assets/services/service.ts @@ -96,10 +96,10 @@ export interface LocalImageService = Record - ) => Promise<{ data: Buffer; format: ImageOutputFormat }>; + ) => Promise<{ data: Uint8Array; format: ImageOutputFormat }>; /** * A list of properties that should be used to generate the hash for the image. diff --git a/packages/astro/src/assets/services/squoosh.ts b/packages/astro/src/assets/services/squoosh.ts index 5be5d40770c6..c9586af10d6c 100644 --- a/packages/astro/src/assets/services/squoosh.ts +++ b/packages/astro/src/assets/services/squoosh.ts @@ -30,7 +30,7 @@ const qualityTable: Record< }; async function getRotationForEXIF( - inputBuffer: Buffer, + inputBuffer: Uint8Array, src?: string ): Promise { const meta = await imageMetadata(inputBuffer, src); diff --git a/packages/astro/src/assets/services/vendor/squoosh/image-pool.ts b/packages/astro/src/assets/services/vendor/squoosh/image-pool.ts index 839708f03b41..cc2df9c96ffe 100644 --- a/packages/astro/src/assets/services/vendor/squoosh/image-pool.ts +++ b/packages/astro/src/assets/services/vendor/squoosh/image-pool.ts @@ -19,7 +19,7 @@ const getWorker = execOnce(() => { type DecodeParams = { operation: 'decode'; - buffer: Buffer; + buffer: Uint8Array; }; type ResizeParams = { operation: 'resize'; @@ -86,7 +86,7 @@ function handleJob(params: JobMessage) { } export async function processBuffer( - buffer: Buffer, + buffer: Uint8Array, operations: Operation[], encoding: ImageOutputFormat, quality?: number diff --git a/packages/astro/src/assets/utils/metadata.ts b/packages/astro/src/assets/utils/metadata.ts index 2ee96a7aca28..175bacc050e7 100644 --- a/packages/astro/src/assets/utils/metadata.ts +++ b/packages/astro/src/assets/utils/metadata.ts @@ -3,9 +3,10 @@ import { AstroError, AstroErrorData } from '../../core/errors/index.js'; import type { ImageInputFormat, ImageMetadata } from '../types.js'; export async function imageMetadata( - data: Buffer, + data: Uint8Array, src?: string ): Promise> { + // @ts-expect-error probe-image-size types are wrong, it does accept Uint8Array. From the README: "Sync version can eat arrays, typed arrays and buffers." const result = probe.sync(data); if (result === null) {