Skip to content

Commit

Permalink
fix(assets): Use uint8arrays instead of Buffer in code that can run o…
Browse files Browse the repository at this point in the history
…utside of Node (#9029)

* fix(assets): Use uint8arrays instead of Buffer in code that can run outside of Node

* chore: changeset

* docs: update changeset with more information on what to do if a Buffer is important

* nit: do a patch instead
  • Loading branch information
Princesseuh authored and natemoo-re committed Nov 22, 2023
1 parent 148e8f8 commit 50a6f66
Show file tree
Hide file tree
Showing 7 changed files with 22 additions and 10 deletions.
7 changes: 7 additions & 0 deletions .changeset/ten-sloths-invent.md
Original file line number Diff line number Diff line change
@@ -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)`.
2 changes: 1 addition & 1 deletion packages/astro/src/assets/build/generate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
10 changes: 7 additions & 3 deletions packages/astro/src/assets/endpoint/generic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand All @@ -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)
Expand All @@ -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,
Expand Down
4 changes: 2 additions & 2 deletions packages/astro/src/assets/services/service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,10 +96,10 @@ export interface LocalImageService<T extends Record<string, any> = Record<string
* final image format of the optimized image.
*/
transform: (
inputBuffer: Buffer,
inputBuffer: Uint8Array,
transform: LocalImageTransform,
imageConfig: ImageConfig<T>
) => 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.
Expand Down
2 changes: 1 addition & 1 deletion packages/astro/src/assets/services/squoosh.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ const qualityTable: Record<
};

async function getRotationForEXIF(
inputBuffer: Buffer,
inputBuffer: Uint8Array,
src?: string
): Promise<Operation | undefined> {
const meta = await imageMetadata(inputBuffer, src);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ const getWorker = execOnce(() => {

type DecodeParams = {
operation: 'decode';
buffer: Buffer;
buffer: Uint8Array;
};
type ResizeParams = {
operation: 'resize';
Expand Down Expand Up @@ -86,7 +86,7 @@ function handleJob(params: JobMessage) {
}

export async function processBuffer(
buffer: Buffer,
buffer: Uint8Array,
operations: Operation[],
encoding: ImageOutputFormat,
quality?: number
Expand Down
3 changes: 2 additions & 1 deletion packages/astro/src/assets/utils/metadata.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<Omit<ImageMetadata, 'src' | 'fsPath'>> {
// @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) {
Expand Down

0 comments on commit 50a6f66

Please sign in to comment.