summaryrefslogtreecommitdiff
path: root/packages/integrations/image/src/index.ts
diff options
context:
space:
mode:
Diffstat (limited to 'packages/integrations/image/src/index.ts')
-rw-r--r--packages/integrations/image/src/index.ts119
1 files changed, 115 insertions, 4 deletions
diff --git a/packages/integrations/image/src/index.ts b/packages/integrations/image/src/index.ts
index 81ef8c6b9..234b1646d 100644
--- a/packages/integrations/image/src/index.ts
+++ b/packages/integrations/image/src/index.ts
@@ -1,5 +1,116 @@
-import integration from './integration.js';
-export * from './lib/get-image.js';
-export * from './lib/get-picture.js';
+import type { AstroConfig, AstroIntegration } from 'astro';
+import { ssgBuild } from './build/ssg.js';
+import { ssrBuild } from './build/ssr.js';
+import { PKG_NAME, ROUTE_PATTERN } from './constants.js';
+import { ImageService, TransformOptions } from './loaders/index.js';
+import { filenameFormat, propsToFilename } from './utils/paths.js';
+import { createPlugin } from './vite-plugin-astro-image.js';
-export default integration;
+export { getImage } from './lib/get-image.js';
+export { getPicture } from './lib/get-picture.js';
+export * from './loaders/index.js';
+export type { ImageMetadata} from './vite-plugin-astro-image.js';
+
+interface ImageIntegration {
+ loader?: ImageService;
+ addStaticImage?: (transform: TransformOptions) => void;
+ filenameFormat?: (transform: TransformOptions, searchParams: URLSearchParams) => string;
+}
+
+declare global {
+ // eslint-disable-next-line no-var
+ var astroImage: ImageIntegration | undefined;
+}
+
+export interface IntegrationOptions {
+ /**
+ * Entry point for the @type {HostedImageService} or @type {LocalImageService} to be used.
+ */
+ serviceEntryPoint?: string;
+}
+
+export default function integration(options: IntegrationOptions = {}): AstroIntegration {
+ const resolvedOptions = {
+ serviceEntryPoint: '@astrojs/image/sharp',
+ ...options,
+ };
+
+ // During SSG builds, this is used to track all transformed images required.
+ const staticImages = new Map<string, Map<string, TransformOptions>>();
+
+ let _config: AstroConfig;
+ let output: 'server' | 'static';
+
+ function getViteConfiguration() {
+ return {
+ plugins: [createPlugin(_config, resolvedOptions)],
+ optimizeDeps: {
+ include: ['image-size', 'sharp'],
+ },
+ ssr: {
+ noExternal: ['@astrojs/image', resolvedOptions.serviceEntryPoint],
+ },
+ };
+ }
+
+ return {
+ name: PKG_NAME,
+ hooks: {
+ 'astro:config:setup': ({ command, config, injectRoute, updateConfig }) => {
+ _config = config;
+
+ // Always treat `astro dev` as SSR mode, even without an adapter
+ output = command === 'dev' ? 'server' : config.output;
+
+ updateConfig({ vite: getViteConfiguration() });
+
+ if (output === 'server') {
+ injectRoute({
+ pattern: ROUTE_PATTERN,
+ entryPoint:
+ command === 'dev' ? '@astrojs/image/endpoints/dev' : '@astrojs/image/endpoints/prod',
+ });
+ }
+ },
+ 'astro:server:setup': async () => {
+ globalThis.astroImage = {};
+ },
+ 'astro:build:setup': () => {
+ // Used to cache all images rendered to HTML
+ // Added to globalThis to share the same map in Node and Vite
+ function addStaticImage(transform: TransformOptions) {
+ const srcTranforms = staticImages.has(transform.src)
+ ? staticImages.get(transform.src)!
+ : new Map<string, TransformOptions>();
+
+ srcTranforms.set(propsToFilename(transform), transform);
+
+ staticImages.set(transform.src, srcTranforms);
+ }
+
+ // Helpers for building static images should only be available for SSG
+ globalThis.astroImage =
+ output === 'static'
+ ? {
+ addStaticImage,
+ filenameFormat,
+ }
+ : {};
+ },
+ 'astro:build:done': async ({ dir }) => {
+ if (output === 'server') {
+ // for SSR builds, copy all image files from src to dist
+ // to make sure they are available for use in production
+ await ssrBuild({ srcDir: _config.srcDir, outDir: dir });
+ } else {
+ // for SSG builds, build all requested image transforms to dist
+ const loader = globalThis?.astroImage?.loader;
+
+ if (loader && 'transform' in loader && staticImages.size > 0) {
+ await ssgBuild({ loader, staticImages, srcDir: _config.srcDir, outDir: dir });
+ }
+ }
+ },
+ },
+ };
+}