astro 7.2.2 → 7.2.4

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 (158) 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/providers/index.d.ts +1 -1
  8. package/dist/assets/fonts/providers/index.js +2 -12
  9. package/dist/assets/utils/vendor/image-size/types/heif.js +8 -3
  10. package/dist/assets/utils/vendor/image-size/types/icns.js +10 -2
  11. package/dist/assets/utils/vendor/image-size/types/jp2.js +2 -2
  12. package/dist/assets/utils/vendor/image-size/types/jxl.js +5 -2
  13. package/dist/assets/utils/vendor/image-size/types/utils.d.ts +1 -1
  14. package/dist/assets/utils/vendor/image-size/types/utils.js +20 -6
  15. package/dist/cli/infra/build-time-astro-version-provider.js +1 -1
  16. package/dist/container/environment.d.ts +20 -0
  17. package/dist/container/environment.js +106 -0
  18. package/dist/container/index.js +73 -37
  19. package/dist/content/content-layer.js +3 -3
  20. package/dist/content/data-store-writer.d.ts +7 -10
  21. package/dist/content/data-store-writer.js +62 -27
  22. package/dist/content/data-store.d.ts +20 -3
  23. package/dist/content/data-store.js +28 -7
  24. package/dist/content/mutable-data-store.js +15 -10
  25. package/dist/content/runtime.d.ts +3 -2
  26. package/dist/content/runtime.js +43 -26
  27. package/dist/core/app/app.d.ts +0 -2
  28. package/dist/core/app/app.js +0 -7
  29. package/dist/core/app/base.d.ts +32 -20
  30. package/dist/core/app/base.js +79 -73
  31. package/dist/core/app/dev-facade.d.ts +27 -0
  32. package/dist/core/app/dev-facade.js +51 -0
  33. package/dist/core/app/entrypoints/index.d.ts +0 -1
  34. package/dist/core/app/entrypoints/index.js +0 -2
  35. package/dist/core/app/entrypoints/virtual/dev.js +24 -19
  36. package/dist/core/app/node.js +13 -14
  37. package/dist/core/app/prepare-response.d.ts +1 -1
  38. package/dist/core/app/validate-headers.js +7 -3
  39. package/dist/core/build/app.d.ts +31 -6
  40. package/dist/core/build/app.js +31 -13
  41. package/dist/core/build/environment.d.ts +25 -0
  42. package/dist/core/build/environment.js +157 -0
  43. package/dist/core/cache/handler.d.ts +13 -7
  44. package/dist/core/cache/handler.js +55 -51
  45. package/dist/core/cache/provider.d.ts +4 -0
  46. package/dist/core/cache/provider.js +15 -0
  47. package/dist/core/constants.d.ts +0 -11
  48. package/dist/core/constants.js +1 -5
  49. package/dist/core/dev/dev.js +1 -1
  50. package/dist/core/environment/dev-nonrunnable.d.ts +6 -0
  51. package/dist/core/environment/dev-nonrunnable.js +170 -0
  52. package/dist/core/environment/index.d.ts +90 -0
  53. package/dist/core/environment/index.js +12 -0
  54. package/dist/core/environment/production.d.ts +6 -0
  55. package/dist/core/environment/production.js +117 -0
  56. package/dist/core/errors/build-handler.d.ts +5 -10
  57. package/dist/core/errors/build-handler.js +11 -17
  58. package/dist/core/errors/default-handler.d.ts +4 -9
  59. package/dist/core/errors/default-handler.js +92 -107
  60. package/dist/core/errors/dev-handler.d.ts +7 -11
  61. package/dist/core/errors/dev-handler.js +71 -69
  62. package/dist/core/errors/errors-data.d.ts +18 -0
  63. package/dist/core/errors/errors-data.js +7 -0
  64. package/dist/core/errors/handler.d.ts +22 -3
  65. package/dist/core/errors/handler.js +25 -0
  66. package/dist/core/fetch/default-handler.d.ts +15 -8
  67. package/dist/core/fetch/default-handler.js +12 -34
  68. package/dist/core/fetch/features.d.ts +23 -0
  69. package/dist/core/fetch/features.js +27 -0
  70. package/dist/core/fetch/fetch-state.d.ts +52 -7
  71. package/dist/core/fetch/fetch-state.js +99 -92
  72. package/dist/core/fetch/index.d.ts +9 -2
  73. package/dist/core/fetch/index.js +18 -79
  74. package/dist/core/fetch/vite-plugin.js +2 -1
  75. package/dist/core/i18n/domain.js +4 -11
  76. package/dist/core/i18n/handler.d.ts +28 -13
  77. package/dist/core/i18n/handler.js +100 -100
  78. package/dist/core/logger/manifest-logger.d.ts +31 -0
  79. package/dist/core/logger/manifest-logger.js +37 -0
  80. package/dist/core/manifest/ambient-source.d.ts +2 -0
  81. package/dist/core/manifest/ambient-source.js +4 -0
  82. package/dist/core/manifest/ambient.d.ts +16 -0
  83. package/dist/core/manifest/ambient.js +22 -0
  84. package/dist/core/manifest/derived.d.ts +3 -0
  85. package/dist/core/manifest/derived.js +10 -0
  86. package/dist/core/manifest/memo.d.ts +31 -0
  87. package/dist/core/manifest/memo.js +47 -0
  88. package/dist/core/messages/runtime.js +1 -1
  89. package/dist/core/middleware/astro-middleware.d.ts +25 -35
  90. package/dist/core/middleware/astro-middleware.js +61 -81
  91. package/dist/core/middleware/load.d.ts +19 -0
  92. package/dist/core/middleware/load.js +36 -0
  93. package/dist/core/middleware/sequence.js +15 -7
  94. package/dist/core/pages/handler.d.ts +18 -25
  95. package/dist/core/pages/handler.js +68 -84
  96. package/dist/core/redirects/render.js +3 -8
  97. package/dist/core/render/index.d.ts +0 -1
  98. package/dist/core/render/index.js +0 -2
  99. package/dist/core/render/route-cache.d.ts +6 -1
  100. package/dist/core/render/route-cache.js +11 -1
  101. package/dist/core/rewrites/handler.d.ts +4 -6
  102. package/dist/core/rewrites/handler.js +19 -20
  103. package/dist/core/routing/default.d.ts +2 -0
  104. package/dist/core/routing/default.js +7 -1
  105. package/dist/core/routing/dev.d.ts +1 -3
  106. package/dist/core/routing/dev.js +12 -5
  107. package/dist/core/routing/handler.d.ts +6 -16
  108. package/dist/core/routing/handler.js +126 -164
  109. package/dist/core/routing/helpers.d.ts +7 -1
  110. package/dist/core/routing/helpers.js +21 -0
  111. package/dist/core/routing/match-request.d.ts +10 -0
  112. package/dist/core/routing/match-request.js +46 -0
  113. package/dist/core/routing/route-table.d.ts +34 -0
  114. package/dist/core/routing/route-table.js +41 -0
  115. package/dist/core/routing/trailing-slash-handler.d.ts +4 -14
  116. package/dist/core/routing/trailing-slash-handler.js +39 -50
  117. package/dist/core/server-islands/mappings.d.ts +6 -0
  118. package/dist/core/server-islands/mappings.js +12 -0
  119. package/dist/core/session/driver.d.ts +4 -0
  120. package/dist/core/session/driver.js +14 -0
  121. package/dist/core/session/handler.d.ts +1 -1
  122. package/dist/core/session/handler.js +8 -8
  123. package/dist/core/session/provider-disabled.js +2 -2
  124. package/dist/entrypoints/prerender.js +5 -1
  125. package/dist/i18n/middleware.d.ts +4 -4
  126. package/dist/i18n/middleware.js +3 -3
  127. package/dist/manifest/serialized.d.ts +1 -0
  128. package/dist/manifest/serialized.js +9 -2
  129. package/dist/runtime/prerender/static-paths.d.ts +14 -2
  130. package/dist/runtime/prerender/static-paths.js +4 -3
  131. package/dist/types/public/config.d.ts +433 -241
  132. package/dist/vite-plugin-app/createAstroServerApp.js +22 -18
  133. package/dist/vite-plugin-app/environment.d.ts +18 -0
  134. package/dist/vite-plugin-app/environment.js +210 -0
  135. package/dist/vite-plugin-app/handle-request.d.ts +30 -0
  136. package/dist/vite-plugin-app/handle-request.js +129 -0
  137. package/dist/vite-plugin-app/index.d.ts +1 -1
  138. package/dist/vite-plugin-app/index.js +1 -1
  139. package/package.json +14 -7
  140. package/src/core/README.md +37 -0
  141. package/src/core/manifest/ambient-source.ts +9 -0
  142. package/src/types/README.md +5 -0
  143. package/dist/container/pipeline.d.ts +0 -14
  144. package/dist/container/pipeline.js +0 -78
  145. package/dist/core/app/dev/app.d.ts +0 -31
  146. package/dist/core/app/dev/app.js +0 -80
  147. package/dist/core/app/dev/pipeline.d.ts +0 -17
  148. package/dist/core/app/dev/pipeline.js +0 -133
  149. package/dist/core/app/pipeline.d.ts +0 -14
  150. package/dist/core/app/pipeline.js +0 -123
  151. package/dist/core/base-pipeline.d.ts +0 -183
  152. package/dist/core/base-pipeline.js +0 -293
  153. package/dist/core/build/pipeline.d.ts +0 -38
  154. package/dist/core/build/pipeline.js +0 -202
  155. package/dist/vite-plugin-app/app.d.ts +0 -62
  156. package/dist/vite-plugin-app/app.js +0 -237
  157. package/dist/vite-plugin-app/pipeline.d.ts +0 -25
  158. package/dist/vite-plugin-app/pipeline.js +0 -189
@@ -1,125 +1,110 @@
1
+ import { removeTrailingForwardSlash } from "@astrojs/internal-helpers/path";
2
+ import { getEnvironment } from "../environment/index.js";
1
3
  import { FetchState } from "../fetch/fetch-state.js";
2
4
  import { prepareResponse } from "../app/prepare-response.js";
3
5
  import { attachCookiesToResponse } from "../cookies/index.js";
4
6
  import { getCookiesFromResponse } from "../cookies/response.js";
5
- import { AstroMiddleware } from "../middleware/astro-middleware.js";
6
- import { PagesHandler } from "../pages/handler.js";
7
+ import { handleMiddleware } from "../middleware/astro-middleware.js";
8
+ import { handlePages } from "../pages/handler.js";
7
9
  import { matchRoute } from "../routing/match.js";
10
+ import { getRouteTable } from "../routing/route-table.js";
8
11
  import { provideSession } from "../session/provider.js";
9
12
  import { validateHost } from "../app/validate-headers.js";
10
13
  import { getErrorRoutePath } from "../../i18n/error-routes.js";
11
14
  import { getOutputFilename } from "../output-filename.js";
12
15
  import { rewroteToEmptyErrorResponse } from "./handler.js";
13
- class DefaultErrorHandler {
14
- #app;
15
- #astroMiddleware;
16
- #pagesHandler;
17
- constructor(app) {
18
- this.#app = app;
19
- this.#astroMiddleware = new AstroMiddleware(app.pipeline);
20
- this.#pagesHandler = new PagesHandler(app.pipeline);
21
- }
22
- async renderError(request, {
16
+ async function renderDefaultError(manifest, request, {
17
+ status,
18
+ response: originalResponse,
19
+ skipMiddleware = false,
20
+ error,
21
+ pathname,
22
+ ...resolvedRenderOptions
23
+ }) {
24
+ const resolvedPathname = pathname ?? new FetchState(manifest, request).pathname;
25
+ const routeTable = getRouteTable(manifest);
26
+ const errorRoutePath = getErrorRoutePath(
27
+ resolvedPathname,
23
28
  status,
24
- response: originalResponse,
25
- skipMiddleware = false,
26
- error,
27
- pathname,
28
- ...resolvedRenderOptions
29
- }) {
30
- const app = this.#app;
31
- const resolvedPathname = pathname ?? new FetchState(app.pipeline, request).pathname;
32
- const errorRoutePath = getErrorRoutePath(
33
- resolvedPathname,
34
- status,
35
- app.manifestData.routes,
36
- app.manifest.i18n?.locales,
37
- app.manifest.trailingSlash === "always"
38
- );
39
- const errorRouteData = matchRoute(errorRoutePath, app.manifestData);
40
- const url = new URL(request.url);
41
- if (errorRouteData) {
42
- if (errorRouteData.prerender) {
43
- const allowedDomains = app.manifest.allowedDomains;
44
- const validatedHost = validateHost(url.host, url.protocol.replace(":", ""), allowedDomains);
45
- const safeOrigin = validatedHost ? url.origin : `${url.protocol}//localhost`;
46
- const statusURL = new URL(
47
- `${app.baseWithoutTrailingSlash}${getOutputFilename(
48
- app.manifest.buildFormat,
49
- errorRouteData.route,
50
- errorRouteData
51
- )}`,
52
- safeOrigin
53
- );
54
- if (statusURL.toString() !== request.url && resolvedRenderOptions.prerenderedErrorPageFetch) {
55
- try {
56
- const response2 = await resolvedRenderOptions.prerenderedErrorPageFetch(
57
- statusURL.toString()
58
- );
59
- const override = { status, removeContentEncodingHeaders: true };
60
- const newResponse = mergeResponses(response2, originalResponse, override);
61
- prepareResponse(newResponse, resolvedRenderOptions);
62
- return newResponse;
63
- } catch {
64
- const response2 = mergeResponses(new Response(null, { status }), originalResponse);
65
- prepareResponse(response2, resolvedRenderOptions);
66
- return response2;
67
- }
29
+ routeTable.routes,
30
+ manifest.i18n?.locales,
31
+ manifest.trailingSlash === "always"
32
+ );
33
+ const errorRouteData = matchRoute(errorRoutePath, routeTable);
34
+ const url = new URL(request.url);
35
+ if (errorRouteData) {
36
+ if (errorRouteData.prerender) {
37
+ const allowedDomains = manifest.allowedDomains;
38
+ const validatedHost = validateHost(url.host, url.protocol.replace(":", ""), allowedDomains);
39
+ const safeOrigin = validatedHost ? url.origin : `${url.protocol}//localhost`;
40
+ const statusURL = new URL(
41
+ `${removeTrailingForwardSlash(manifest.base)}${getOutputFilename(
42
+ manifest.buildFormat,
43
+ errorRouteData.route,
44
+ errorRouteData
45
+ )}`,
46
+ safeOrigin
47
+ );
48
+ if (statusURL.toString() !== request.url && resolvedRenderOptions.prerenderedErrorPageFetch) {
49
+ try {
50
+ const response2 = await resolvedRenderOptions.prerenderedErrorPageFetch(
51
+ statusURL.toString()
52
+ );
53
+ const override = { status, removeContentEncodingHeaders: true };
54
+ const newResponse = mergeResponses(response2, originalResponse, override);
55
+ prepareResponse(newResponse, resolvedRenderOptions);
56
+ return newResponse;
57
+ } catch {
58
+ const response2 = mergeResponses(new Response(null, { status }), originalResponse);
59
+ prepareResponse(response2, resolvedRenderOptions);
60
+ return response2;
68
61
  }
69
62
  }
70
- const mod = await app.pipeline.getComponentByRoute(errorRouteData);
71
- const errorState = new FetchState(app.pipeline, request);
72
- errorState.skipMiddleware = skipMiddleware;
73
- errorState.clientAddress = resolvedRenderOptions.clientAddress;
74
- errorState.routeData = errorRouteData;
75
- errorState.pathname = resolvedPathname;
76
- errorState.status = status;
77
- errorState.componentInstance = mod;
78
- errorState.locals = resolvedRenderOptions.locals ?? {};
79
- errorState.initialProps = { error };
80
- try {
81
- await provideSession(errorState);
82
- const response2 = await this.#astroMiddleware.handle(
83
- errorState,
84
- this.#pagesHandler.handle.bind(this.#pagesHandler)
85
- );
86
- if (rewroteToEmptyErrorResponse(
87
- skipMiddleware,
88
- errorRouteData,
89
- errorState.routeData,
90
- response2
91
- )) {
92
- return this.renderError(request, {
93
- ...resolvedRenderOptions,
94
- status,
95
- error,
96
- response: originalResponse,
97
- skipMiddleware: true,
98
- pathname: resolvedPathname
99
- });
100
- }
101
- const newResponse = mergeResponses(response2, originalResponse);
102
- prepareResponse(newResponse, resolvedRenderOptions);
103
- return newResponse;
104
- } catch {
105
- if (skipMiddleware === false) {
106
- return this.renderError(request, {
107
- ...resolvedRenderOptions,
108
- status,
109
- error,
110
- response: originalResponse,
111
- skipMiddleware: true,
112
- pathname: resolvedPathname
113
- });
114
- }
115
- } finally {
116
- await errorState.finalizeAll();
63
+ }
64
+ const mod = await getEnvironment(manifest).getComponentByRoute(manifest, errorRouteData);
65
+ const errorState = new FetchState(manifest, request);
66
+ errorState.skipMiddleware = skipMiddleware;
67
+ errorState.clientAddress = resolvedRenderOptions.clientAddress;
68
+ errorState.routeData = errorRouteData;
69
+ errorState.pathname = resolvedPathname;
70
+ errorState.status = status;
71
+ errorState.componentInstance = mod;
72
+ errorState.locals = resolvedRenderOptions.locals ?? {};
73
+ errorState.initialProps = { error };
74
+ try {
75
+ await provideSession(errorState);
76
+ const response2 = await handleMiddleware(errorState, handlePages);
77
+ if (rewroteToEmptyErrorResponse(skipMiddleware, errorRouteData, errorState.routeData, response2)) {
78
+ return renderDefaultError(manifest, request, {
79
+ ...resolvedRenderOptions,
80
+ status,
81
+ error,
82
+ response: originalResponse,
83
+ skipMiddleware: true,
84
+ pathname: resolvedPathname
85
+ });
86
+ }
87
+ const newResponse = mergeResponses(response2, originalResponse);
88
+ prepareResponse(newResponse, resolvedRenderOptions);
89
+ return newResponse;
90
+ } catch {
91
+ if (skipMiddleware === false) {
92
+ return renderDefaultError(manifest, request, {
93
+ ...resolvedRenderOptions,
94
+ status,
95
+ error,
96
+ response: originalResponse,
97
+ skipMiddleware: true,
98
+ pathname: resolvedPathname
99
+ });
117
100
  }
101
+ } finally {
102
+ await errorState.finalizeAll();
118
103
  }
119
- const response = mergeResponses(new Response(null, { status }), originalResponse);
120
- prepareResponse(response, resolvedRenderOptions);
121
- return response;
122
104
  }
105
+ const response = mergeResponses(new Response(null, { status }), originalResponse);
106
+ prepareResponse(response, resolvedRenderOptions);
107
+ return response;
123
108
  }
124
109
  function mergeResponses(newResponse, originalResponse, override) {
125
110
  let newResponseHeaders = newResponse.headers;
@@ -180,5 +165,5 @@ function mergeResponses(newResponse, originalResponse, override) {
180
165
  return mergedResponse;
181
166
  }
182
167
  export {
183
- DefaultErrorHandler
168
+ renderDefaultError
184
169
  };
@@ -1,6 +1,5 @@
1
- import type { BaseApp, RenderErrorOptions } from '../app/base.js';
2
- import type { Pipeline } from '../base-pipeline.js';
3
- import { type ErrorHandler } from './handler.js';
1
+ import type { RenderErrorOptions } from '../app/base.js';
2
+ import type { SSRManifest } from '../app/types.js';
4
3
  export interface DevErrorHandlerOptions {
5
4
  /**
6
5
  * Whether to inject CSP meta tags into the rendered error page response.
@@ -9,13 +8,10 @@ export interface DevErrorHandlerOptions {
9
8
  shouldInjectCspMetaTags: boolean;
10
9
  }
11
10
  /**
12
- * The dev-server error handler. Renders custom 404/500 routes if the user
11
+ * The dev-server error strategy. Renders custom 404/500 routes if the user
13
12
  * has them, otherwise throws so Vite's dev overlay is shown. Shared between
14
- * the Vite dev server (`AstroServerApp`) and the non-runnable dev pipeline
15
- * (`DevApp`); only `shouldInjectCspMetaTags` differs between them.
13
+ * the Vite dev server and the non-runnable dev pipeline; only
14
+ * `shouldInjectCspMetaTags` differs between them (carried by the
15
+ * environment record's `injectCspMetaTagsOnErrorPages` static).
16
16
  */
17
- export declare class DevErrorHandler implements ErrorHandler {
18
- #private;
19
- constructor(app: BaseApp<Pipeline>, options: DevErrorHandlerOptions);
20
- renderError(request: Request, { skipMiddleware, error, status, response: _response, pathname, ...resolvedRenderOptions }: RenderErrorOptions): Promise<Response>;
21
- }
17
+ export declare function renderDevError(manifest: SSRManifest, request: Request, { skipMiddleware, error, status, response: _response, pathname, ...resolvedRenderOptions }: RenderErrorOptions, { shouldInjectCspMetaTags }: DevErrorHandlerOptions): Promise<Response>;
@@ -1,92 +1,94 @@
1
+ import { getEnvironment } from "../environment/index.js";
1
2
  import { FetchState } from "../fetch/fetch-state.js";
2
- import { AstroMiddleware } from "../middleware/astro-middleware.js";
3
- import { PagesHandler } from "../pages/handler.js";
3
+ import { getLogger } from "../logger/manifest-logger.js";
4
+ import { handleMiddleware } from "../middleware/astro-middleware.js";
5
+ import { handlePages } from "../pages/handler.js";
4
6
  import { getCustom404Route, getCustom500Route } from "../routing/helpers.js";
7
+ import { getRouteTable } from "../routing/route-table.js";
5
8
  import { isAstroError } from "./index.js";
6
9
  import { MiddlewareNoDataOrNextCalled, MiddlewareNotAResponse } from "./errors-data.js";
7
10
  import { rewroteToEmptyErrorResponse } from "./handler.js";
8
- class DevErrorHandler {
9
- #app;
10
- #shouldInjectCspMetaTags;
11
- #astroMiddleware;
12
- #pagesHandler;
13
- constructor(app, options) {
14
- this.#app = app;
15
- this.#shouldInjectCspMetaTags = options.shouldInjectCspMetaTags;
16
- this.#astroMiddleware = new AstroMiddleware(app.pipeline);
17
- this.#pagesHandler = new PagesHandler(app.pipeline);
11
+ async function renderDevError(manifest, request, {
12
+ skipMiddleware = false,
13
+ error,
14
+ status,
15
+ response: _response,
16
+ pathname,
17
+ ...resolvedRenderOptions
18
+ }, { shouldInjectCspMetaTags }) {
19
+ if (isAstroError(error) && [MiddlewareNoDataOrNextCalled.name, MiddlewareNotAResponse.name].includes(error.name)) {
20
+ throw error;
18
21
  }
19
- async renderError(request, {
20
- skipMiddleware = false,
21
- error,
22
- status,
23
- response: _response,
24
- pathname,
25
- ...resolvedRenderOptions
26
- }) {
27
- if (isAstroError(error) && [MiddlewareNoDataOrNextCalled.name, MiddlewareNotAResponse.name].includes(error.name)) {
28
- throw error;
29
- }
30
- const app = this.#app;
31
- const shouldInjectCspMetaTags = this.#shouldInjectCspMetaTags;
32
- const resolvedPathname = pathname ?? new FetchState(app.pipeline, request).pathname;
33
- const renderRoute = async (routeData) => {
34
- try {
35
- const preloadedComponent = await app.pipeline.getComponentByRoute(routeData);
36
- const errorState = new FetchState(app.pipeline, request);
37
- errorState.skipMiddleware = skipMiddleware;
38
- errorState.clientAddress = resolvedRenderOptions.clientAddress;
39
- errorState.shouldInjectCspMetaTags = shouldInjectCspMetaTags ? !!app.manifest.csp : false;
40
- errorState.routeData = routeData;
41
- errorState.pathname = resolvedPathname;
42
- errorState.status = status;
43
- errorState.componentInstance = preloadedComponent;
44
- errorState.locals = resolvedRenderOptions.locals ?? {};
45
- errorState.initialProps = { error };
46
- const response = await this.#astroMiddleware.handle(
47
- errorState,
48
- this.#pagesHandler.handle.bind(this.#pagesHandler)
49
- );
50
- if (rewroteToEmptyErrorResponse(skipMiddleware, routeData, errorState.routeData, response)) {
51
- return this.renderError(request, {
22
+ const resolvedPathname = pathname ?? new FetchState(manifest, request).pathname;
23
+ const renderRoute = async (routeData) => {
24
+ try {
25
+ const preloadedComponent = await getEnvironment(manifest).getComponentByRoute(
26
+ manifest,
27
+ routeData
28
+ );
29
+ const errorState = new FetchState(manifest, request);
30
+ errorState.skipMiddleware = skipMiddleware;
31
+ errorState.clientAddress = resolvedRenderOptions.clientAddress;
32
+ errorState.shouldInjectCspMetaTags = shouldInjectCspMetaTags ? !!manifest.csp : false;
33
+ errorState.routeData = routeData;
34
+ errorState.pathname = resolvedPathname;
35
+ errorState.status = status;
36
+ errorState.componentInstance = preloadedComponent;
37
+ errorState.locals = resolvedRenderOptions.locals ?? {};
38
+ errorState.initialProps = { error };
39
+ const response = await handleMiddleware(errorState, handlePages);
40
+ if (rewroteToEmptyErrorResponse(skipMiddleware, routeData, errorState.routeData, response)) {
41
+ return renderDevError(
42
+ manifest,
43
+ request,
44
+ {
52
45
  ...resolvedRenderOptions,
53
46
  status,
54
47
  error,
55
48
  skipMiddleware: true,
56
49
  pathname: resolvedPathname
57
- });
58
- }
59
- if (error) {
60
- app.logger.error("router", error.stack || error.message);
61
- }
62
- return response;
63
- } catch (_err) {
64
- if (skipMiddleware === false) {
65
- return this.renderError(request, {
50
+ },
51
+ { shouldInjectCspMetaTags }
52
+ );
53
+ }
54
+ if (error) {
55
+ getLogger(manifest).error(
56
+ "router",
57
+ error.stack || error.message
58
+ );
59
+ }
60
+ return response;
61
+ } catch (_err) {
62
+ if (skipMiddleware === false) {
63
+ return renderDevError(
64
+ manifest,
65
+ request,
66
+ {
66
67
  ...resolvedRenderOptions,
67
68
  status: 500,
68
69
  skipMiddleware: true,
69
70
  error: _err,
70
71
  pathname: resolvedPathname
71
- });
72
- }
73
- throw _err;
74
- }
75
- };
76
- if (status === 404) {
77
- const custom404 = getCustom404Route(app.manifestData);
78
- if (custom404) {
79
- return renderRoute(custom404);
72
+ },
73
+ { shouldInjectCspMetaTags }
74
+ );
80
75
  }
76
+ throw _err;
81
77
  }
82
- const custom500 = getCustom500Route(app.manifestData);
83
- if (!custom500) {
84
- throw error;
85
- } else {
86
- return renderRoute(custom500);
78
+ };
79
+ if (status === 404) {
80
+ const custom404 = getCustom404Route(getRouteTable(manifest));
81
+ if (custom404) {
82
+ return renderRoute(custom404);
87
83
  }
88
84
  }
85
+ const custom500 = getCustom500Route(getRouteTable(manifest));
86
+ if (!custom500) {
87
+ throw error;
88
+ } else {
89
+ return renderRoute(custom500);
90
+ }
89
91
  }
90
92
  export {
91
- DevErrorHandler
93
+ renderDevError
92
94
  };
@@ -1377,6 +1377,24 @@ export declare const LoggerConfigurationNotSerializable: {
1377
1377
  name: string;
1378
1378
  title: string;
1379
1379
  };
1380
+ /**
1381
+ * @docs
1382
+ * @description
1383
+ * `new FetchState(request)` can only be used inside an Astro server — the built
1384
+ * server output or the dev server — where Astro provides the manifest describing
1385
+ * your site. This error means it was called somewhere else, for example in a
1386
+ * plain Node script that imports `astro/fetch`.
1387
+ *
1388
+ * If this error occurs inside an Astro-built server, please [open an issue](https://astro.build/issues/).
1389
+ * @message
1390
+ * `new FetchState(request)` was called outside of an Astro server, so no manifest is available.
1391
+ */
1392
+ export declare const NoManifestAvailable: {
1393
+ name: string;
1394
+ title: string;
1395
+ message: string;
1396
+ hint: string;
1397
+ };
1380
1398
  /**
1381
1399
  * @docs
1382
1400
  * @kind heading
@@ -527,6 +527,12 @@ const LoggerConfigurationNotSerializable = {
527
527
  name: "LoggerConfigurationNotSerializable",
528
528
  title: "The configuration of the logger is not serializable."
529
529
  };
530
+ const NoManifestAvailable = {
531
+ name: "NoManifestAvailableError",
532
+ title: "No manifest available.",
533
+ message: "`new FetchState(request)` was called outside of an Astro server, so no manifest is available.",
534
+ hint: "Make sure this code runs as part of your Astro app, such as its fetch entrypoint. If this error occurred inside an Astro-built server, please open an issue at https://github.com/withastro/astro/issues."
535
+ };
530
536
  const UnknownCSSError = {
531
537
  name: "UnknownCSSError",
532
538
  title: "Unknown CSS error."
@@ -896,6 +902,7 @@ export {
896
902
  NoClientEntrypoint,
897
903
  NoClientOnlyHint,
898
904
  NoImageMetadata,
905
+ NoManifestAvailable,
899
906
  NoMatchingImport,
900
907
  NoMatchingRenderer,
901
908
  NoMatchingStaticPathFound,
@@ -1,13 +1,32 @@
1
1
  import type { RenderErrorOptions } from '../app/base.js';
2
2
  import type { RouteData } from '../../types/public/index.js';
3
+ import type { SSRManifest } from '../app/types.js';
4
+ import type { FetchState } from '../fetch/fetch-state.js';
3
5
  /**
4
- * A strategy for rendering error responses (404, 500, etc.). Each execution
5
- * environment (prod SSR, build/prerender, dev server) supplies its own
6
- * implementation rather than overriding a method on the app.
6
+ * A strategy for rendering error responses (404, 500, etc.).
7
+ *
8
+ * Internal shape of `BaseApp`'s `#errorHandler` (whose default wraps
9
+ * {@link renderErrorPage}); external `BaseApp` subclasses may return their
10
+ * own implementation from the protected `createErrorHandler()`.
7
11
  */
8
12
  export interface ErrorHandler {
9
13
  renderError(request: Request, options: RenderErrorOptions): Promise<Response>;
10
14
  }
15
+ /**
16
+ * Renders the error page (404.astro / 500.astro or a plain response) for a
17
+ * request, dispatching to the strategy the manifest's environment selects:
18
+ * production/container default, dev (overlay + custom error routes, with or
19
+ * without CSP meta-tag injection), or build (500s throw so the build fails).
20
+ */
21
+ export declare function renderErrorPage(manifest: SSRManifest, request: Request, options: RenderErrorOptions): Promise<Response>;
22
+ /**
23
+ * Dispatches an internal error render for a request flowing through the
24
+ * handler chain: through the facade's late-bound `renderError` hook when the
25
+ * state was built by `BaseApp.render`'s fast path (preserving instance
26
+ * overrides/reassignments, e.g. cloudflare's prerender-error propagation),
27
+ * else through the environment's strategy via {@link renderErrorPage}.
28
+ */
29
+ export declare function renderErrorFromState(state: FetchState, request: Request, options: RenderErrorOptions): Promise<Response>;
11
30
  /**
12
31
  * Whether a middleware rewrite (`ctx.rewrite()` / `next(payload)`) issued while
13
32
  * rendering the error page dead-ended in another empty reroutable (404/500)
@@ -1,7 +1,32 @@
1
1
  import { REROUTABLE_STATUS_CODES } from "../constants.js";
2
+ import { getEnvironment } from "../environment/index.js";
3
+ import { renderBuildError } from "./build-handler.js";
4
+ import { renderDefaultError } from "./default-handler.js";
5
+ import { renderDevError } from "./dev-handler.js";
6
+ function renderErrorPage(manifest, request, options) {
7
+ const env = getEnvironment(manifest);
8
+ switch (env.errorStrategy) {
9
+ case "dev":
10
+ return renderDevError(manifest, request, options, {
11
+ shouldInjectCspMetaTags: env.injectCspMetaTagsOnErrorPages
12
+ });
13
+ case "build":
14
+ return renderBuildError(manifest, request, options);
15
+ case "default":
16
+ return renderDefaultError(manifest, request, options);
17
+ }
18
+ }
19
+ function renderErrorFromState(state, request, options) {
20
+ if (state.renderError) {
21
+ return state.renderError(request, options);
22
+ }
23
+ return renderErrorPage(state.manifest, request, options);
24
+ }
2
25
  function rewroteToEmptyErrorResponse(skipMiddleware, errorRouteData, renderedRouteData, response) {
3
26
  return skipMiddleware === false && renderedRouteData !== errorRouteData && response.body === null && REROUTABLE_STATUS_CODES.includes(response.status);
4
27
  }
5
28
  export {
29
+ renderErrorFromState,
30
+ renderErrorPage,
6
31
  rewroteToEmptyErrorResponse
7
32
  };
@@ -1,17 +1,24 @@
1
- import type { BaseApp, ResolvedRenderOptions } from '../app/base.js';
2
- import type { Pipeline } from '../base-pipeline.js';
1
+ import type { SSRManifest } from '../app/types.js';
3
2
  import type { FetchHandler } from './types.js';
4
3
  /**
5
- * The default request handler for `BaseApp`. Builds the per-request
6
- * `FetchState` and delegates to an `AstroHandler`.
4
+ * The default request handler for `BaseApp`. Stateless: builds the
5
+ * per-request `FetchState` from the manifest and delegates to
6
+ * `handleRequest`.
7
+ *
8
+ * The export path (`astro/app/fetch/default-handler`), the class name, and
9
+ * no-arg constructibility are baked into generated builds
10
+ * (`core/fetch/vite-plugin.ts` emits `new DefaultFetchHandler()`), so all
11
+ * three survive.
7
12
  */
8
13
  export declare class DefaultFetchHandler {
9
14
  #private;
10
- constructor(app?: BaseApp<Pipeline>);
11
15
  /**
12
- * Fast path: called directly by `BaseApp.render()` with pre-resolved
13
- * options, avoiding the `Reflect.set/get` round-trip through the request.
16
+ * `BaseApp` passes itself so states resolve that app's manifest ahead of
17
+ * the ambient one; generated builds construct the handler with no
18
+ * arguments and use the ambient manifest.
14
19
  */
15
- renderWithOptions(request: Request, options: ResolvedRenderOptions): Promise<Response>;
20
+ constructor(app?: {
21
+ manifest: SSRManifest;
22
+ });
16
23
  fetch: FetchHandler;
17
24
  }
@@ -1,43 +1,21 @@
1
+ import { getAmbientManifest } from "../manifest/ambient.js";
2
+ import { getRenderOptions } from "../app/render-options.js";
3
+ import { handleRequest } from "../routing/handler.js";
1
4
  import { FetchState } from "./fetch-state.js";
2
- import { appSymbol } from "../constants.js";
3
- import { AstroHandler } from "../routing/handler.js";
4
5
  class DefaultFetchHandler {
5
- #app;
6
- #handler;
7
- constructor(app) {
8
- this.#app = app ?? null;
9
- this.#handler = app ? new AstroHandler(app) : null;
10
- }
6
+ #manifest;
11
7
  /**
12
- * Fast path: called directly by `BaseApp.render()` with pre-resolved
13
- * options, avoiding the `Reflect.set/get` round-trip through the request.
8
+ * `BaseApp` passes itself so states resolve that app's manifest ahead of
9
+ * the ambient one; generated builds construct the handler with no
10
+ * arguments and use the ambient manifest.
14
11
  */
15
- renderWithOptions(request, options) {
16
- if (!this.#app) {
17
- const app = Reflect.get(request, appSymbol);
18
- if (!app) {
19
- throw new Error("No fetch handler provided.");
20
- }
21
- this.#app = app;
22
- this.#handler = new AstroHandler(app);
23
- }
24
- const state = new FetchState(this.#app.pipeline, request, options);
25
- return this.#handler.handle(state);
12
+ constructor(app) {
13
+ this.#manifest = app?.manifest;
26
14
  }
27
15
  fetch = (request) => {
28
- if (!this.#app) {
29
- const app = Reflect.get(request, appSymbol);
30
- if (!app) {
31
- throw new Error("No fetch handler provided.");
32
- }
33
- this.#app = app;
34
- this.#handler = new AstroHandler(app);
35
- }
36
- const state = new FetchState(this.#app.pipeline, request);
37
- if (!this.#handler) {
38
- throw new Error("No fetch handler provided.");
39
- }
40
- return this.#handler.handle(state);
16
+ const options = getRenderOptions(request);
17
+ const manifest = this.#manifest ?? getAmbientManifest();
18
+ return handleRequest(new FetchState(manifest, request, options));
41
19
  };
42
20
  }
43
21
  export {
@@ -0,0 +1,23 @@
1
+ import type { SSRManifest } from '../app/types.js';
2
+ /**
3
+ * Bit flags for features that handler functions register as "used" when a
4
+ * custom `src/fetch.ts` fetch handler is in play. After the first request
5
+ * (dev) or at runtime (prod SSR), we compare against the manifest to warn
6
+ * about features the user configured but forgot to include in their custom
7
+ * fetch handler.
8
+ */
9
+ export declare const FetchFeatures: {
10
+ readonly redirects: number;
11
+ readonly sessions: number;
12
+ readonly actions: number;
13
+ readonly middleware: number;
14
+ readonly i18n: number;
15
+ readonly cache: number;
16
+ };
17
+ /** All feature bits ORed together. Keep next to `FetchFeatures` so
18
+ * new flags are hard to forget. */
19
+ export declare const ALL_FETCH_FEATURES: number;
20
+ /** ORs a feature bit into the manifest's used-features bitmask. */
21
+ export declare function markFeatureUsed(manifest: SSRManifest, feature: number): void;
22
+ /** The used-features bitmask for a manifest; `0` when nothing was marked. */
23
+ export declare function getUsedFeatures(manifest: SSRManifest): number;