astro 7.2.1 → 7.2.3

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 (166) hide show
  1. package/dist/actions/handler.d.ts +6 -12
  2. package/dist/actions/handler.js +30 -40
  3. package/dist/actions/load.d.ts +12 -0
  4. package/dist/actions/load.js +55 -0
  5. package/dist/actions/runtime/entrypoints/server.js +5 -4
  6. package/dist/actions/runtime/server.js +8 -6
  7. package/dist/assets/fonts/constants.d.ts +8 -0
  8. package/dist/assets/fonts/constants.js +2 -0
  9. package/dist/assets/fonts/providers/index.d.ts +1 -1
  10. package/dist/assets/fonts/providers/index.js +2 -12
  11. package/dist/assets/fonts/vite-plugin-fonts.js +3 -1
  12. package/dist/assets/utils/node.js +35 -3
  13. package/dist/cli/dev/index.js +2 -2
  14. package/dist/cli/infra/build-time-astro-version-provider.js +1 -1
  15. package/dist/cli/preview/index.js +1 -1
  16. package/dist/cli/server.js +4 -4
  17. package/dist/container/environment.d.ts +20 -0
  18. package/dist/container/environment.js +106 -0
  19. package/dist/container/index.js +65 -32
  20. package/dist/content/content-layer.js +3 -3
  21. package/dist/content/data-store-writer.d.ts +7 -10
  22. package/dist/content/data-store-writer.js +62 -27
  23. package/dist/content/data-store.d.ts +20 -3
  24. package/dist/content/data-store.js +28 -7
  25. package/dist/content/loaders/file.js +19 -4
  26. package/dist/content/loaders/glob.js +15 -2
  27. package/dist/content/mutable-data-store.js +15 -10
  28. package/dist/content/runtime.d.ts +3 -2
  29. package/dist/content/runtime.js +43 -26
  30. package/dist/core/app/app.d.ts +0 -2
  31. package/dist/core/app/app.js +0 -7
  32. package/dist/core/app/base.d.ts +32 -20
  33. package/dist/core/app/base.js +76 -66
  34. package/dist/core/app/dev-facade.d.ts +27 -0
  35. package/dist/core/app/dev-facade.js +51 -0
  36. package/dist/core/app/entrypoints/index.d.ts +0 -1
  37. package/dist/core/app/entrypoints/index.js +0 -2
  38. package/dist/core/app/entrypoints/virtual/dev.js +24 -19
  39. package/dist/core/app/node.js +13 -14
  40. package/dist/core/app/prepare-response.d.ts +1 -1
  41. package/dist/core/app/validate-headers.js +7 -3
  42. package/dist/core/build/app.d.ts +31 -6
  43. package/dist/core/build/app.js +31 -13
  44. package/dist/core/build/environment.d.ts +25 -0
  45. package/dist/core/build/environment.js +157 -0
  46. package/dist/core/build/generate.js +10 -1
  47. package/dist/core/build/plugins/plugin-incremental.js +145 -37
  48. package/dist/core/cache/handler.d.ts +13 -7
  49. package/dist/core/cache/handler.js +55 -51
  50. package/dist/core/cache/provider.d.ts +4 -0
  51. package/dist/core/cache/provider.js +15 -0
  52. package/dist/core/constants.d.ts +0 -11
  53. package/dist/core/constants.js +1 -5
  54. package/dist/core/dev/dev.js +1 -1
  55. package/dist/core/dev/lockfile.d.ts +19 -2
  56. package/dist/core/dev/lockfile.js +25 -2
  57. package/dist/core/environment/dev-nonrunnable.d.ts +6 -0
  58. package/dist/core/environment/dev-nonrunnable.js +170 -0
  59. package/dist/core/environment/index.d.ts +90 -0
  60. package/dist/core/environment/index.js +12 -0
  61. package/dist/core/environment/production.d.ts +6 -0
  62. package/dist/core/environment/production.js +117 -0
  63. package/dist/core/errors/build-handler.d.ts +5 -10
  64. package/dist/core/errors/build-handler.js +11 -17
  65. package/dist/core/errors/default-handler.d.ts +4 -9
  66. package/dist/core/errors/default-handler.js +92 -107
  67. package/dist/core/errors/dev-handler.d.ts +7 -11
  68. package/dist/core/errors/dev-handler.js +71 -69
  69. package/dist/core/errors/errors-data.d.ts +18 -0
  70. package/dist/core/errors/errors-data.js +7 -0
  71. package/dist/core/errors/handler.d.ts +22 -3
  72. package/dist/core/errors/handler.js +25 -0
  73. package/dist/core/fetch/default-handler.d.ts +15 -8
  74. package/dist/core/fetch/default-handler.js +12 -34
  75. package/dist/core/fetch/features.d.ts +23 -0
  76. package/dist/core/fetch/features.js +27 -0
  77. package/dist/core/fetch/fetch-state.d.ts +52 -7
  78. package/dist/core/fetch/fetch-state.js +92 -81
  79. package/dist/core/fetch/index.d.ts +9 -2
  80. package/dist/core/fetch/index.js +18 -79
  81. package/dist/core/fetch/vite-plugin.js +2 -1
  82. package/dist/core/i18n/handler.d.ts +28 -13
  83. package/dist/core/i18n/handler.js +100 -100
  84. package/dist/core/logger/manifest-logger.d.ts +31 -0
  85. package/dist/core/logger/manifest-logger.js +37 -0
  86. package/dist/core/manifest/ambient-source.d.ts +2 -0
  87. package/dist/core/manifest/ambient-source.js +4 -0
  88. package/dist/core/manifest/ambient.d.ts +16 -0
  89. package/dist/core/manifest/ambient.js +22 -0
  90. package/dist/core/manifest/derived.d.ts +3 -0
  91. package/dist/core/manifest/derived.js +10 -0
  92. package/dist/core/manifest/memo.d.ts +31 -0
  93. package/dist/core/manifest/memo.js +47 -0
  94. package/dist/core/messages/runtime.js +1 -1
  95. package/dist/core/middleware/astro-middleware.d.ts +25 -35
  96. package/dist/core/middleware/astro-middleware.js +61 -81
  97. package/dist/core/middleware/load.d.ts +19 -0
  98. package/dist/core/middleware/load.js +36 -0
  99. package/dist/core/middleware/sequence.js +15 -7
  100. package/dist/core/pages/handler.d.ts +18 -25
  101. package/dist/core/pages/handler.js +68 -84
  102. package/dist/core/redirects/render.js +3 -8
  103. package/dist/core/render/index.d.ts +0 -1
  104. package/dist/core/render/index.js +0 -2
  105. package/dist/core/render/route-cache.d.ts +6 -1
  106. package/dist/core/render/route-cache.js +11 -1
  107. package/dist/core/rewrites/handler.d.ts +4 -6
  108. package/dist/core/rewrites/handler.js +19 -20
  109. package/dist/core/routing/default.d.ts +2 -0
  110. package/dist/core/routing/default.js +7 -1
  111. package/dist/core/routing/dev.d.ts +1 -3
  112. package/dist/core/routing/dev.js +12 -5
  113. package/dist/core/routing/handler.d.ts +6 -16
  114. package/dist/core/routing/handler.js +126 -164
  115. package/dist/core/routing/helpers.d.ts +7 -1
  116. package/dist/core/routing/helpers.js +21 -0
  117. package/dist/core/routing/match-request.d.ts +10 -0
  118. package/dist/core/routing/match-request.js +57 -0
  119. package/dist/core/routing/route-table.d.ts +34 -0
  120. package/dist/core/routing/route-table.js +41 -0
  121. package/dist/core/routing/trailing-slash-handler.d.ts +4 -14
  122. package/dist/core/routing/trailing-slash-handler.js +39 -50
  123. package/dist/core/server-islands/mappings.d.ts +6 -0
  124. package/dist/core/server-islands/mappings.js +12 -0
  125. package/dist/core/session/driver.d.ts +4 -0
  126. package/dist/core/session/driver.js +14 -0
  127. package/dist/core/session/handler.d.ts +1 -1
  128. package/dist/core/session/handler.js +8 -8
  129. package/dist/core/session/provider-disabled.js +2 -2
  130. package/dist/core/util.js +2 -2
  131. package/dist/entrypoints/prerender.js +5 -1
  132. package/dist/i18n/middleware.d.ts +4 -4
  133. package/dist/i18n/middleware.js +3 -3
  134. package/dist/manifest/serialized.d.ts +1 -0
  135. package/dist/manifest/serialized.js +9 -2
  136. package/dist/runtime/prerender/static-paths.d.ts +14 -2
  137. package/dist/runtime/prerender/static-paths.js +4 -3
  138. package/dist/types/public/config.d.ts +433 -241
  139. package/dist/vite-plugin-app/createAstroServerApp.js +22 -18
  140. package/dist/vite-plugin-app/environment.d.ts +18 -0
  141. package/dist/vite-plugin-app/environment.js +210 -0
  142. package/dist/vite-plugin-app/handle-request.d.ts +30 -0
  143. package/dist/vite-plugin-app/handle-request.js +129 -0
  144. package/dist/vite-plugin-app/index.d.ts +1 -1
  145. package/dist/vite-plugin-app/index.js +1 -1
  146. package/dist/vite-plugin-css/index.js +2 -2
  147. package/package.json +14 -6
  148. package/src/core/README.md +37 -0
  149. package/src/core/manifest/ambient-source.ts +9 -0
  150. package/src/types/README.md +5 -0
  151. package/dist/container/pipeline.d.ts +0 -14
  152. package/dist/container/pipeline.js +0 -78
  153. package/dist/core/app/dev/app.d.ts +0 -31
  154. package/dist/core/app/dev/app.js +0 -80
  155. package/dist/core/app/dev/pipeline.d.ts +0 -17
  156. package/dist/core/app/dev/pipeline.js +0 -133
  157. package/dist/core/app/pipeline.d.ts +0 -14
  158. package/dist/core/app/pipeline.js +0 -123
  159. package/dist/core/base-pipeline.d.ts +0 -183
  160. package/dist/core/base-pipeline.js +0 -293
  161. package/dist/core/build/pipeline.d.ts +0 -38
  162. package/dist/core/build/pipeline.js +0 -202
  163. package/dist/vite-plugin-app/app.d.ts +0 -62
  164. package/dist/vite-plugin-app/app.js +0 -237
  165. package/dist/vite-plugin-app/pipeline.d.ts +0 -25
  166. package/dist/vite-plugin-app/pipeline.js +0 -189
@@ -3,7 +3,7 @@
3
3
  * and marks the response as sent.
4
4
  *
5
5
  * This is a pure function with no dependencies on the app; it is shared by
6
- * `AstroHandler` and the various error handlers.
6
+ * `handleRequest` and the various error handlers.
7
7
  */
8
8
  export declare function prepareResponse(response: Response, { addCookieHeader }: {
9
9
  addCookieHeader: boolean;
@@ -9,6 +9,7 @@ function sanitizeHost(hostname) {
9
9
  }
10
10
  function parseHost(host) {
11
11
  const parts = host.split(":");
12
+ if (parts.length > 2) return void 0;
12
13
  return {
13
14
  hostname: parts[0],
14
15
  port: parts[1]
@@ -28,7 +29,9 @@ function validateHost(host, protocol, allowedDomains) {
28
29
  if (!allowedDomains || allowedDomains.length === 0) return void 0;
29
30
  const sanitized = sanitizeHost(host);
30
31
  if (!sanitized) return void 0;
31
- const { hostname, port } = parseHost(sanitized);
32
+ const parsed = parseHost(sanitized);
33
+ if (!parsed) return void 0;
34
+ const { hostname, port } = parsed;
32
35
  if (matchesAllowedDomains(hostname, protocol, port, allowedDomains)) {
33
36
  return sanitized;
34
37
  }
@@ -67,8 +70,9 @@ function validateForwardedHeaders(forwardedProtocol, forwardedHost, forwardedPor
67
70
  if (forwardedHost && forwardedHost.length > 0 && allowedDomains && allowedDomains.length > 0) {
68
71
  const protoForValidation = result.protocol || "https";
69
72
  const sanitized = sanitizeHost(forwardedHost);
70
- if (sanitized) {
71
- const { hostname, port: portFromHost } = parseHost(sanitized);
73
+ const parsed = sanitized ? parseHost(sanitized) : void 0;
74
+ if (sanitized && parsed) {
75
+ const { hostname, port: portFromHost } = parsed;
72
76
  const portForValidation = result.port || portFromHost;
73
77
  if (matchesAllowedDomains(hostname, protoForValidation, portForValidation, allowedDomains)) {
74
78
  result.host = sanitized;
@@ -1,17 +1,42 @@
1
1
  import { BaseApp } from '../app/entrypoints/index.js';
2
+ import type { LogRequestPayload } from '../app/base.js';
2
3
  import type { SSRManifest } from '../app/types.js';
4
+ import type { ComponentInstance } from '../../types/astro.js';
5
+ import type { RouteData } from '../../types/public/internal.js';
6
+ import { type RouteCache } from '../render/route-cache.js';
7
+ import type { BuildEnvironmentSlots } from './environment.js';
3
8
  import type { BuildInternals } from './internal.js';
4
- import { BuildPipeline } from './pipeline.js';
5
9
  import type { StaticBuildOptions } from './types.js';
6
- import type { LogRequestPayload } from '../app/base.js';
7
- import type { ErrorHandler } from '../errors/handler.js';
8
- export declare class BuildApp extends BaseApp<BuildPipeline> {
9
- createPipeline(_streaming: boolean, manifest: SSRManifest, ..._args: any[]): BuildPipeline;
10
+ /**
11
+ * The build / prerender facade: a thin shell over the
12
+ * build environment record. The two-phase init state (`setInternals` /
13
+ * `setOptions`, injected by `createDefaultPrerenderer.setup()` after the
14
+ * prerender bundle import) lives in the `BuildEnvironmentSlots` closure
15
+ * created by the prerender entrypoint; the facade only forwards across the
16
+ * bundle boundary into those slots.
17
+ */
18
+ export declare class BuildApp extends BaseApp {
19
+ #private;
20
+ constructor(manifest: SSRManifest, buildEnv: BuildEnvironmentSlots);
10
21
  isDev(): boolean;
22
+ /**
23
+ * Streaming falls through to the environment default
24
+ * (`manifest.serverLike` for the build environment) — we can skip
25
+ * streaming in SSG for performance, as writing strings is faster.
26
+ */
27
+ protected resolveStreaming(): boolean | undefined;
11
28
  setInternals(internals: BuildInternals): void;
12
29
  setOptions(options: StaticBuildOptions): void;
13
30
  getOptions(): StaticBuildOptions;
14
31
  getSettings(): import("../../types/astro.js").AstroSettings;
15
- protected createErrorHandler(): ErrorHandler;
32
+ /**
33
+ * Route cache and component loader for `StaticPaths`. Defined on the app
34
+ * (rather than reached through the functional core at the call site) so
35
+ * they execute inside the prerender bundle's module graph: the default
36
+ * prerenderer constructs `StaticPaths` from a different bundle, whose
37
+ * copies of the core modules hold separate per-manifest state.
38
+ */
39
+ get routeCache(): RouteCache;
40
+ getComponentByRoute(routeData: RouteData): Promise<ComponentInstance>;
16
41
  logRequest(_options: LogRequestPayload): void;
17
42
  }
@@ -1,31 +1,49 @@
1
1
  import { BaseApp } from "../app/entrypoints/index.js";
2
- import { BuildPipeline } from "./pipeline.js";
3
- import { BuildErrorHandler } from "../errors/build-handler.js";
2
+ import { getEnvironment } from "../environment/index.js";
3
+ import { getRouteCache } from "../render/route-cache.js";
4
4
  class BuildApp extends BaseApp {
5
- createPipeline(_streaming, manifest, ..._args) {
6
- return BuildPipeline.create({
7
- manifest
8
- });
5
+ #buildEnv;
6
+ constructor(manifest, buildEnv) {
7
+ super(manifest);
8
+ this.#buildEnv = buildEnv;
9
9
  }
10
10
  isDev() {
11
11
  return true;
12
12
  }
13
+ /**
14
+ * Streaming falls through to the environment default
15
+ * (`manifest.serverLike` for the build environment) — we can skip
16
+ * streaming in SSG for performance, as writing strings is faster.
17
+ */
18
+ resolveStreaming() {
19
+ return void 0;
20
+ }
13
21
  setInternals(internals) {
14
- this.pipeline.setInternals(internals);
22
+ this.#buildEnv.setInternals(internals);
15
23
  }
16
24
  setOptions(options) {
17
- this.pipeline.setOptions(options);
25
+ this.#buildEnv.setOptions(options);
18
26
  this.logger.setDestination(options.logger.options.destination);
19
27
  this.resetAdapterLogger();
20
28
  }
21
29
  getOptions() {
22
- return this.pipeline.getOptions();
30
+ return this.#buildEnv.getOptions();
23
31
  }
24
32
  getSettings() {
25
- return this.pipeline.getSettings();
26
- }
27
- createErrorHandler() {
28
- return new BuildErrorHandler(this);
33
+ return this.#buildEnv.getSettings();
34
+ }
35
+ /**
36
+ * Route cache and component loader for `StaticPaths`. Defined on the app
37
+ * (rather than reached through the functional core at the call site) so
38
+ * they execute inside the prerender bundle's module graph: the default
39
+ * prerenderer constructs `StaticPaths` from a different bundle, whose
40
+ * copies of the core modules hold separate per-manifest state.
41
+ */
42
+ get routeCache() {
43
+ return getRouteCache(this.manifest);
44
+ }
45
+ getComponentByRoute(routeData) {
46
+ return getEnvironment(this.manifest).getComponentByRoute(this.manifest, routeData);
29
47
  }
30
48
  logRequest(_options) {
31
49
  }
@@ -0,0 +1,25 @@
1
+ import type { AstroSettings } from '../../types/astro.js';
2
+ import type { RenderEnvironment } from '../environment/index.js';
3
+ import type { BuildInternals } from './internal.js';
4
+ import type { StaticBuildOptions } from './types.js';
5
+ /**
6
+ * The build / prerender environment record and its mutable closure slots.
7
+ * The build has a two-phase initialization: the prerender bundle is imported
8
+ * first, and `createDefaultPrerenderer.setup()` injects `BuildInternals` /
9
+ * `StaticBuildOptions` afterwards through the facade. The slots live in this
10
+ * closure; accessors throw before injection, and the environment functions
11
+ * close over the same slots.
12
+ */
13
+ export interface BuildEnvironmentSlots {
14
+ /** The build `RenderEnvironment`; its functions close over the slots below. */
15
+ env: RenderEnvironment;
16
+ setInternals(internals: BuildInternals): void;
17
+ setOptions(options: StaticBuildOptions): void;
18
+ /** Throws `No internals defined` before injection. */
19
+ getInternals(): BuildInternals;
20
+ /** Throws `No options defined` before injection. */
21
+ getOptions(): StaticBuildOptions;
22
+ /** Throws `No options defined` before injection. */
23
+ getSettings(): AstroSettings;
24
+ }
25
+ export declare function createBuildEnvironment(): BuildEnvironmentSlots;
@@ -0,0 +1,157 @@
1
+ import { BEFORE_HYDRATION_SCRIPT_ID, PAGE_SCRIPT_ID } from "../../vite-plugin-scripts/index.js";
2
+ import { RedirectSinglePageBuiltModule } from "../redirects/index.js";
3
+ import { createAssetLink, createStylesheetElementSet } from "../render/ssr-element.js";
4
+ import { getDefaultRoutes } from "../routing/default.js";
5
+ import { getFallbackRoute, routeIsFallback, routeIsRedirect } from "../routing/helpers.js";
6
+ import { findRouteToRewrite } from "../routing/rewrite.js";
7
+ import { cssOrder, getPageData, mergeInlineCss } from "./runtime.js";
8
+ async function getModuleForRoute(manifest, route) {
9
+ for (const defaultRoute of getDefaultRoutes(manifest)) {
10
+ if (route.component === defaultRoute.component) {
11
+ return {
12
+ page: () => Promise.resolve(defaultRoute.instance)
13
+ };
14
+ }
15
+ }
16
+ let routeToProcess = route;
17
+ if (routeIsRedirect(route)) {
18
+ if (route.redirectRoute) {
19
+ routeToProcess = route.redirectRoute;
20
+ } else {
21
+ return RedirectSinglePageBuiltModule;
22
+ }
23
+ } else if (routeIsFallback(route)) {
24
+ routeToProcess = getFallbackRoute(route, manifest.routes);
25
+ }
26
+ if (manifest.pageMap) {
27
+ const importComponentInstance = manifest.pageMap.get(routeToProcess.component);
28
+ if (!importComponentInstance) {
29
+ throw new Error(`Unexpectedly unable to find a component instance for route ${route.route}`);
30
+ }
31
+ return await importComponentInstance();
32
+ } else if (manifest.pageModule) {
33
+ return manifest.pageModule;
34
+ }
35
+ throw new Error(
36
+ "Astro couldn't find the correct page to render, probably because it wasn't correctly mapped for SSR usage. This is an internal error, please file an issue."
37
+ );
38
+ }
39
+ async function getComponentByRoute(manifest, routeData) {
40
+ const module = await getModuleForRoute(manifest, routeData);
41
+ return module.page();
42
+ }
43
+ function createBuildEnvironment() {
44
+ let internals;
45
+ let options;
46
+ function getInternals() {
47
+ if (!internals) {
48
+ throw new Error("No internals defined");
49
+ }
50
+ return internals;
51
+ }
52
+ function getOptions() {
53
+ if (!options) {
54
+ throw new Error("No options defined");
55
+ }
56
+ return options;
57
+ }
58
+ function getSettings() {
59
+ return getOptions().settings;
60
+ }
61
+ const resolveCache = /* @__PURE__ */ new Map();
62
+ const env = {
63
+ name: "build",
64
+ runtimeMode: "production",
65
+ // We can skip streaming in SSG for performance as writing as strings is
66
+ // faster.
67
+ defaultStreaming: (manifest) => manifest.serverLike,
68
+ async resolve(manifest, specifier) {
69
+ if (resolveCache.has(specifier)) {
70
+ return resolveCache.get(specifier);
71
+ }
72
+ const hashedFilePath = manifest.entryModules[specifier];
73
+ if (typeof hashedFilePath !== "string" || hashedFilePath === "") {
74
+ if (specifier === BEFORE_HYDRATION_SCRIPT_ID) {
75
+ resolveCache.set(specifier, "");
76
+ return "";
77
+ }
78
+ throw new Error(`Cannot find the built path for ${specifier}`);
79
+ }
80
+ const assetLink = createAssetLink(hashedFilePath, manifest.base, manifest.assetsPrefix);
81
+ resolveCache.set(specifier, assetLink);
82
+ return assetLink;
83
+ },
84
+ headElements(manifest, routeData) {
85
+ const { assetsPrefix, base } = manifest;
86
+ const settings = getSettings();
87
+ const buildInternals = getInternals();
88
+ const links = /* @__PURE__ */ new Set();
89
+ const pageBuildData = getPageData(buildInternals, routeData.route, routeData.component);
90
+ const scripts = /* @__PURE__ */ new Set();
91
+ const sortedCssAssets = pageBuildData?.styles.sort(cssOrder).map(({ sheet }) => sheet).reduce(mergeInlineCss, []);
92
+ const styles = createStylesheetElementSet(sortedCssAssets ?? [], base, assetsPrefix);
93
+ if (settings.scripts.some((script) => script.stage === "page")) {
94
+ const hashedFilePath = buildInternals.entrySpecifierToBundleMap.get(PAGE_SCRIPT_ID);
95
+ if (typeof hashedFilePath !== "string") {
96
+ throw new Error(`Cannot find the built path for ${PAGE_SCRIPT_ID}`);
97
+ }
98
+ const src = createAssetLink(hashedFilePath, base, assetsPrefix);
99
+ scripts.add({
100
+ props: { type: "module", src },
101
+ children: ""
102
+ });
103
+ }
104
+ for (const script of settings.scripts) {
105
+ if (script.stage === "head-inline") {
106
+ scripts.add({
107
+ props: {},
108
+ children: script.content
109
+ });
110
+ }
111
+ }
112
+ return { scripts, styles, links };
113
+ },
114
+ componentMetadata() {
115
+ },
116
+ getComponentByRoute,
117
+ getModuleForRoute,
118
+ async tryRewrite(manifest, payload, request) {
119
+ const { routeData, pathname, newUrl } = findRouteToRewrite({
120
+ payload,
121
+ request,
122
+ // RAW manifest routes, exactly like `BuildPipeline.tryRewrite` — see
123
+ // the production environment's tryRewrite for why the derived
124
+ // (ensured-404) table is NOT observably identical here.
125
+ routes: manifest.routes.map((r) => r.routeData),
126
+ trailingSlash: manifest.trailingSlash,
127
+ buildFormat: manifest.buildFormat,
128
+ base: manifest.base,
129
+ outDir: manifest.serverLike ? manifest.buildClientDir : manifest.outDir
130
+ });
131
+ const componentInstance = await getComponentByRoute(manifest, routeData);
132
+ return { routeData, componentInstance, newUrl, pathname };
133
+ },
134
+ getRenderers(manifest) {
135
+ return manifest.renderers;
136
+ },
137
+ errorStrategy: "build",
138
+ injectCspMetaTagsOnErrorPages: false,
139
+ logRequest() {
140
+ }
141
+ };
142
+ return {
143
+ env,
144
+ setInternals(value) {
145
+ internals = value;
146
+ },
147
+ setOptions(value) {
148
+ options = value;
149
+ },
150
+ getInternals,
151
+ getOptions,
152
+ getSettings
153
+ };
154
+ }
155
+ export {
156
+ createBuildEnvironment
157
+ };
@@ -222,7 +222,16 @@ ${colors.bgGreen(colors.black(` ${verb} static routes `))}`);
222
222
  if (prerenderer.collectStaticImages) {
223
223
  const adapterImages = await prerenderer.collectStaticImages();
224
224
  for (const [path, entry] of adapterImages) {
225
- staticImageList.set(path, entry);
225
+ const existing = staticImageList.get(path);
226
+ if (existing) {
227
+ for (const [hash, transform] of entry.transforms) {
228
+ if (!existing.transforms.has(hash)) {
229
+ existing.transforms.set(hash, transform);
230
+ }
231
+ }
232
+ } else {
233
+ staticImageList.set(path, entry);
234
+ }
226
235
  }
227
236
  }
228
237
  } finally {
@@ -1,4 +1,5 @@
1
1
  import crypto from "node:crypto";
2
+ import { FONTS_SERVER_ADDRESS_PLACEHOLDER } from "../../../assets/fonts/constants.js";
2
3
  import { PROPAGATED_ASSET_FLAG } from "../../../content/consts.js";
3
4
  import { hasContentFlag } from "../../../content/utils.js";
4
5
  import { ASTRO_VITE_ENVIRONMENT_NAMES } from "../../constants.js";
@@ -7,29 +8,13 @@ import { rootRelativePath } from "../../viteUtils.js";
7
8
  import { moduleIsTopLevelPage } from "../graph.js";
8
9
  import { isContentDataIncrementalModule } from "../incremental-metadata.js";
9
10
  import { getPageDataByViteID } from "../internal.js";
10
- function collectTransitiveDeps(graph, rootId) {
11
- const deps = /* @__PURE__ */ new Set();
12
- const queue = [rootId];
13
- while (queue.length > 0) {
14
- const current = queue.pop();
15
- if (deps.has(current)) continue;
16
- const modInfo = graph.getModuleInfo(current);
17
- if (isContentDataIncrementalModule(modInfo)) continue;
18
- deps.add(current);
19
- if (!modInfo) continue;
20
- for (const dep of modInfo.importedIds) {
21
- if (!deps.has(dep)) queue.push(dep);
22
- }
23
- for (const dep of modInfo.dynamicallyImportedIds) {
24
- if (!deps.has(dep)) queue.push(dep);
25
- }
26
- }
27
- return [...deps].sort();
28
- }
29
11
  const ASSET_PLACEHOLDERS = [
30
12
  { token: "__ASTRO_ASSET_IMAGE__", pattern: /__ASTRO_ASSET_IMAGE__([\w$]+)__(?:_(.*?)__)?/g },
31
13
  { token: "__VITE_ASSET__", pattern: /__VITE_ASSET__([\w$]+)__(?:\$_(.*?)__)?/g }
32
14
  ];
15
+ const FONTS_ADDRESS_DECLARATION = new RegExp(
16
+ `(?:const|let|var)\\s+${FONTS_SERVER_ADDRESS_PLACEHOLDER}\\s*=[^;]+;`
17
+ );
33
18
  function resolveAssetPlaceholders(graph, code) {
34
19
  let resolved = code;
35
20
  for (const { token, pattern } of ASSET_PLACEHOLDERS) {
@@ -42,6 +27,9 @@ function resolveAssetPlaceholders(graph, code) {
42
27
  }
43
28
  });
44
29
  }
30
+ if (resolved.includes(FONTS_SERVER_ADDRESS_PLACEHOLDER)) {
31
+ resolved = resolved.replace(FONTS_ADDRESS_DECLARATION, "");
32
+ }
45
33
  return resolved;
46
34
  }
47
35
  function hashModules(graph, sortedIds) {
@@ -57,11 +45,131 @@ function hashModules(graph, sortedIds) {
57
45
  }
58
46
  return hasher.digest("hex");
59
47
  }
60
- function collectClientEntrypointHashes(graph, entrypointIds, pagesByEntrypoint, hashesByComponent) {
48
+ function createTransitiveGraphCache(graph) {
49
+ const modules = /* @__PURE__ */ new Map();
50
+ const dependencies = /* @__PURE__ */ new Map();
51
+ const excludedModules = /* @__PURE__ */ new Set();
52
+ const pending = [...graph.getModuleIds()];
53
+ for (const id of pending) {
54
+ if (modules.has(id)) continue;
55
+ const info = graph.getModuleInfo(id);
56
+ modules.set(id, info);
57
+ if (isContentDataIncrementalModule(info)) {
58
+ excludedModules.add(id);
59
+ continue;
60
+ }
61
+ const importedIds = [...info?.importedIds ?? [], ...info?.dynamicallyImportedIds ?? []];
62
+ dependencies.set(id, importedIds);
63
+ pending.push(...importedIds);
64
+ }
65
+ for (const id of excludedModules) modules.delete(id);
66
+ for (const [id, importedIds] of dependencies) {
67
+ dependencies.set(
68
+ id,
69
+ importedIds.filter((importedId) => !excludedModules.has(importedId))
70
+ );
71
+ }
72
+ const reverseDependencies = /* @__PURE__ */ new Map();
73
+ for (const id of modules.keys()) reverseDependencies.set(id, []);
74
+ for (const [id, importedIds] of dependencies) {
75
+ for (const importedId of importedIds) reverseDependencies.get(importedId)?.push(id);
76
+ }
77
+ const visited = /* @__PURE__ */ new Set();
78
+ const finishOrder = [];
79
+ for (const rootId of modules.keys()) {
80
+ if (visited.has(rootId)) continue;
81
+ visited.add(rootId);
82
+ const stack = [[rootId, 0]];
83
+ while (stack.length > 0) {
84
+ const frame = stack[stack.length - 1];
85
+ const importedIds = dependencies.get(frame[0]) ?? [];
86
+ if (frame[1] < importedIds.length) {
87
+ const importedId = importedIds[frame[1]++];
88
+ if (!visited.has(importedId)) {
89
+ visited.add(importedId);
90
+ stack.push([importedId, 0]);
91
+ }
92
+ } else {
93
+ finishOrder.push(frame[0]);
94
+ stack.pop();
95
+ }
96
+ }
97
+ }
98
+ const componentByModule = /* @__PURE__ */ new Map();
99
+ const components = [];
100
+ for (const rootId of finishOrder.toReversed()) {
101
+ if (componentByModule.has(rootId)) continue;
102
+ const componentIndex = components.length;
103
+ const component = [];
104
+ const stack = [rootId];
105
+ componentByModule.set(rootId, componentIndex);
106
+ while (stack.length > 0) {
107
+ const id = stack.pop();
108
+ component.push(id);
109
+ for (const importerId of reverseDependencies.get(id) ?? []) {
110
+ if (!componentByModule.has(importerId)) {
111
+ componentByModule.set(importerId, componentIndex);
112
+ stack.push(importerId);
113
+ }
114
+ }
115
+ }
116
+ components.push(component.sort());
117
+ }
118
+ const componentDependencies = components.map(() => /* @__PURE__ */ new Set());
119
+ const componentImporters = components.map(() => /* @__PURE__ */ new Set());
120
+ for (const [id, importedIds] of dependencies) {
121
+ const componentIndex = componentByModule.get(id);
122
+ for (const importedId of importedIds) {
123
+ const dependencyIndex = componentByModule.get(importedId);
124
+ if (dependencyIndex === componentIndex) continue;
125
+ componentDependencies[componentIndex].add(dependencyIndex);
126
+ componentImporters[dependencyIndex].add(componentIndex);
127
+ }
128
+ }
129
+ const componentHashes = /* @__PURE__ */ new Map();
130
+ const componentHasServerIsland = /* @__PURE__ */ new Map();
131
+ const unresolvedDependencies = componentDependencies.map((items) => items.size);
132
+ const ready = unresolvedDependencies.flatMap((count, index) => count === 0 ? [index] : []);
133
+ for (const componentIndex of ready) {
134
+ const hasher = crypto.createHash("sha256");
135
+ hasher.update(hashModules(graph, components[componentIndex]));
136
+ const dependencyHashes = [...componentDependencies[componentIndex]].map((dependencyIndex) => componentHashes.get(dependencyIndex)).sort();
137
+ for (const dependencyHash of dependencyHashes) {
138
+ hasher.update("\n");
139
+ hasher.update(dependencyHash);
140
+ }
141
+ componentHashes.set(componentIndex, hasher.digest("hex"));
142
+ componentHasServerIsland.set(
143
+ componentIndex,
144
+ components[componentIndex].some(
145
+ (id) => (modules.get(id)?.meta?.astro?.serverComponents?.length ?? 0) > 0
146
+ ) || [...componentDependencies[componentIndex]].some(
147
+ (dependencyIndex) => componentHasServerIsland.get(dependencyIndex)
148
+ )
149
+ );
150
+ for (const importerIndex of componentImporters[componentIndex]) {
151
+ unresolvedDependencies[importerIndex]--;
152
+ if (unresolvedDependencies[importerIndex] === 0) ready.push(importerIndex);
153
+ }
154
+ }
155
+ return {
156
+ hashes: new Map(
157
+ [...componentByModule].map(([id, componentIndex]) => [
158
+ id,
159
+ componentHashes.get(componentIndex)
160
+ ])
161
+ ),
162
+ serverIslandModules: new Set(
163
+ [...componentByModule].filter(([, componentIndex]) => componentHasServerIsland.get(componentIndex)).map(([id]) => id)
164
+ )
165
+ };
166
+ }
167
+ function collectClientEntrypointHashes(transitiveHashes, entrypointIds, pagesByEntrypoint, hashesByComponent) {
61
168
  for (const entrypointId of entrypointIds) {
62
169
  const pages = pagesByEntrypoint.get(entrypointId);
63
170
  if (!pages?.size) continue;
64
- const hash = hashModules(graph, collectTransitiveDeps(graph, entrypointId));
171
+ const hash = transitiveHashes.get(entrypointId);
172
+ if (!hash) continue;
65
173
  for (const pageData of pages) {
66
174
  let list = hashesByComponent.get(pageData.component);
67
175
  if (!list) {
@@ -75,15 +183,16 @@ function collectClientEntrypointHashes(graph, entrypointIds, pagesByEntrypoint,
75
183
  function foldClientDependencies(graph, internals) {
76
184
  const baseHashes = internals.pageDependencyHashes;
77
185
  if (!baseHashes) return;
186
+ const { hashes: transitiveHashes } = createTransitiveGraphCache(graph);
78
187
  const hashesByComponent = /* @__PURE__ */ new Map();
79
188
  collectClientEntrypointHashes(
80
- graph,
189
+ transitiveHashes,
81
190
  internals.discoveredClientOnlyComponents.keys(),
82
191
  internals.pagesByClientOnly,
83
192
  hashesByComponent
84
193
  );
85
194
  collectClientEntrypointHashes(
86
- graph,
195
+ transitiveHashes,
87
196
  internals.discoveredScripts,
88
197
  internals.pagesByScriptId,
89
198
  hashesByComponent
@@ -98,24 +207,17 @@ function foldClientDependencies(graph, internals) {
98
207
  baseHashes.set(component, hasher.digest("hex"));
99
208
  }
100
209
  }
101
- function collectContentEntryHashes(graph, root) {
210
+ function collectContentEntryHashes(graph, root, transitiveHashes) {
102
211
  const entryHashes = /* @__PURE__ */ new Map();
103
212
  for (const id of graph.getModuleIds()) {
104
213
  if (!hasContentFlag(id, PROPAGATED_ASSET_FLAG)) continue;
105
214
  const renderModuleId = removeQueryString(id);
106
215
  const key = rootRelativePath(root, renderModuleId, false);
107
- const deps = collectTransitiveDeps(graph, renderModuleId);
108
- entryHashes.set(key, hashModules(graph, deps));
216
+ const hash = transitiveHashes.get(renderModuleId);
217
+ if (hash) entryHashes.set(key, hash);
109
218
  }
110
219
  return entryHashes;
111
220
  }
112
- function pageContainsServerIsland(graph, ids) {
113
- for (const id of ids) {
114
- const serverComponents = graph.getModuleInfo(id)?.meta?.astro?.serverComponents;
115
- if (serverComponents?.length) return true;
116
- }
117
- return false;
118
- }
119
221
  function pluginIncremental(internals, root) {
120
222
  return {
121
223
  name: "@astro/plugin-incremental",
@@ -127,6 +229,7 @@ function pluginIncremental(internals, root) {
127
229
  foldClientDependencies(this, internals);
128
230
  return;
129
231
  }
232
+ const transitiveGraph = createTransitiveGraphCache(this);
130
233
  const hashes = /* @__PURE__ */ new Map();
131
234
  const serverIslandComponents = /* @__PURE__ */ new Set();
132
235
  for (const id of this.getModuleIds()) {
@@ -135,14 +238,19 @@ function pluginIncremental(internals, root) {
135
238
  if (!moduleIsTopLevelPage(info)) continue;
136
239
  const pageData = getPageDataByViteID(internals, info.id);
137
240
  if (!pageData) continue;
138
- const deps = collectTransitiveDeps(this, info.id);
139
- hashes.set(pageData.component, hashModules(this, deps));
140
- if (pageContainsServerIsland(this, deps)) {
241
+ const hash = transitiveGraph.hashes.get(info.id);
242
+ if (!hash) continue;
243
+ hashes.set(pageData.component, hash);
244
+ if (transitiveGraph.serverIslandModules.has(info.id)) {
141
245
  serverIslandComponents.add(pageData.component);
142
246
  }
143
247
  }
144
248
  internals.pageDependencyHashes = hashes;
145
- internals.contentEntryRenderHashes = collectContentEntryHashes(this, root);
249
+ internals.contentEntryRenderHashes = collectContentEntryHashes(
250
+ this,
251
+ root,
252
+ transitiveGraph.hashes
253
+ );
146
254
  internals.serverIslandPageComponents = serverIslandComponents;
147
255
  }
148
256
  };
@@ -1,6 +1,6 @@
1
- import type { BaseApp } from '../app/base.js';
2
1
  import type { FetchState } from '../fetch/fetch-state.js';
3
- import type { Pipeline } from '../base-pipeline.js';
2
+ import type { SSRManifest } from '../app/types.js';
3
+ import { type CompiledCacheRoute } from './runtime/route-matching.js';
4
4
  /**
5
5
  * Registers a cache provider on the given `FetchState`. When
6
6
  * `state.resolve('cache')` is first called, the appropriate cache
@@ -22,8 +22,14 @@ export declare function provideCache(state: FetchState): Promise<void> | void;
22
22
  * Cache headers (`CDN-Cache-Control`, `Cache-Tag`) are stripped from
23
23
  * the final response after the runtime provider has read them.
24
24
  */
25
- export declare class CacheHandler {
26
- #private;
27
- constructor(app: BaseApp<Pipeline>);
28
- handle(state: FetchState, next: () => Promise<Response>): Promise<Response>;
29
- }
25
+ export declare function handleCache(state: FetchState, next: () => Promise<Response>): Promise<Response>;
26
+ /**
27
+ * Config-level cache routes compiled from `manifest.cacheConfig`, derived
28
+ * lazily on the first cache-seeded request.
29
+ */
30
+ export declare function getCompiledCacheRoutes(manifest: SSRManifest): CompiledCacheRoute[];
31
+ /**
32
+ * Internal raw setter — exists only so the transitional `Pipeline` bridge can
33
+ * expose `compiledCacheRoutes` as a get/set pair.
34
+ */
35
+ export declare function setCompiledCacheRoutes(manifest: SSRManifest, routes: CompiledCacheRoute[]): void;