diff --git a/.changeset/unlucky-emus-learn.md b/.changeset/unlucky-emus-learn.md new file mode 100644 index 000000000000..2fdac383a3f8 --- /dev/null +++ b/.changeset/unlucky-emus-learn.md @@ -0,0 +1,5 @@ +--- +'astro': patch +--- + +Added more types and utilities exports related to `astro:assets` to help building custom image components and image services diff --git a/packages/astro/src/@types/astro.ts b/packages/astro/src/@types/astro.ts index 0064994d87b6..e9ac3bc23dfa 100644 --- a/packages/astro/src/@types/astro.ts +++ b/packages/astro/src/@types/astro.ts @@ -30,8 +30,20 @@ export type { RemarkPlugins, ShikiConfig, } from '@astrojs/markdown-remark'; -export type { ExternalImageService, LocalImageService } from '../assets/services/service'; -export type { ImageMetadata, ImageTransform } from '../assets/types'; +export type { + ExternalImageService, + ImageService, + LocalImageService, +} from '../assets/services/service'; +export type { + GetImageResult, + ImageInputFormat, + ImageMetadata, + ImageOutputFormat, + ImageQuality, + ImageQualityPreset, + ImageTransform, +} from '../assets/types'; export type { SSRManifest } from '../core/app/types'; export type { AstroCookies } from '../core/cookies'; diff --git a/packages/astro/src/assets/index.ts b/packages/astro/src/assets/index.ts index 04940ac17da8..6b792fa97db3 100644 --- a/packages/astro/src/assets/index.ts +++ b/packages/astro/src/assets/index.ts @@ -1,5 +1,5 @@ export { getConfiguredImageService, getImage } from './internal.js'; -export { baseService } from './services/service.js'; +export { baseService, isLocalService } from './services/service.js'; export { type LocalImageProps, type RemoteImageProps } from './types.js'; export { emitESMImage } from './utils/emitAsset.js'; export { imageMetadata } from './utils/metadata.js'; diff --git a/packages/astro/src/assets/internal.ts b/packages/astro/src/assets/internal.ts index 5c5d82e77a82..f38b88124680 100644 --- a/packages/astro/src/assets/internal.ts +++ b/packages/astro/src/assets/internal.ts @@ -4,7 +4,7 @@ import type { StaticBuildOptions } from '../core/build/types.js'; import { AstroError, AstroErrorData } from '../core/errors/index.js'; import { prependForwardSlash } from '../core/path.js'; import { isLocalService, type ImageService, type LocalImageService } from './services/service.js'; -import type { ImageMetadata, ImageTransform } from './types.js'; +import type { GetImageResult, ImageMetadata, ImageTransform } from './types.js'; export function isESMImportedImage(src: ImageMetadata | string): src is ImageMetadata { return typeof src === 'object'; @@ -29,13 +29,6 @@ export async function getConfiguredImageService(): Promise { return globalThis.astroAsset.imageService; } -interface GetImageResult { - rawOptions: ImageTransform; - options: ImageTransform; - src: string; - attributes: Record; -} - /** * Get an optimized image and the necessary attributes to render it. * @@ -45,7 +38,7 @@ interface GetImageResult { * import { getImage } from 'astro:assets'; * import originalImage from '../assets/image.png'; * - * const optimizedImage = await getImage({src: originalImage, width: 1280 }) + * const optimizedImage = await getImage({src: originalImage, width: 1280 }); * --- * * ``` diff --git a/packages/astro/src/assets/services/service.ts b/packages/astro/src/assets/services/service.ts index 693ced00f7ab..b167f6aa2651 100644 --- a/packages/astro/src/assets/services/service.ts +++ b/packages/astro/src/assets/services/service.ts @@ -1,7 +1,6 @@ import { AstroError, AstroErrorData } from '../../core/errors/index.js'; import { VALID_INPUT_FORMATS } from '../consts.js'; -import { isESMImportedImage } from '../internal.js'; -import type { ImageTransform, OutputFormat } from '../types.js'; +import { isESMImportedImage } from '../internal.js';import type { ImageOutputFormat, ImageTransform } from '../types.js'; export type ImageService = LocalImageService | ExternalImageService; @@ -71,7 +70,7 @@ export interface LocalImageService extends SharedServiceProps { transform: ( inputBuffer: Buffer, transform: LocalImageTransform - ) => Promise<{ data: Buffer; format: OutputFormat }>; + ) => Promise<{ data: Buffer; format: ImageOutputFormat }>; } export type BaseServiceTransform = { @@ -204,7 +203,7 @@ export const baseService: Omit = { src: params.get('href')!, width: params.has('w') ? parseInt(params.get('w')!) : undefined, height: params.has('h') ? parseInt(params.get('h')!) : undefined, - format: params.get('f') as OutputFormat, + format: params.get('f') as ImageOutputFormat, quality: params.get('q'), }; diff --git a/packages/astro/src/assets/services/sharp.ts b/packages/astro/src/assets/services/sharp.ts index d68f8be43410..04ddf77fa00c 100644 --- a/packages/astro/src/assets/services/sharp.ts +++ b/packages/astro/src/assets/services/sharp.ts @@ -1,5 +1,5 @@ import type { FormatEnum } from 'sharp'; -import type { ImageQualityPreset, OutputFormat } from '../types.js'; +import type { ImageOutputFormat, ImageQualityPreset } from '../types.js'; import { baseService, parseQuality, @@ -64,7 +64,7 @@ const sharpService: LocalImageService = { return { data: data, - format: info.format as OutputFormat, + format: info.format as ImageOutputFormat, }; }, }; diff --git a/packages/astro/src/assets/services/squoosh.ts b/packages/astro/src/assets/services/squoosh.ts index 25cc279399e6..089fcbc81048 100644 --- a/packages/astro/src/assets/services/squoosh.ts +++ b/packages/astro/src/assets/services/squoosh.ts @@ -1,6 +1,6 @@ // TODO: Investigate removing this service once sharp lands WASM support, as libsquoosh is deprecated -import type { ImageQualityPreset, OutputFormat } from '../types.js'; +import type { ImageOutputFormat, ImageQualityPreset } from '../types.js'; import { baseService, parseQuality, @@ -11,7 +11,10 @@ import { processBuffer } from './vendor/squoosh/image-pool.js'; import type { Operation } from './vendor/squoosh/image.js'; const baseQuality = { low: 25, mid: 50, high: 80, max: 100 }; -const qualityTable: Record, Record> = { +const qualityTable: Record< + Exclude, + Record +> = { avif: { // Squoosh's AVIF encoder has a bit of a weird behavior where `62` is technically the maximum, and anything over is overkill max: 62, 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 ac72fc4ef4b4..73bd8545bf11 100644 --- a/packages/astro/src/assets/services/vendor/squoosh/image-pool.ts +++ b/packages/astro/src/assets/services/vendor/squoosh/image-pool.ts @@ -1,7 +1,7 @@ import { isMainThread } from 'node:worker_threads'; import { cpus } from 'os'; import { fileURLToPath } from 'url'; -import type { OutputFormat } from '../../../types.js'; +import type { ImageOutputFormat } from '../../../types.js'; import { getModuleURL } from './emscripten-utils.js'; import type { Operation } from './image.js'; import * as impl from './impl.js'; @@ -88,7 +88,7 @@ function handleJob(params: JobMessage) { export async function processBuffer( buffer: Buffer, operations: Operation[], - encoding: OutputFormat, + encoding: ImageOutputFormat, quality?: number ): Promise { // @ts-ignore diff --git a/packages/astro/src/assets/services/vendor/squoosh/image.ts b/packages/astro/src/assets/services/vendor/squoosh/image.ts index 0b19c5091fe0..4a05d212c40c 100644 --- a/packages/astro/src/assets/services/vendor/squoosh/image.ts +++ b/packages/astro/src/assets/services/vendor/squoosh/image.ts @@ -1,4 +1,4 @@ -import type { OutputFormat } from '../../../types.js'; +import type { ImageOutputFormat } from '../../../types.js'; import * as impl from './impl.js'; type RotateOperation = { @@ -15,7 +15,7 @@ export type Operation = RotateOperation | ResizeOperation export async function processBuffer( buffer: Buffer, operations: Operation[], - encoding: OutputFormat, + encoding: ImageOutputFormat, quality?: number ): Promise { let imageData = await impl.decodeBuffer(buffer) diff --git a/packages/astro/src/assets/types.ts b/packages/astro/src/assets/types.ts index 846e4e4cdc2f..91bf97732f74 100644 --- a/packages/astro/src/assets/types.ts +++ b/packages/astro/src/assets/types.ts @@ -4,8 +4,8 @@ import type { ImageService } from './services/service.js'; export type ImageQualityPreset = 'low' | 'mid' | 'high' | 'max' | (string & {}); export type ImageQuality = ImageQualityPreset | number; -export type InputFormat = (typeof VALID_INPUT_FORMATS)[number] | 'svg'; -export type OutputFormat = (typeof VALID_OUTPUT_FORMATS)[number] | (string & {}); +export type ImageInputFormat = (typeof VALID_INPUT_FORMATS)[number] | 'svg'; +export type ImageOutputFormat = (typeof VALID_OUTPUT_FORMATS)[number] | (string & {}); declare global { // eslint-disable-next-line no-var @@ -23,7 +23,7 @@ export interface ImageMetadata { src: string; width: number; height: number; - format: InputFormat; + format: ImageInputFormat; } /** @@ -31,13 +31,20 @@ export interface ImageMetadata { */ export type ImageTransform = { src: ImageMetadata | string; - width?: number; - height?: number; - quality?: ImageQuality; - format?: OutputFormat; + width?: number | undefined; + height?: number | undefined; + quality?: ImageQuality | undefined; + format?: ImageOutputFormat | undefined; [key: string]: any; }; +export interface GetImageResult { + rawOptions: ImageTransform; + options: ImageTransform; + src: string; + attributes: Record; +} + type WithRequired = T & { [P in K]-?: T[P] }; type ImageSharedProps = T & { /** @@ -94,11 +101,11 @@ export type LocalImageProps = ImageSharedProps & { * ... * ``` */ - format?: OutputFormat; + format?: ImageOutputFormat; /** * Desired quality for the image. Value can either be a preset such as `low` or `high`, or a numeric value from 0 to 100. * - * The perceptual quality of the output image is loader-specific. + * The perceptual quality of the output image is service-specific. * For instance, a certain service might decide that `high` results in a very beautiful image, but another could choose for it to be at best passable. * * **Example**: diff --git a/packages/astro/src/assets/utils/metadata.ts b/packages/astro/src/assets/utils/metadata.ts index 4a722d7319ea..8d2b5c6a2b99 100644 --- a/packages/astro/src/assets/utils/metadata.ts +++ b/packages/astro/src/assets/utils/metadata.ts @@ -1,6 +1,6 @@ import fs from 'node:fs/promises'; import { fileURLToPath } from 'node:url'; -import type { ImageMetadata, InputFormat } from '../types.js'; +import type { ImageInputFormat, ImageMetadata } from '../types.js'; import imageSize from '../vendor/image-size/index.js'; export interface Metadata extends ImageMetadata { @@ -31,7 +31,7 @@ export async function imageMetadata( src: fileURLToPath(src), width: isPortrait ? height : width, height: isPortrait ? width : height, - format: type as InputFormat, + format: type as ImageInputFormat, orientation, }; } diff --git a/packages/astro/src/assets/utils/queryParams.ts b/packages/astro/src/assets/utils/queryParams.ts index 980c3dcd96e9..18acc8876a7e 100644 --- a/packages/astro/src/assets/utils/queryParams.ts +++ b/packages/astro/src/assets/utils/queryParams.ts @@ -1,4 +1,4 @@ -import type { ImageMetadata, InputFormat } from '../types.js'; +import type { ImageInputFormat, ImageMetadata } from '../types.js'; export function getOrigQueryParams( params: URLSearchParams @@ -14,6 +14,6 @@ export function getOrigQueryParams( return { width: parseInt(width), height: parseInt(height), - format: format as InputFormat, + format: format as ImageInputFormat, }; } diff --git a/packages/astro/src/assets/vite-plugin-assets.ts b/packages/astro/src/assets/vite-plugin-assets.ts index 7c018654445f..3512303f3f6a 100644 --- a/packages/astro/src/assets/vite-plugin-assets.ts +++ b/packages/astro/src/assets/vite-plugin-assets.ts @@ -80,7 +80,7 @@ export default function assets({ load(id) { if (id === resolvedVirtualModuleId) { return ` - export { getImage, getConfiguredImageService } from "astro/assets"; + export { getImage, getConfiguredImageService, isLocalService } from "astro/assets"; export { default as Image } from "astro/components/Image.astro"; `; }