astro 2.0.18 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (140) hide show
  1. package/README.md +3 -3
  2. package/client-base.d.ts +27 -0
  3. package/client-image.d.ts +48 -0
  4. package/components/Image.astro +28 -0
  5. package/dist/@types/astro.d.ts +101 -1
  6. package/dist/assets/consts.d.ts +4 -0
  7. package/dist/assets/consts.js +20 -0
  8. package/dist/assets/image-endpoint.d.ts +5 -0
  9. package/dist/assets/image-endpoint.js +50 -0
  10. package/dist/assets/index.d.ts +4 -0
  11. package/dist/assets/index.js +10 -0
  12. package/dist/assets/internal.d.ts +36 -0
  13. package/dist/assets/internal.js +70 -0
  14. package/dist/assets/services/service.d.ts +71 -0
  15. package/dist/assets/services/service.js +88 -0
  16. package/dist/assets/services/sharp.d.ts +3 -0
  17. package/dist/assets/services/sharp.js +57 -0
  18. package/dist/assets/services/squoosh.d.ts +3 -0
  19. package/dist/assets/services/squoosh.js +56 -0
  20. package/dist/assets/services/vendor/squoosh/avif/avif_enc.d.js +11 -0
  21. package/dist/assets/services/vendor/squoosh/avif/avif_node_dec.d.ts +2 -0
  22. package/dist/assets/services/vendor/squoosh/avif/avif_node_dec.js +1628 -0
  23. package/dist/assets/services/vendor/squoosh/avif/avif_node_dec.wasm +0 -0
  24. package/dist/assets/services/vendor/squoosh/avif/avif_node_enc.d.ts +2 -0
  25. package/dist/assets/services/vendor/squoosh/avif/avif_node_enc.js +1850 -0
  26. package/dist/assets/services/vendor/squoosh/avif/avif_node_enc.wasm +0 -0
  27. package/dist/assets/services/vendor/squoosh/codecs.d.ts +158 -0
  28. package/dist/assets/services/vendor/squoosh/codecs.js +284 -0
  29. package/dist/assets/services/vendor/squoosh/copy-wasm.d.ts +1 -0
  30. package/dist/assets/services/vendor/squoosh/copy-wasm.js +24 -0
  31. package/dist/assets/services/vendor/squoosh/emscripten-types.d.js +0 -0
  32. package/dist/assets/services/vendor/squoosh/emscripten-utils.d.ts +9 -0
  33. package/dist/assets/services/vendor/squoosh/emscripten-utils.js +33 -0
  34. package/dist/assets/services/vendor/squoosh/image-pool.d.ts +4 -0
  35. package/dist/assets/services/vendor/squoosh/image-pool.js +94 -0
  36. package/dist/assets/services/vendor/squoosh/image.d.ts +14 -0
  37. package/dist/assets/services/vendor/squoosh/image.js +27 -0
  38. package/dist/assets/services/vendor/squoosh/image_data.d.ts +9 -0
  39. package/dist/assets/services/vendor/squoosh/image_data.js +22 -0
  40. package/dist/assets/services/vendor/squoosh/impl.d.ts +22 -0
  41. package/dist/assets/services/vendor/squoosh/impl.js +110 -0
  42. package/dist/assets/services/vendor/squoosh/mozjpeg/mozjpeg_enc.d.js +11 -0
  43. package/dist/assets/services/vendor/squoosh/mozjpeg/mozjpeg_node_dec.d.ts +2 -0
  44. package/dist/assets/services/vendor/squoosh/mozjpeg/mozjpeg_node_dec.js +1631 -0
  45. package/dist/assets/services/vendor/squoosh/mozjpeg/mozjpeg_node_dec.wasm +0 -0
  46. package/dist/assets/services/vendor/squoosh/mozjpeg/mozjpeg_node_enc.d.ts +2 -0
  47. package/dist/assets/services/vendor/squoosh/mozjpeg/mozjpeg_node_enc.js +1737 -0
  48. package/dist/assets/services/vendor/squoosh/mozjpeg/mozjpeg_node_enc.wasm +0 -0
  49. package/dist/assets/services/vendor/squoosh/png/squoosh_oxipng.d.ts +10 -0
  50. package/dist/assets/services/vendor/squoosh/png/squoosh_oxipng.js +89 -0
  51. package/dist/assets/services/vendor/squoosh/png/squoosh_oxipng_bg.wasm +0 -0
  52. package/dist/assets/services/vendor/squoosh/png/squoosh_png.d.ts +15 -0
  53. package/dist/assets/services/vendor/squoosh/png/squoosh_png.js +138 -0
  54. package/dist/assets/services/vendor/squoosh/png/squoosh_png_bg.wasm +0 -0
  55. package/dist/assets/services/vendor/squoosh/resize/squoosh_resize.d.ts +15 -0
  56. package/dist/assets/services/vendor/squoosh/resize/squoosh_resize.js +95 -0
  57. package/dist/assets/services/vendor/squoosh/resize/squoosh_resize_bg.wasm +0 -0
  58. package/dist/assets/services/vendor/squoosh/rotate/rotate.wasm +0 -0
  59. package/dist/assets/services/vendor/squoosh/utils/execOnce.d.ts +1 -0
  60. package/dist/assets/services/vendor/squoosh/utils/execOnce.js +14 -0
  61. package/dist/assets/services/vendor/squoosh/utils/workerPool.d.ts +22 -0
  62. package/dist/assets/services/vendor/squoosh/utils/workerPool.js +95 -0
  63. package/dist/assets/services/vendor/squoosh/webp/webp_enc.d.js +4 -0
  64. package/dist/assets/services/vendor/squoosh/webp/webp_node_dec.d.ts +2 -0
  65. package/dist/assets/services/vendor/squoosh/webp/webp_node_dec.js +1473 -0
  66. package/dist/assets/services/vendor/squoosh/webp/webp_node_dec.wasm +0 -0
  67. package/dist/assets/services/vendor/squoosh/webp/webp_node_enc.d.ts +2 -0
  68. package/dist/assets/services/vendor/squoosh/webp/webp_node_enc.js +1640 -0
  69. package/dist/assets/services/vendor/squoosh/webp/webp_node_enc.wasm +0 -0
  70. package/dist/assets/types.d.ts +119 -0
  71. package/dist/assets/types.js +0 -0
  72. package/dist/assets/utils/etag.d.ts +12 -0
  73. package/dist/assets/utils/etag.js +28 -0
  74. package/dist/assets/utils/metadata.d.ts +6 -0
  75. package/dist/assets/utils/metadata.js +30 -0
  76. package/dist/assets/utils/queryParams.d.ts +2 -0
  77. package/dist/assets/utils/queryParams.js +16 -0
  78. package/dist/assets/utils/transformToPath.d.ts +2 -0
  79. package/dist/assets/utils/transformToPath.js +17 -0
  80. package/dist/assets/vite-plugin-assets.d.ts +5 -0
  81. package/dist/assets/vite-plugin-assets.js +187 -0
  82. package/dist/cli/check/index.d.ts +81 -2
  83. package/dist/cli/check/index.js +190 -44
  84. package/dist/cli/index.js +39 -16
  85. package/dist/cli/telemetry.js +1 -1
  86. package/dist/content/consts.d.ts +0 -1
  87. package/dist/content/consts.js +1 -3
  88. package/dist/content/internal.d.ts +7 -0
  89. package/dist/content/internal.js +27 -5
  90. package/dist/content/template/virtual-mod.d.mts +1 -0
  91. package/dist/content/types-generator.js +25 -10
  92. package/dist/content/utils.d.ts +16 -13
  93. package/dist/content/utils.js +29 -6
  94. package/dist/content/vite-plugin-content-assets.d.ts +3 -1
  95. package/dist/content/vite-plugin-content-assets.js +10 -6
  96. package/dist/content/vite-plugin-content-imports.js +54 -27
  97. package/dist/content/vite-plugin-content-virtual-mod.js +7 -4
  98. package/dist/core/app/index.js +104 -134
  99. package/dist/core/build/generate.js +30 -5
  100. package/dist/core/build/index.d.ts +2 -0
  101. package/dist/core/build/index.js +16 -0
  102. package/dist/core/build/plugins/plugin-ssr.js +3 -5
  103. package/dist/core/config/config.js +2 -1
  104. package/dist/core/config/schema.d.ts +64 -8
  105. package/dist/core/config/schema.js +17 -3
  106. package/dist/core/config/settings.js +3 -1
  107. package/dist/core/constants.js +1 -1
  108. package/dist/core/cookies/cookies.js +36 -68
  109. package/dist/core/create-vite.js +5 -1
  110. package/dist/core/dev/dev.d.ts +2 -2
  111. package/dist/core/dev/dev.js +24 -4
  112. package/dist/core/errors/dev/vite.js +6 -1
  113. package/dist/core/errors/errors-data.d.ts +17 -1
  114. package/dist/core/errors/errors-data.js +16 -0
  115. package/dist/core/messages.js +2 -2
  116. package/dist/core/path.d.ts +1 -0
  117. package/dist/core/path.js +4 -0
  118. package/dist/core/preview/index.d.ts +3 -1
  119. package/dist/core/preview/index.js +16 -1
  120. package/dist/core/render/dev/environment.js +1 -5
  121. package/dist/core/render/environment.js +1 -2
  122. package/dist/core/render/result.js +13 -35
  123. package/dist/core/sync/index.d.ts +18 -5
  124. package/dist/core/sync/index.js +13 -1
  125. package/dist/integrations/index.js +12 -1
  126. package/dist/runtime/server/render/component.js +1 -1
  127. package/dist/runtime/server/response.js +11 -30
  128. package/dist/vite-plugin-astro-postprocess/index.js +1 -1
  129. package/dist/vite-plugin-astro-server/plugin.js +1 -1
  130. package/dist/vite-plugin-env/index.js +4 -4
  131. package/dist/vite-plugin-inject-env-ts/index.js +17 -2
  132. package/dist/vite-plugin-markdown/content-entry-type.d.ts +7 -0
  133. package/dist/vite-plugin-markdown/content-entry-type.js +39 -0
  134. package/dist/vite-plugin-markdown/index.js +70 -4
  135. package/dist/vite-plugin-ssr-manifest/index.d.ts +2 -0
  136. package/dist/vite-plugin-ssr-manifest/index.js +25 -0
  137. package/package.json +26 -8
  138. package/src/content/template/types.d.ts +18 -9
  139. package/src/content/template/virtual-mod.mjs +6 -0
  140. package/tsconfigs/base.json +6 -1
package/README.md CHANGED
@@ -1,10 +1,10 @@
1
1
  <br/>
2
2
  <p align="center">
3
- <img src="../../assets/social/banner-minimal.png" alt="Astro logo">
3
+ <img src="../../.github/assets/banner.png" alt="Build the web you want">
4
4
  <br/><br/>
5
- <a href="https://astro.build">Astro</a> is a website build tool for the modern web &mdash;
5
+ <a href="https://astro.build">Astro</a> is the all-in-one web framework designed for speed.
6
6
  <br/>
7
- powerful developer experience meets lightweight output.
7
+ Pull your content from anywhere and deploy everywhere, all powered by your favorite UI components and libraries.
8
8
  <br/><br/>
9
9
  </p>
10
10
 
package/client-base.d.ts CHANGED
@@ -1,5 +1,28 @@
1
1
  /// <reference path="./import-meta.d.ts" />
2
2
 
3
+ declare module 'astro:assets' {
4
+ // Exporting things one by one is a bit cumbersome, not sure if there's a better way - erika, 2023-02-03
5
+ type AstroAssets = {
6
+ getImage: typeof import('./dist/assets/index.js').getImage;
7
+ Image: typeof import('./components/Image.astro').default;
8
+ };
9
+
10
+ type WithRequired<T, K extends keyof T> = T & { [P in K]-?: T[P] };
11
+ type Simplify<T> = { [KeyType in keyof T]: T[KeyType] };
12
+ type ImgAttributes = WithRequired<
13
+ Omit<import('./types').HTMLAttributes<'img'>, 'src' | 'width' | 'height'>,
14
+ 'alt'
15
+ >;
16
+
17
+ export type LocalImageProps = Simplify<
18
+ import('./dist/assets/types.js').LocalImageProps<ImgAttributes>
19
+ >;
20
+ export type RemoteImageProps = Simplify<
21
+ import('./dist/assets/types.js').RemoteImageProps<ImgAttributes>
22
+ >;
23
+ export const { getImage, Image }: AstroAssets;
24
+ }
25
+
3
26
  type MD = import('./dist/@types/astro').MarkdownInstance<Record<string, any>>;
4
27
  interface ExportedMarkdownModuleEntities {
5
28
  frontmatter: MD['frontmatter'];
@@ -117,6 +140,10 @@ declare module '*.mdx' {
117
140
  export default load;
118
141
  }
119
142
 
143
+ declare module 'astro:ssr-manifest' {
144
+ export const manifest: import('./dist/@types/astro').SSRManifest;
145
+ }
146
+
120
147
  // Everything below are Vite's types (apart from image types, which are in `client.d.ts`)
121
148
 
122
149
  // CSS modules
@@ -0,0 +1,48 @@
1
+ /// <reference path="./client-base.d.ts" />
2
+
3
+ type InputFormat = 'avif' | 'gif' | 'heic' | 'heif' | 'jpeg' | 'jpg' | 'png' | 'tiff' | 'webp';
4
+
5
+ interface ImageMetadata {
6
+ src: string;
7
+ width: number;
8
+ height: number;
9
+ format: InputFormat;
10
+ }
11
+
12
+ // images
13
+ declare module '*.avif' {
14
+ const metadata: ImageMetadata;
15
+ export default metadata;
16
+ }
17
+ declare module '*.gif' {
18
+ const metadata: ImageMetadata;
19
+ export default metadata;
20
+ }
21
+ declare module '*.heic' {
22
+ const metadata: ImageMetadata;
23
+ export default metadata;
24
+ }
25
+ declare module '*.heif' {
26
+ const metadata: ImageMetadata;
27
+ export default metadata;
28
+ }
29
+ declare module '*.jpeg' {
30
+ const metadata: ImageMetadata;
31
+ export default metadata;
32
+ }
33
+ declare module '*.jpg' {
34
+ const metadata: ImageMetadata;
35
+ export default metadata;
36
+ }
37
+ declare module '*.png' {
38
+ const metadata: ImageMetadata;
39
+ export default metadata;
40
+ }
41
+ declare module '*.tiff' {
42
+ const metadata: ImageMetadata;
43
+ export default metadata;
44
+ }
45
+ declare module '*.webp' {
46
+ const metadata: ImageMetadata;
47
+ export default metadata;
48
+ }
@@ -0,0 +1,28 @@
1
+ ---
2
+ import { getImage, type LocalImageProps, type RemoteImageProps } from 'astro:assets';
3
+ import { AstroError, AstroErrorData } from '../dist/core/errors/index.js';
4
+
5
+ // The TypeScript diagnostic for JSX props uses the last member of the union to suggest props, so it would be better for
6
+ // LocalImageProps to be last. Unfortunately, when we do this the error messages that remote images get are complete nonsense
7
+ // Not 100% sure how to fix this, seems to be a TypeScript issue. Unfortunate.
8
+ type Props = LocalImageProps | RemoteImageProps;
9
+
10
+ const props = Astro.props;
11
+
12
+ if (props.alt === undefined || props.alt === null) {
13
+ throw new AstroError(AstroErrorData.ImageMissingAlt);
14
+ }
15
+
16
+ // As a convenience, allow width and height to be string with a number in them, to match HTML's native `img`.
17
+ if (typeof props.width === 'string') {
18
+ props.width = parseInt(props.width);
19
+ }
20
+
21
+ if (typeof props.height === 'string') {
22
+ props.height = parseInt(props.height);
23
+ }
24
+
25
+ const image = await getImage(props);
26
+ ---
27
+
28
+ <img src={image.src} {...image.attributes} />
@@ -13,9 +13,12 @@ import type { PageBuildData } from '../core/build/types';
13
13
  import type { AstroConfigSchema } from '../core/config';
14
14
  import type { AstroTimer } from '../core/config/timer';
15
15
  import type { AstroCookies } from '../core/cookies';
16
+ import type { LogOptions } from '../core/logger/core';
16
17
  import type { AstroComponentFactory, AstroComponentInstance } from '../runtime/server';
17
18
  import { SUPPORTED_MARKDOWN_FILE_EXTENSIONS } from './../core/constants.js';
18
19
  export type { MarkdownHeading, MarkdownMetadata, MarkdownRenderingResult, RehypePlugins, RemarkPlugins, ShikiConfig, } from '@astrojs/markdown-remark';
20
+ export type { ExternalImageService, LocalImageService } from '../assets/services/service';
21
+ export type { ImageTransform } from '../assets/types';
19
22
  export type { SSRManifest } from '../core/app/types';
20
23
  export type { AstroCookies } from '../core/cookies';
21
24
  export interface AstroBuiltinProps {
@@ -64,6 +67,7 @@ export interface CLIFlags {
64
67
  port?: number;
65
68
  config?: string;
66
69
  drafts?: boolean;
70
+ experimentalAssets?: boolean;
67
71
  }
68
72
  export interface BuildConfig {
69
73
  /**
@@ -648,6 +652,14 @@ export interface AstroUserConfig {
648
652
  server?: ServerConfig | ((options: {
649
653
  command: 'dev' | 'preview';
650
654
  }) => ServerConfig);
655
+ /**
656
+ * @docs
657
+ * @kind heading
658
+ * @name Image options
659
+ */
660
+ image?: {
661
+ service: 'astro/assets/services/sharp' | 'astro/assets/services/squoosh' | (string & {});
662
+ };
651
663
  /**
652
664
  * @docs
653
665
  * @kind heading
@@ -861,7 +873,27 @@ export interface AstroUserConfig {
861
873
  * Astro offers experimental flags to give users early access to new features.
862
874
  * These flags are not guaranteed to be stable.
863
875
  */
864
- experimental?: object;
876
+ experimental?: {
877
+ /**
878
+ * @docs
879
+ * @name experimental.assets
880
+ * @type {boolean}
881
+ * @default `false`
882
+ * @version 2.1.0
883
+ * @description
884
+ * Enable experimental support for optimizing and resizing images. With this enabled, a new `astro:assets` module will be exposed.
885
+ *
886
+ * To enable this feature, set `experimental.assets` to `true` in your Astro config:
887
+ *
888
+ * ```js
889
+ * {
890
+ * experimental: {
891
+ * assets: true,
892
+ * },
893
+ * }
894
+ */
895
+ assets?: boolean;
896
+ };
865
897
  /** @deprecated - Use "integrations" instead. Run Astro to learn more about migrating. */
866
898
  renderers?: never;
867
899
  /** @deprecated `projectRoot` has been renamed to `root` */
@@ -902,11 +934,31 @@ export interface InjectedRoute {
902
934
  export interface AstroConfig extends z.output<typeof AstroConfigSchema> {
903
935
  integrations: AstroIntegration[];
904
936
  }
937
+ export interface ContentEntryType {
938
+ extensions: string[];
939
+ getEntryInfo(params: {
940
+ fileUrl: URL;
941
+ contents: string;
942
+ }): GetEntryInfoReturnType | Promise<GetEntryInfoReturnType>;
943
+ contentModuleTypes?: string;
944
+ }
945
+ type GetEntryInfoReturnType = {
946
+ data: Record<string, unknown>;
947
+ /**
948
+ * Used for error hints to point to correct line and location
949
+ * Should be the untouched data as read from the file,
950
+ * including newlines
951
+ */
952
+ rawData: string;
953
+ body: string;
954
+ slug: string;
955
+ };
905
956
  export interface AstroSettings {
906
957
  config: AstroConfig;
907
958
  adapter: AstroAdapter | undefined;
908
959
  injectedRoutes: InjectedRoute[];
909
960
  pageExtensions: string[];
961
+ contentEntryTypes: ContentEntryType[];
910
962
  renderers: AstroRenderer[];
911
963
  scripts: {
912
964
  stage: InjectedScriptStage;
@@ -990,6 +1042,50 @@ export type GetStaticPathsResultKeyed = GetStaticPathsResult & {
990
1042
  * [Astro Reference](https://docs.astro.build/en/reference/api-reference/#getstaticpaths)
991
1043
  */
992
1044
  export type GetStaticPaths = (options: GetStaticPathsOptions) => Promise<GetStaticPathsResult | GetStaticPathsResult[]> | GetStaticPathsResult | GetStaticPathsResult[];
1045
+ /**
1046
+ * Infers the shape of the `params` property returned by `getStaticPaths()`.
1047
+ *
1048
+ * @example
1049
+ * ```ts
1050
+ * export async function getStaticPaths() {
1051
+ * return results.map((entry) => ({
1052
+ * params: { slug: entry.slug },
1053
+ * }));
1054
+ * }
1055
+ *
1056
+ * type Params = InferGetStaticParamsType<typeof getStaticPaths>;
1057
+ * // ^? { slug: string; }
1058
+ *
1059
+ * const { slug } = Astro.params as Params;
1060
+ * ```
1061
+ */
1062
+ export type InferGetStaticParamsType<T> = T extends () => Promise<infer R> ? R extends Array<infer U> ? U extends {
1063
+ params: infer P;
1064
+ } ? P : never : never : never;
1065
+ /**
1066
+ * Infers the shape of the `props` property returned by `getStaticPaths()`.
1067
+ *
1068
+ * @example
1069
+ * ```ts
1070
+ * export async function getStaticPaths() {
1071
+ * return results.map((entry) => ({
1072
+ * params: { slug: entry.slug },
1073
+ * props: {
1074
+ * propA: true,
1075
+ * propB: 42
1076
+ * },
1077
+ * }));
1078
+ * }
1079
+ *
1080
+ * type Props = InferGetStaticPropsType<typeof getStaticPaths>;
1081
+ * // ^? { propA: boolean; propB: number; }
1082
+ *
1083
+ * const { propA, propB } = Astro.props as Props;
1084
+ * ```
1085
+ */
1086
+ export type InferGetStaticPropsType<T> = T extends () => Promise<infer R> ? R extends Array<infer U> ? U extends {
1087
+ props: infer P;
1088
+ } ? P : never : never : never;
993
1089
  export interface HydrateOptions {
994
1090
  name: string;
995
1091
  value?: string;
@@ -1248,6 +1344,10 @@ export interface AstroIntegration {
1248
1344
  }) => void | Promise<void>;
1249
1345
  };
1250
1346
  }
1347
+ export interface AstroPluginOptions {
1348
+ settings: AstroSettings;
1349
+ logging: LogOptions;
1350
+ }
1251
1351
  export type RouteType = 'page' | 'endpoint';
1252
1352
  export interface RoutePart {
1253
1353
  content: string;
@@ -0,0 +1,4 @@
1
+ export declare const VIRTUAL_MODULE_ID = "astro:assets";
2
+ export declare const VIRTUAL_SERVICE_ID = "virtual:image-service";
3
+ export declare const VALID_INPUT_FORMATS: readonly ["heic", "heif", "avif", "jpeg", "jpg", "png", "tiff", "webp", "gif"];
4
+ export declare const VALID_OUTPUT_FORMATS: readonly ["avif", "png", "webp", "jpeg", "jpg"];
@@ -0,0 +1,20 @@
1
+ const VIRTUAL_MODULE_ID = "astro:assets";
2
+ const VIRTUAL_SERVICE_ID = "virtual:image-service";
3
+ const VALID_INPUT_FORMATS = [
4
+ "heic",
5
+ "heif",
6
+ "avif",
7
+ "jpeg",
8
+ "jpg",
9
+ "png",
10
+ "tiff",
11
+ "webp",
12
+ "gif"
13
+ ];
14
+ const VALID_OUTPUT_FORMATS = ["avif", "png", "webp", "jpeg", "jpg"];
15
+ export {
16
+ VALID_INPUT_FORMATS,
17
+ VALID_OUTPUT_FORMATS,
18
+ VIRTUAL_MODULE_ID,
19
+ VIRTUAL_SERVICE_ID
20
+ };
@@ -0,0 +1,5 @@
1
+ import type { APIRoute } from '../@types/astro.js';
2
+ /**
3
+ * Endpoint used in SSR to serve optimized images
4
+ */
5
+ export declare const get: APIRoute;
@@ -0,0 +1,50 @@
1
+ import mime from "mime";
2
+ import { isRemotePath } from "../core/path.js";
3
+ import { getConfiguredImageService } from "./internal.js";
4
+ import { isLocalService } from "./services/service.js";
5
+ import { etag } from "./utils/etag.js";
6
+ async function loadRemoteImage(src) {
7
+ try {
8
+ const res = await fetch(src);
9
+ if (!res.ok) {
10
+ return void 0;
11
+ }
12
+ return Buffer.from(await res.arrayBuffer());
13
+ } catch (err) {
14
+ return void 0;
15
+ }
16
+ }
17
+ const get = async ({ request }) => {
18
+ try {
19
+ const imageService = await getConfiguredImageService();
20
+ if (!isLocalService(imageService)) {
21
+ throw new Error("Configured image service is not a local service");
22
+ }
23
+ const url = new URL(request.url);
24
+ const transform = await imageService.parseURL(url);
25
+ if (!transform || !transform.src) {
26
+ throw new Error("Incorrect transform returned by `parseURL`");
27
+ }
28
+ let inputBuffer = void 0;
29
+ const sourceUrl = isRemotePath(transform.src) ? new URL(transform.src) : new URL(transform.src, url.origin);
30
+ inputBuffer = await loadRemoteImage(sourceUrl);
31
+ if (!inputBuffer) {
32
+ return new Response("Not Found", { status: 404 });
33
+ }
34
+ const { data, format } = await imageService.transform(inputBuffer, transform);
35
+ return new Response(data, {
36
+ status: 200,
37
+ headers: {
38
+ "Content-Type": mime.getType(format) || "",
39
+ "Cache-Control": "public, max-age=31536000",
40
+ ETag: etag(data.toString()),
41
+ Date: new Date().toUTCString()
42
+ }
43
+ });
44
+ } catch (err) {
45
+ return new Response(`Server Error: ${err}`, { status: 500 });
46
+ }
47
+ };
48
+ export {
49
+ get
50
+ };
@@ -0,0 +1,4 @@
1
+ export { getConfiguredImageService, getImage } from './internal.js';
2
+ export { baseService } from './services/service.js';
3
+ export { type LocalImageProps, type RemoteImageProps } from './types.js';
4
+ export { imageMetadata } from './utils/metadata.js';
@@ -0,0 +1,10 @@
1
+ import { getConfiguredImageService, getImage } from "./internal.js";
2
+ import { baseService } from "./services/service.js";
3
+ import {} from "./types.js";
4
+ import { imageMetadata } from "./utils/metadata.js";
5
+ export {
6
+ baseService,
7
+ getConfiguredImageService,
8
+ getImage,
9
+ imageMetadata
10
+ };
@@ -0,0 +1,36 @@
1
+ import { StaticBuildOptions } from '../core/build/types.js';
2
+ import { ImageService } from './services/service.js';
3
+ import type { ImageMetadata, ImageTransform } from './types.js';
4
+ export declare function isESMImportedImage(src: ImageMetadata | string): src is ImageMetadata;
5
+ export declare function getConfiguredImageService(): Promise<ImageService>;
6
+ interface GetImageResult {
7
+ options: ImageTransform;
8
+ src: string;
9
+ attributes: Record<string, any>;
10
+ }
11
+ /**
12
+ * Get an optimized image and the necessary attributes to render it.
13
+ *
14
+ * **Example**
15
+ * ```astro
16
+ * ---
17
+ * import { getImage } from 'astro:assets';
18
+ * import originalImage from '../assets/image.png';
19
+ *
20
+ * const optimizedImage = await getImage({src: originalImage, width: 1280 })
21
+ * ---
22
+ * <img src={optimizedImage.src} {...optimizedImage.attributes} />
23
+ * ```
24
+ *
25
+ * This is functionally equivalent to using the `<Image />` component, as the component calls this function internally.
26
+ */
27
+ export declare function getImage(options: ImageTransform): Promise<GetImageResult>;
28
+ export declare function getStaticImageList(): Iterable<[ImageTransform, string]>;
29
+ interface GenerationData {
30
+ weight: {
31
+ before: number;
32
+ after: number;
33
+ };
34
+ }
35
+ export declare function generateImage(buildOpts: StaticBuildOptions, options: ImageTransform, filepath: string): Promise<GenerationData | undefined>;
36
+ export {};
@@ -0,0 +1,70 @@
1
+ import fs from "node:fs";
2
+ import { AstroError, AstroErrorData } from "../core/errors/index.js";
3
+ import { isLocalService } from "./services/service.js";
4
+ function isESMImportedImage(src) {
5
+ return typeof src === "object";
6
+ }
7
+ async function getConfiguredImageService() {
8
+ if (!globalThis.astroAsset.imageService) {
9
+ const { default: service } = await import("virtual:image-service").catch((e) => {
10
+ const error = new AstroError(AstroErrorData.InvalidImageService);
11
+ error.cause = e;
12
+ throw error;
13
+ });
14
+ globalThis.astroAsset.imageService = service;
15
+ return service;
16
+ }
17
+ return globalThis.astroAsset.imageService;
18
+ }
19
+ async function getImage(options) {
20
+ const service = await getConfiguredImageService();
21
+ let imageURL = service.getURL(options);
22
+ if (isLocalService(service) && globalThis.astroAsset.addStaticImage) {
23
+ imageURL = globalThis.astroAsset.addStaticImage(options);
24
+ }
25
+ return {
26
+ options,
27
+ src: imageURL,
28
+ attributes: service.getHTMLAttributes !== void 0 ? service.getHTMLAttributes(options) : {}
29
+ };
30
+ }
31
+ function getStaticImageList() {
32
+ var _a, _b;
33
+ if (!((_a = globalThis == null ? void 0 : globalThis.astroAsset) == null ? void 0 : _a.staticImages)) {
34
+ return [];
35
+ }
36
+ return (_b = globalThis.astroAsset.staticImages) == null ? void 0 : _b.entries();
37
+ }
38
+ async function generateImage(buildOpts, options, filepath) {
39
+ if (!isESMImportedImage(options.src)) {
40
+ return void 0;
41
+ }
42
+ const imageService = await getConfiguredImageService();
43
+ let serverRoot, clientRoot;
44
+ if (buildOpts.settings.config.output === "server") {
45
+ serverRoot = buildOpts.settings.config.build.server;
46
+ clientRoot = buildOpts.settings.config.build.client;
47
+ } else {
48
+ serverRoot = buildOpts.settings.config.outDir;
49
+ clientRoot = buildOpts.settings.config.outDir;
50
+ }
51
+ const fileData = await fs.promises.readFile(new URL("." + options.src.src, serverRoot));
52
+ const resultData = await imageService.transform(fileData, { ...options, src: options.src.src });
53
+ const finalFileURL = new URL("." + filepath, clientRoot);
54
+ const finalFolderURL = new URL("./", finalFileURL);
55
+ await fs.promises.mkdir(finalFolderURL, { recursive: true });
56
+ await fs.promises.writeFile(finalFileURL, resultData.data);
57
+ return {
58
+ weight: {
59
+ before: Math.trunc(fileData.byteLength / 1024),
60
+ after: Math.trunc(resultData.data.byteLength / 1024)
61
+ }
62
+ };
63
+ }
64
+ export {
65
+ generateImage,
66
+ getConfiguredImageService,
67
+ getImage,
68
+ getStaticImageList,
69
+ isESMImportedImage
70
+ };
@@ -0,0 +1,71 @@
1
+ /// <reference types="node" />
2
+ import { ImageTransform, OutputFormat } from '../types.js';
3
+ export type ImageService = LocalImageService | ExternalImageService;
4
+ export declare function isLocalService(service: ImageService | undefined): service is LocalImageService;
5
+ export declare function parseQuality(quality: string): string | number;
6
+ interface SharedServiceProps {
7
+ /**
8
+ * Return the URL to the endpoint or URL your images are generated from.
9
+ *
10
+ * For a local service, your service should expose an endpoint handling the image requests, or use Astro's at `/_image`.
11
+ *
12
+ * For external services, this should point to the URL your images are coming from, for instance, `/_vercel/image`
13
+ *
14
+ */
15
+ getURL: (options: ImageTransform) => string;
16
+ /**
17
+ * Return any additional HTML attributes separate from `src` that your service requires to show the image properly.
18
+ *
19
+ * For example, you might want to return the `width` and `height` to avoid CLS, or a particular `class` or `style`.
20
+ * In most cases, you'll want to return directly what your user supplied you, minus the attributes that were used to generate the image.
21
+ */
22
+ getHTMLAttributes?: (options: ImageTransform) => Record<string, any>;
23
+ }
24
+ export type ExternalImageService = SharedServiceProps;
25
+ type LocalImageTransform = {
26
+ src: string;
27
+ [key: string]: any;
28
+ };
29
+ export interface LocalImageService extends SharedServiceProps {
30
+ /**
31
+ * Parse the requested parameters passed in the URL from `getURL` back into an object to be used later by `transform`
32
+ *
33
+ * In most cases, this will get query parameters using, for example, `params.get('width')` and return those.
34
+ */
35
+ parseURL: (url: URL) => LocalImageTransform | undefined;
36
+ /**
37
+ * Performs the image transformations on the input image and returns both the binary data and
38
+ * final image format of the optimized image.
39
+ */
40
+ transform: (inputBuffer: Buffer, transform: LocalImageTransform) => Promise<{
41
+ data: Buffer;
42
+ format: OutputFormat;
43
+ }>;
44
+ }
45
+ export type BaseServiceTransform = {
46
+ src: string;
47
+ width?: number;
48
+ height?: number;
49
+ format?: string | null;
50
+ quality?: string | null;
51
+ };
52
+ /**
53
+ * Basic local service using the included `_image` endpoint.
54
+ * This service intentionally does not implement `transform`.
55
+ *
56
+ * Example usage:
57
+ * ```ts
58
+ * const service = {
59
+ * getURL: baseService.getURL,
60
+ * parseURL: baseService.parseURL,
61
+ * getHTMLAttributes: baseService.getHTMLAttributes,
62
+ * async transform(inputBuffer, transformOptions) {...}
63
+ * }
64
+ * ```
65
+ *
66
+ * This service only supports the following properties: `width`, `height`, `format` and `quality`.
67
+ * Additionally, remote URLs are passed as-is.
68
+ *
69
+ */
70
+ export declare const baseService: Omit<LocalImageService, 'transform'>;
71
+ export {};
@@ -0,0 +1,88 @@
1
+ import { AstroError, AstroErrorData } from "../../core/errors/index.js";
2
+ import { isRemotePath } from "../../core/path.js";
3
+ import { isESMImportedImage } from "../internal.js";
4
+ function isLocalService(service) {
5
+ if (!service) {
6
+ return false;
7
+ }
8
+ return "transform" in service;
9
+ }
10
+ function parseQuality(quality) {
11
+ let result = parseInt(quality);
12
+ if (Number.isNaN(result)) {
13
+ return quality;
14
+ }
15
+ return result;
16
+ }
17
+ const baseService = {
18
+ getHTMLAttributes(options) {
19
+ let targetWidth = options.width;
20
+ let targetHeight = options.height;
21
+ if (isESMImportedImage(options.src)) {
22
+ const aspectRatio = options.src.width / options.src.height;
23
+ if (targetHeight && !targetWidth) {
24
+ targetWidth = Math.round(targetHeight * aspectRatio);
25
+ } else if (targetWidth && !targetHeight) {
26
+ targetHeight = Math.round(targetWidth / aspectRatio);
27
+ } else {
28
+ targetWidth = options.src.width;
29
+ targetHeight = options.src.height;
30
+ }
31
+ }
32
+ const { src, width, height, format, quality, ...attributes } = options;
33
+ return {
34
+ ...attributes,
35
+ width: targetWidth,
36
+ height: targetHeight,
37
+ loading: attributes.loading ?? "lazy",
38
+ decoding: attributes.decoding ?? "async"
39
+ };
40
+ },
41
+ getURL(options) {
42
+ if (!isESMImportedImage(options.src)) {
43
+ let missingDimension;
44
+ if (!options.width && !options.height) {
45
+ missingDimension = "both";
46
+ } else if (!options.width && options.height) {
47
+ missingDimension = "width";
48
+ } else if (options.width && !options.height) {
49
+ missingDimension = "height";
50
+ }
51
+ if (missingDimension) {
52
+ throw new AstroError({
53
+ ...AstroErrorData.MissingImageDimension,
54
+ message: AstroErrorData.MissingImageDimension.message(missingDimension)
55
+ });
56
+ }
57
+ }
58
+ if (!isESMImportedImage(options.src) && isRemotePath(options.src)) {
59
+ return options.src;
60
+ }
61
+ const searchParams = new URLSearchParams();
62
+ searchParams.append("href", isESMImportedImage(options.src) ? options.src.src : options.src);
63
+ options.width && searchParams.append("w", options.width.toString());
64
+ options.height && searchParams.append("h", options.height.toString());
65
+ options.quality && searchParams.append("q", options.quality.toString());
66
+ options.format && searchParams.append("f", options.format);
67
+ return "/_image?" + searchParams;
68
+ },
69
+ parseURL(url) {
70
+ const params = url.searchParams;
71
+ if (!params.has("href")) {
72
+ return void 0;
73
+ }
74
+ const transform = {
75
+ src: params.get("href"),
76
+ width: params.has("w") ? parseInt(params.get("w")) : void 0,
77
+ height: params.has("h") ? parseInt(params.get("h")) : void 0,
78
+ format: params.get("f"),
79
+ quality: params.get("q")
80
+ };
81
+ return transform;
82
+ }
83
+ };
84
+ export {
85
+ baseService,
86
+ isLocalService,
87
+ parseQuality
88
+ };
@@ -0,0 +1,3 @@
1
+ import { LocalImageService } from './service.js';
2
+ declare const sharpService: LocalImageService;
3
+ export default sharpService;