astro 4.10.2 → 4.11.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 (72) hide show
  1. package/components/Code.astro +9 -0
  2. package/dist/@types/astro.d.ts +43 -39
  3. package/dist/actions/runtime/virtual/server.d.ts +1 -1
  4. package/dist/assets/internal.d.ts +1 -1
  5. package/dist/assets/internal.js +6 -0
  6. package/dist/assets/types.d.ts +8 -2
  7. package/dist/assets/types.js +7 -0
  8. package/dist/container/index.d.ts +32 -1
  9. package/dist/container/index.js +45 -0
  10. package/dist/container/pipeline.d.ts +0 -1
  11. package/dist/container/pipeline.js +13 -32
  12. package/dist/container/vite-plugin-container.d.ts +2 -0
  13. package/dist/container/vite-plugin-container.js +15 -0
  14. package/dist/content/runtime-assets.d.ts +3 -3
  15. package/dist/content/types-generator.js +55 -34
  16. package/dist/content/utils.d.ts +11 -0
  17. package/dist/content/utils.js +49 -0
  18. package/dist/content/vite-plugin-content-imports.d.ts +3 -1
  19. package/dist/content/vite-plugin-content-imports.js +15 -4
  20. package/dist/core/app/index.d.ts +4 -0
  21. package/dist/core/app/index.js +17 -6
  22. package/dist/core/app/pipeline.d.ts +1 -2
  23. package/dist/core/app/pipeline.js +11 -39
  24. package/dist/core/base-pipeline.d.ts +0 -9
  25. package/dist/core/base-pipeline.js +1 -1
  26. package/dist/core/build/internal.d.ts +4 -0
  27. package/dist/core/build/internal.js +2 -1
  28. package/dist/core/build/page-data.js +2 -4
  29. package/dist/core/build/pipeline.d.ts +1 -2
  30. package/dist/core/build/pipeline.js +16 -42
  31. package/dist/core/build/plugins/plugin-chunks.js +6 -0
  32. package/dist/core/build/plugins/plugin-prerender.js +55 -48
  33. package/dist/core/build/plugins/plugin-ssr.js +15 -12
  34. package/dist/core/build/static-build.js +36 -44
  35. package/dist/core/build/types.d.ts +0 -1
  36. package/dist/core/config/schema.d.ts +4 -156
  37. package/dist/core/constants.d.ts +4 -0
  38. package/dist/core/constants.js +3 -1
  39. package/dist/core/cookies/cookies.d.ts +5 -0
  40. package/dist/core/cookies/cookies.js +12 -0
  41. package/dist/core/cookies/response.d.ts +1 -0
  42. package/dist/core/cookies/response.js +1 -0
  43. package/dist/core/create-vite.js +4 -6
  44. package/dist/core/dev/dev.js +1 -1
  45. package/dist/core/errors/errors-data.d.ts +40 -11
  46. package/dist/core/errors/errors-data.js +13 -6
  47. package/dist/core/messages.js +2 -2
  48. package/dist/core/render-context.d.ts +1 -1
  49. package/dist/core/render-context.js +22 -6
  50. package/dist/core/request.js +7 -1
  51. package/dist/core/routing/astro-designed-error-pages.d.ts +1 -0
  52. package/dist/core/routing/astro-designed-error-pages.js +15 -1
  53. package/dist/core/routing/rewrite.d.ts +10 -0
  54. package/dist/core/routing/rewrite.js +41 -0
  55. package/dist/core/util.js +5 -2
  56. package/dist/env/constants.d.ts +0 -1
  57. package/dist/env/constants.js +0 -2
  58. package/dist/env/runtime.d.ts +3 -1
  59. package/dist/env/runtime.js +8 -1
  60. package/dist/env/schema.d.ts +2 -78
  61. package/dist/env/schema.js +1 -17
  62. package/dist/env/vite-plugin-env.js +15 -15
  63. package/dist/jsx/server.d.ts +3 -5
  64. package/dist/jsx/server.js +3 -1
  65. package/dist/vite-plugin-astro/index.js +1 -1
  66. package/dist/vite-plugin-astro-server/pipeline.d.ts +1 -2
  67. package/dist/vite-plugin-astro-server/pipeline.js +15 -42
  68. package/dist/vite-plugin-astro-server/request.js +1 -1
  69. package/dist/vite-plugin-astro-server/route.js +53 -94
  70. package/package.json +8 -7
  71. package/templates/env/module.mjs +14 -5
  72. package/templates/env/types.d.ts +1 -12
@@ -3,6 +3,7 @@ import type { ThemePresets } from '@astrojs/markdown-remark';
3
3
  import type {
4
4
  BuiltinLanguage,
5
5
  LanguageRegistration,
6
+ ShikiTransformer,
6
7
  SpecialLanguage,
7
8
  ThemeRegistration,
8
9
  ThemeRegistrationRaw,
@@ -50,6 +51,12 @@ interface Props extends Omit<HTMLAttributes<'pre'>, 'lang'> {
50
51
  * @default false
51
52
  */
52
53
  inline?: boolean;
54
+ /**
55
+ * Shiki transformers to customize the generated HTML by manipulating the hast tree.
56
+ * Supports all transformers listed here: https://shiki.style/packages/transformers#transformers
57
+ * Instructions for custom transformers: https://shiki.style/guide/transformers
58
+ */
59
+ transformers?: ShikiTransformer[];
53
60
  }
54
61
 
55
62
  const {
@@ -59,6 +66,7 @@ const {
59
66
  themes = {},
60
67
  wrap = false,
61
68
  inline = false,
69
+ transformers = [],
62
70
  ...rest
63
71
  } = Astro.props;
64
72
 
@@ -85,6 +93,7 @@ const highlighter = await getCachedHighlighter({
85
93
  theme,
86
94
  themes,
87
95
  wrap,
96
+ transformers,
88
97
  });
89
98
 
90
99
  const html = await highlighter.highlight(code, typeof lang === 'string' ? lang : lang.name, {
@@ -211,7 +211,7 @@ export interface AstroGlobal<Props extends Record<string, any> = Record<string,
211
211
  /**
212
212
  * The <Astro.self /> element allows a component to reference itself recursively.
213
213
  *
214
- * [Astro reference](https://docs.astro.build/en/guides/api-reference/#astroself)
214
+ * [Astro reference](https://docs.astro.build/en/reference/api-reference/#astroself)
215
215
  */
216
216
  self: Self;
217
217
  /** Utility functions for modifying an Astro component’s slotted children
@@ -1295,7 +1295,7 @@ export interface AstroUserConfig {
1295
1295
  * import remarkToc from 'remark-toc';
1296
1296
  * {
1297
1297
  * markdown: {
1298
- * remarkPlugins: [remarkToc]
1298
+ * remarkPlugins: [ [remarkToc, { heading: "contents"} ] ]
1299
1299
  * }
1300
1300
  * }
1301
1301
  * ```
@@ -1931,17 +1931,17 @@ export interface AstroUserConfig {
1931
1931
  *
1932
1932
  * ```astro
1933
1933
  * ---
1934
- * import { PUBLIC_APP_ID } from "astro:env/client"
1935
- * import { PUBLIC_API_URL, getSecret } from "astro:env/server"
1936
- * const API_TOKEN = getSecret("API_TOKEN")
1934
+ * import { APP_ID } from "astro:env/client"
1935
+ * import { API_URL, API_TOKEN, getSecret } from "astro:env/server"
1936
+ * const NODE_ENV = getSecret("NODE_ENV")
1937
1937
  *
1938
- * const data = await fetch(`${PUBLIC_API_URL}/users`, {
1938
+ * const data = await fetch(`${API_URL}/users`, {
1939
1939
  * method: "POST",
1940
1940
  * headers: {
1941
1941
  * "Content-Type": "application/json",
1942
1942
  * "Authorization": `Bearer ${API_TOKEN}`
1943
1943
  * },
1944
- * body: JSON.stringify({ appId: PUBLIC_APP_ID })
1944
+ * body: JSON.stringify({ appId: APP_ID, nodeEnv: NODE_ENV })
1945
1945
  * })
1946
1946
  * ---
1947
1947
  * ```
@@ -1956,8 +1956,8 @@ export interface AstroUserConfig {
1956
1956
  * experimental: {
1957
1957
  * env: {
1958
1958
  * schema: {
1959
- * PUBLIC_API_URL: envField.string({ context: "client", access: "public", optional: true }),
1960
- * PUBLIC_PORT: envField.number({ context: "server", access: "public", default: 4321 }),
1959
+ * API_URL: envField.string({ context: "client", access: "public", optional: true }),
1960
+ * PORT: envField.number({ context: "server", access: "public", default: 4321 }),
1961
1961
  * API_SECRET: envField.string({ context: "server", access: "secret" }),
1962
1962
  * }
1963
1963
  * }
@@ -1965,28 +1965,27 @@ export interface AstroUserConfig {
1965
1965
  * })
1966
1966
  * ```
1967
1967
  *
1968
- * There are currently three data types supported: strings, numbers and booleans.
1968
+ * There are currently four data types supported: strings, numbers, booleans and enums.
1969
1969
  *
1970
1970
  * There are three kinds of environment variables, determined by the combination of `context` (client or server) and `access` (secret or public) settings defined in your [`env.schema`](#experimentalenvschema):
1971
1971
  *
1972
1972
  * - **Public client variables**: These variables end up in both your final client and server bundles, and can be accessed from both client and server through the `astro:env/client` module:
1973
1973
  *
1974
1974
  * ```js
1975
- * import { PUBLIC_API_URL } from "astro:env/client"
1975
+ * import { API_URL } from "astro:env/client"
1976
1976
  * ```
1977
1977
  *
1978
1978
  * - **Public server variables**: These variables end up in your final server bundle and can be accessed on the server through the `astro:env/server` module:
1979
1979
  *
1980
1980
  * ```js
1981
- * import { PUBLIC_PORT } from "astro:env/server"
1981
+ * import { PORT } from "astro:env/server"
1982
1982
  * ```
1983
1983
  *
1984
- * - **Secret server variables**: These variables are not part of your final bundle and can be accessed on the server through the `getSecret()` helper function available from the `astro:env/server` module:
1984
+ * - **Secret server variables**: These variables are not part of your final bundle and can be accessed on the server through the `astro:env/server` module. The `getSecret()` helper function can be used to retrieve secrets not specified in the schema:
1985
1985
  *
1986
1986
  * ```js
1987
- * import { getSecret } from "astro:env/server"
1987
+ * import { API_SECRET, getSecret } from "astro:env/server"
1988
1988
  *
1989
- * const API_SECRET = getSecret("API_SECRET") // typed
1990
1989
  * const SECRET_NOT_IN_SCHEMA = getSecret("SECRET_NOT_IN_SCHEMA") // string | undefined
1991
1990
  * ```
1992
1991
  *
@@ -2013,8 +2012,8 @@ export interface AstroUserConfig {
2013
2012
  * experimental: {
2014
2013
  * env: {
2015
2014
  * schema: {
2016
- * PUBLIC_API_URL: envField.string({ context: "client", access: "public", optional: true }),
2017
- * PUBLIC_PORT: envField.number({ context: "server", access: "public", default: 4321 }),
2015
+ * API_URL: envField.string({ context: "client", access: "public", optional: true }),
2016
+ * PORT: envField.number({ context: "server", access: "public", default: 4321 }),
2018
2017
  * API_SECRET: envField.string({ context: "server", access: "secret" }),
2019
2018
  * }
2020
2019
  * }
@@ -2604,7 +2603,7 @@ export interface APIContext<Props extends Record<string, any> = Record<string, a
2604
2603
  * }
2605
2604
  * ```
2606
2605
  *
2607
- * [Reference](https://docs.astro.build/en/guides/api-reference/#contextprops)
2606
+ * [Reference](https://docs.astro.build/en/reference/api-reference/#contextprops)
2608
2607
  */
2609
2608
  props: AstroSharedContext<Props, APIParams>['props'];
2610
2609
  /**
@@ -2711,27 +2710,32 @@ export interface AstroRenderer {
2711
2710
  /** @deprecated Vite plugins should transform the JSX instead */
2712
2711
  jsxTransformOptions?: JSXTransformFn;
2713
2712
  }
2714
- export interface SSRLoadedRenderer extends AstroRenderer {
2715
- ssr: {
2716
- check: AsyncRendererComponentFn<boolean>;
2717
- renderToStaticMarkup: AsyncRendererComponentFn<{
2718
- html: string;
2719
- attrs?: Record<string, string>;
2720
- }>;
2721
- supportsAstroStaticSlot?: boolean;
2722
- /**
2723
- * If provided, Astro will call this function and inject the returned
2724
- * script in the HTML before the first component handled by this renderer.
2725
- *
2726
- * This feature is needed by some renderers (in particular, by Solid). The
2727
- * Solid official hydration script sets up a page-level data structure.
2728
- * It is mainly used to transfer data between the server side render phase
2729
- * and the browser application state. Solid Components rendered later in
2730
- * the HTML may inject tiny scripts into the HTML that call into this
2731
- * page-level data structure.
2732
- */
2733
- renderHydrationScript?: () => string;
2734
- };
2713
+ export interface NamedSSRLoadedRendererValue extends SSRLoadedRendererValue {
2714
+ name: string;
2715
+ }
2716
+ export interface SSRLoadedRendererValue {
2717
+ name?: string;
2718
+ check: AsyncRendererComponentFn<boolean>;
2719
+ renderToStaticMarkup: AsyncRendererComponentFn<{
2720
+ html: string;
2721
+ attrs?: Record<string, string>;
2722
+ }>;
2723
+ supportsAstroStaticSlot?: boolean;
2724
+ /**
2725
+ * If provided, Astro will call this function and inject the returned
2726
+ * script in the HTML before the first component handled by this renderer.
2727
+ *
2728
+ * This feature is needed by some renderers (in particular, by Solid). The
2729
+ * Solid official hydration script sets up a page-level data structure.
2730
+ * It is mainly used to transfer data between the server side render phase
2731
+ * and the browser application state. Solid Components rendered later in
2732
+ * the HTML may inject tiny scripts into the HTML that call into this
2733
+ * page-level data structure.
2734
+ */
2735
+ renderHydrationScript?: () => string;
2736
+ }
2737
+ export interface SSRLoadedRenderer extends Pick<AstroRenderer, 'name' | 'clientEntrypoint'> {
2738
+ ssr: SSRLoadedRendererValue;
2735
2739
  }
2736
2740
  export type HookParameters<Hook extends keyof AstroIntegration['hooks'], Fn = AstroIntegration['hooks'][Hook]> = Fn extends (...args: any) => any ? Parameters<Fn>[0] : never;
2737
2741
  export interface AstroIntegration {
@@ -14,7 +14,7 @@ export type ActionClient<TOutput, TAccept extends Accept, TInputSchema extends I
14
14
  } : ((input?: any) => Promise<Awaited<TOutput>>) & {
15
15
  safe: (input?: any) => Promise<SafeResult<never, Awaited<TOutput>>>;
16
16
  };
17
- export declare function defineAction<TOutput, TAccept extends Accept = 'json', TInputSchema extends InputSchema<Accept> | undefined = TAccept extends 'form' ? z.ZodType<FormData> : undefined>({ accept, input: inputSchema, handler, }: {
17
+ export declare function defineAction<TOutput, TAccept extends Accept, TInputSchema extends InputSchema<Accept> | undefined = TAccept extends 'form' ? z.ZodType<FormData> : undefined>({ accept, input: inputSchema, handler, }: {
18
18
  input?: TInputSchema;
19
19
  accept?: TAccept;
20
20
  handler: Handler<TInputSchema, TOutput>;
@@ -1,5 +1,5 @@
1
1
  import type { AstroConfig } from '../@types/astro.js';
2
2
  import { type ImageService } from './services/service.js';
3
- import type { GetImageResult, UnresolvedImageTransform } from './types.js';
3
+ import { type GetImageResult, type UnresolvedImageTransform } from './types.js';
4
4
  export declare function getConfiguredImageService(): Promise<ImageService>;
5
5
  export declare function getImage(options: UnresolvedImageTransform, imageConfig: AstroConfig['image']): Promise<GetImageResult>;
@@ -1,6 +1,9 @@
1
1
  import { AstroError, AstroErrorData } from "../core/errors/index.js";
2
2
  import { DEFAULT_HASH_PROPS } from "./consts.js";
3
3
  import { isLocalService } from "./services/service.js";
4
+ import {
5
+ isImageMetadata
6
+ } from "./types.js";
4
7
  import { isESMImportedImage, isRemoteImage, resolveSrc } from "./utils/imageKind.js";
5
8
  import { probe } from "./utils/remoteProbe.js";
6
9
  async function getConfiguredImageService() {
@@ -36,6 +39,9 @@ async function getImage(options, imageConfig) {
36
39
  )
37
40
  });
38
41
  }
42
+ if (isImageMetadata(options)) {
43
+ throw new AstroError(AstroErrorData.ExpectedNotESMImage);
44
+ }
39
45
  const service = await getConfiguredImageService();
40
46
  const resolvedOptions = {
41
47
  ...options,
@@ -20,16 +20,20 @@ declare global {
20
20
  referencedImages?: Set<string>;
21
21
  };
22
22
  }
23
+ declare const isESMImport: unique symbol;
24
+ export type OmitBrand<T> = Omit<T, typeof isESMImport>;
23
25
  /**
24
26
  * Type returned by ESM imports of images
25
27
  */
26
- export interface ImageMetadata {
28
+ export type ImageMetadata = {
27
29
  src: string;
28
30
  width: number;
29
31
  height: number;
30
32
  format: ImageInputFormat;
31
33
  orientation?: number;
32
- }
34
+ [isESMImport]?: true;
35
+ };
36
+ export declare function isImageMetadata(src: any): src is ImageMetadata;
33
37
  /**
34
38
  * A yet to be completed with an url `SrcSetValue`. Other hooks will only see a resolved value, where the URL of the image has been added.
35
39
  */
@@ -49,6 +53,8 @@ export type UnresolvedImageTransform = Omit<ImageTransform, 'src'> & {
49
53
  default: ImageMetadata;
50
54
  }>;
51
55
  inferSize?: boolean;
56
+ } & {
57
+ [isESMImport]?: never;
52
58
  };
53
59
  /**
54
60
  * Options accepted by the image transformation service.
@@ -0,0 +1,7 @@
1
+ const isESMImport = Symbol("#isESM");
2
+ function isImageMetadata(src) {
3
+ return src.fsPath && !("fsPath" in src);
4
+ }
5
+ export {
6
+ isImageMetadata
7
+ };
@@ -1,4 +1,4 @@
1
- import type { AstroUserConfig, Props, RouteType, SSRLoadedRenderer, SSRManifest, SSRResult } from '../@types/astro.js';
1
+ import type { AstroUserConfig, NamedSSRLoadedRendererValue, Props, RouteType, SSRLoadedRenderer, SSRLoadedRendererValue, SSRManifest, SSRResult } from '../@types/astro.js';
2
2
  import type { AstroComponentFactory } from '../runtime/server/index.js';
3
3
  /**
4
4
  * Options to be passed when rendering a route
@@ -59,6 +59,13 @@ export type ContainerRenderOptions = {
59
59
  */
60
60
  props?: Props;
61
61
  };
62
+ export type AddServerRenderer = {
63
+ renderer: NamedSSRLoadedRendererValue;
64
+ name: never;
65
+ } | {
66
+ renderer: SSRLoadedRendererValue;
67
+ name: string;
68
+ };
62
69
  export type AstroContainerUserConfig = Omit<AstroUserConfig, 'integrations' | 'adapter'>;
63
70
  /**
64
71
  * Options that are used for the entire lifecycle of the current instance of the container.
@@ -122,6 +129,30 @@ export declare class experimental_AstroContainer {
122
129
  * @param {AstroContainerOptions=} containerOptions
123
130
  */
124
131
  static create(containerOptions?: AstroContainerOptions): Promise<experimental_AstroContainer>;
132
+ /**
133
+ * Use this function to manually add a renderer to the container.
134
+ *
135
+ * This function is preferred when you require to use the container with a renderer in environments such as on-demand pages.
136
+ *
137
+ * ## Example
138
+ *
139
+ * ```js
140
+ * import reactRenderer from "@astrojs/react/server.js";
141
+ * import vueRenderer from "@astrojs/vue/server.js";
142
+ * import customRenderer from "../renderer/customRenderer.js";
143
+ * import { experimental_AstroContainer as AstroContainer } from "astro/container"
144
+ *
145
+ * const container = await AstroContainer.create();
146
+ * container.addServerRenderer(reactRenderer);
147
+ * container.addServerRenderer(vueRenderer);
148
+ * container.addServerRenderer("customRenderer", customRenderer);
149
+ * ```
150
+ *
151
+ * @param options {object}
152
+ * @param options.name The name of the renderer. The name **isn't** arbitrary, and it should match the name of the package.
153
+ * @param options.renderer The server renderer exported by integration.
154
+ */
155
+ addServerRenderer(options: AddServerRenderer): void;
125
156
  private static createFromManifest;
126
157
  /**
127
158
  * @description
@@ -93,6 +93,48 @@ class experimental_AstroContainer {
93
93
  resolve
94
94
  });
95
95
  }
96
+ /**
97
+ * Use this function to manually add a renderer to the container.
98
+ *
99
+ * This function is preferred when you require to use the container with a renderer in environments such as on-demand pages.
100
+ *
101
+ * ## Example
102
+ *
103
+ * ```js
104
+ * import reactRenderer from "@astrojs/react/server.js";
105
+ * import vueRenderer from "@astrojs/vue/server.js";
106
+ * import customRenderer from "../renderer/customRenderer.js";
107
+ * import { experimental_AstroContainer as AstroContainer } from "astro/container"
108
+ *
109
+ * const container = await AstroContainer.create();
110
+ * container.addServerRenderer(reactRenderer);
111
+ * container.addServerRenderer(vueRenderer);
112
+ * container.addServerRenderer("customRenderer", customRenderer);
113
+ * ```
114
+ *
115
+ * @param options {object}
116
+ * @param options.name The name of the renderer. The name **isn't** arbitrary, and it should match the name of the package.
117
+ * @param options.renderer The server renderer exported by integration.
118
+ */
119
+ addServerRenderer(options) {
120
+ const { renderer, name } = options;
121
+ if (!renderer.check || !renderer.renderToStaticMarkup) {
122
+ throw new Error(
123
+ "The renderer you passed isn't valid. A renderer is usually an object that exposes the `check` and `renderToStaticMarkup` functions.\nUsually, the renderer is exported by a /server.js entrypoint e.g. `import renderer from '@astrojs/react/server.js'`"
124
+ );
125
+ }
126
+ if (isNamedRenderer(renderer)) {
127
+ this.#pipeline.manifest.renderers.push({
128
+ name: renderer.name,
129
+ ssr: renderer
130
+ });
131
+ } else {
132
+ this.#pipeline.manifest.renderers.push({
133
+ name,
134
+ ssr: renderer
135
+ });
136
+ }
137
+ }
96
138
  // NOTE: we keep this private via TS instead via `#` so it's still available on the surface, so we can play with it.
97
139
  // @ematipico: I plan to use it for a possible integration that could help people
98
140
  static async createFromManifest(manifest) {
@@ -234,6 +276,9 @@ class experimental_AstroContainer {
234
276
  return { default: componentFactory };
235
277
  }
236
278
  }
279
+ function isNamedRenderer(renderer) {
280
+ return !!renderer?.name;
281
+ }
237
282
  export {
238
283
  experimental_AstroContainer
239
284
  };
@@ -8,5 +8,4 @@ export declare class ContainerPipeline extends Pipeline {
8
8
  tryRewrite(payload: RewritePayload, request: Request): Promise<[RouteData, ComponentInstance, URL]>;
9
9
  insertRoute(route: RouteData, componentInstance: ComponentInstance): void;
10
10
  getComponentByRoute(_routeData: RouteData): Promise<ComponentInstance>;
11
- rewriteKnownRoute(pathname: string, _sourceRoute: RouteData): ComponentInstance;
12
11
  }
@@ -1,11 +1,12 @@
1
1
  import { Pipeline } from "../core/base-pipeline.js";
2
- import { InvalidRewrite404, RouteNotFound } from "../core/errors/errors-data.js";
2
+ import { RouteNotFound } from "../core/errors/errors-data.js";
3
3
  import { AstroError } from "../core/errors/index.js";
4
4
  import {
5
5
  createModuleScriptElement,
6
6
  createStylesheetElementSet
7
7
  } from "../core/render/ssr-element.js";
8
- import { DEFAULT_404_ROUTE, default404Page } from "../core/routing/astro-designed-error-pages.js";
8
+ import { DEFAULT_404_ROUTE } from "../core/routing/astro-designed-error-pages.js";
9
+ import { findRouteToRewrite } from "../core/routing/rewrite.js";
9
10
  class ContainerPipeline extends Pipeline {
10
11
  /**
11
12
  * Internal cache to store components instances by `RouteData`.
@@ -52,30 +53,16 @@ class ContainerPipeline extends Pipeline {
52
53
  return { links, styles, scripts };
53
54
  }
54
55
  async tryRewrite(payload, request) {
55
- let foundRoute;
56
- let finalUrl = void 0;
57
- for (const route of this.manifest.routes) {
58
- if (payload instanceof URL) {
59
- finalUrl = payload;
60
- } else if (payload instanceof Request) {
61
- finalUrl = new URL(payload.url);
62
- } else {
63
- finalUrl = new URL(payload, new URL(request.url).origin);
64
- }
65
- if (route.routeData.pattern.test(decodeURI(finalUrl.pathname))) {
66
- foundRoute = route.routeData;
67
- break;
68
- } else if (finalUrl.pathname === "/404") {
69
- foundRoute = DEFAULT_404_ROUTE;
70
- break;
71
- }
72
- }
73
- if (foundRoute && finalUrl) {
74
- const componentInstance = await this.getComponentByRoute(foundRoute);
75
- return [foundRoute, componentInstance, finalUrl];
76
- } else {
77
- throw new AstroError(RouteNotFound);
78
- }
56
+ const [foundRoute, finalUrl] = findRouteToRewrite({
57
+ payload,
58
+ request,
59
+ routes: this.manifest?.routes.map((r) => r.routeData),
60
+ trailingSlash: this.manifest.trailingSlash,
61
+ buildFormat: this.manifest.buildFormat,
62
+ base: this.manifest.base
63
+ });
64
+ const componentInstance = await this.getComponentByRoute(foundRoute);
65
+ return [foundRoute, componentInstance, finalUrl];
79
66
  }
80
67
  insertRoute(route, componentInstance) {
81
68
  this.#componentsInterner.set(route, {
@@ -90,12 +77,6 @@ class ContainerPipeline extends Pipeline {
90
77
  // @ts-expect-error It needs to be implemented.
91
78
  async getComponentByRoute(_routeData) {
92
79
  }
93
- rewriteKnownRoute(pathname, _sourceRoute) {
94
- if (pathname === "/404") {
95
- return { default: default404Page };
96
- }
97
- throw new AstroError(InvalidRewrite404);
98
- }
99
80
  }
100
81
  export {
101
82
  ContainerPipeline
@@ -0,0 +1,2 @@
1
+ import type * as vite from 'vite';
2
+ export default function astroContainer(): vite.Plugin;
@@ -0,0 +1,15 @@
1
+ const virtualModuleId = "astro:container";
2
+ function astroContainer() {
3
+ return {
4
+ name: "astro:container",
5
+ enforce: "pre",
6
+ resolveId(id) {
7
+ if (id === virtualModuleId) {
8
+ return this.resolve("astro/virtual-modules/container.js");
9
+ }
10
+ }
11
+ };
12
+ }
13
+ export {
14
+ astroContainer as default
15
+ };
@@ -2,10 +2,10 @@ import type { PluginContext } from 'rollup';
2
2
  import { z } from 'zod';
3
3
  export declare function createImage(pluginContext: PluginContext, shouldEmitFile: boolean, entryFilePath: string): () => z.ZodEffects<z.ZodString, z.ZodNever | {
4
4
  ASTRO_ASSET: string;
5
- src: string;
5
+ format: "jpeg" | "jpg" | "png" | "tiff" | "webp" | "gif" | "svg" | "avif";
6
6
  width: number;
7
7
  height: number;
8
- format: "jpeg" | "jpg" | "png" | "tiff" | "webp" | "gif" | "svg" | "avif";
9
- orientation?: number | undefined;
8
+ src: string;
10
9
  fsPath: string;
10
+ orientation?: number | undefined;
11
11
  }, string>;
@@ -318,13 +318,26 @@ async function writeContentFiles({
318
318
  // This ensures `getCollection('empty-collection')` doesn't raise a type error
319
319
  collectionConfig?.type ?? "data"
320
320
  ) : collection.type;
321
+ const collectionEntryKeys = Object.keys(collection.entries).sort();
322
+ const dataType = collectionConfig?.schema ? `InferEntrySchema<${collectionKey}>` : "any";
321
323
  switch (resolvedType) {
322
324
  case "content":
325
+ if (collectionEntryKeys.length === 0) {
326
+ contentTypesStr += `${collectionKey}: Record<string, {
327
+ id: string;
328
+ slug: string;
329
+ body: string;
330
+ collection: ${collectionKey};
331
+ data: ${dataType};
332
+ render(): Render[".md"];
333
+ }>;
334
+ `;
335
+ break;
336
+ }
323
337
  contentTypesStr += `${collectionKey}: {
324
338
  `;
325
- for (const entryKey of Object.keys(collection.entries).sort()) {
339
+ for (const entryKey of collectionEntryKeys) {
326
340
  const entryMetadata = collection.entries[entryKey];
327
- const dataType = collectionConfig?.schema ? `InferEntrySchema<${collectionKey}>` : "any";
328
341
  const renderType = `{ render(): Render[${JSON.stringify(
329
342
  path.extname(JSON.parse(entryKey))
330
343
  )}] }`;
@@ -342,46 +355,54 @@ async function writeContentFiles({
342
355
  `;
343
356
  break;
344
357
  case "data":
345
- dataTypesStr += `${collectionKey}: {
358
+ if (collectionEntryKeys.length === 0) {
359
+ dataTypesStr += `${collectionKey}: Record<string, {
360
+ id: string;
361
+ collection: ${collectionKey};
362
+ data: ${dataType};
363
+ }>;
346
364
  `;
347
- for (const entryKey of Object.keys(collection.entries).sort()) {
348
- const dataType = collectionConfig?.schema ? `InferEntrySchema<${collectionKey}>` : "any";
349
- dataTypesStr += `${entryKey}: {
365
+ } else {
366
+ dataTypesStr += `${collectionKey}: {
367
+ `;
368
+ for (const entryKey of collectionEntryKeys) {
369
+ dataTypesStr += `${entryKey}: {
350
370
  id: ${entryKey};
351
371
  collection: ${collectionKey};
352
372
  data: ${dataType}
353
373
  };
354
374
  `;
355
- if (settings.config.experimental.contentCollectionJsonSchema && collectionConfig?.schema) {
356
- let zodSchemaForJson = typeof collectionConfig.schema === "function" ? collectionConfig.schema({ image: () => z.string() }) : collectionConfig.schema;
357
- if (zodSchemaForJson instanceof z.ZodObject) {
358
- zodSchemaForJson = zodSchemaForJson.extend({
359
- $schema: z.string().optional()
360
- });
361
- }
362
- try {
363
- await fs.promises.writeFile(
364
- new URL(`./${collectionKey.replace(/"/g, "")}.schema.json`, collectionSchemasDir),
365
- JSON.stringify(
366
- zodToJsonSchema(zodSchemaForJson, {
367
- name: collectionKey.replace(/"/g, ""),
368
- markdownDescription: true,
369
- errorMessages: true
370
- }),
371
- null,
372
- 2
373
- )
374
- );
375
- } catch (err) {
376
- logger.warn(
377
- "content",
378
- `An error was encountered while creating the JSON schema for the ${entryKey} entry in ${collectionKey} collection. Proceeding without it. Error: ${err}`
379
- );
380
- }
381
375
  }
382
- }
383
- dataTypesStr += `};
376
+ dataTypesStr += `};
384
377
  `;
378
+ }
379
+ if (settings.config.experimental.contentCollectionJsonSchema && collectionConfig?.schema) {
380
+ let zodSchemaForJson = typeof collectionConfig.schema === "function" ? collectionConfig.schema({ image: () => z.string() }) : collectionConfig.schema;
381
+ if (zodSchemaForJson instanceof z.ZodObject) {
382
+ zodSchemaForJson = zodSchemaForJson.extend({
383
+ $schema: z.string().optional()
384
+ });
385
+ }
386
+ try {
387
+ await fs.promises.writeFile(
388
+ new URL(`./${collectionKey.replace(/"/g, "")}.schema.json`, collectionSchemasDir),
389
+ JSON.stringify(
390
+ zodToJsonSchema(zodSchemaForJson, {
391
+ name: collectionKey.replace(/"/g, ""),
392
+ markdownDescription: true,
393
+ errorMessages: true
394
+ }),
395
+ null,
396
+ 2
397
+ )
398
+ );
399
+ } catch (err) {
400
+ logger.warn(
401
+ "content",
402
+ `An error was encountered while creating the JSON schema for the ${collectionKey} collection. Proceeding without it. Error: ${err}`
403
+ );
404
+ }
405
+ }
385
406
  break;
386
407
  }
387
408
  }
@@ -5,6 +5,7 @@ import type { PluginContext } from 'rollup';
5
5
  import { type ViteDevServer } from 'vite';
6
6
  import { z } from 'zod';
7
7
  import type { AstroConfig, AstroSettings, ContentEntryType, DataEntryType } from '../@types/astro.js';
8
+ import type { Logger } from '../core/logger/core.js';
8
9
  import { CONTENT_FLAGS } from './consts.js';
9
10
  /**
10
11
  * Amap from a collection + slug to the local file path.
@@ -99,6 +100,16 @@ export declare function getEntryData(entry: {
99
100
  export declare function getContentEntryExts(settings: Pick<AstroSettings, 'contentEntryTypes'>): string[];
100
101
  export declare function getDataEntryExts(settings: Pick<AstroSettings, 'dataEntryTypes'>): string[];
101
102
  export declare function getEntryConfigByExtMap<TEntryType extends ContentEntryType | DataEntryType>(entryTypes: TEntryType[]): Map<string, TEntryType>;
103
+ export declare function getSymlinkedContentCollections({ contentDir, logger, fs, }: {
104
+ contentDir: URL;
105
+ logger: Logger;
106
+ fs: typeof fsMod;
107
+ }): Promise<Map<string, string>>;
108
+ export declare function reverseSymlink({ entry, symlinks, contentDir, }: {
109
+ entry: string | URL;
110
+ contentDir: string | URL;
111
+ symlinks?: Map<string, string>;
112
+ }): string;
102
113
  export declare function getEntryCollectionName({ contentDir, entry, }: Pick<ContentPaths, 'contentDir'> & {
103
114
  entry: string | URL;
104
115
  }): string | undefined;