astro 7.0.0-alpha.0 → 7.0.0-alpha.2

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 (251) hide show
  1. package/components/Code.astro +1 -1
  2. package/dist/actions/handler.d.ts +32 -0
  3. package/dist/actions/handler.js +45 -0
  4. package/dist/actions/runtime/server.js +1 -1
  5. package/dist/assets/build/generate.js +1 -1
  6. package/dist/assets/build/remote.d.ts +3 -2
  7. package/dist/assets/build/remote.js +16 -9
  8. package/dist/assets/endpoint/dev.js +1 -1
  9. package/dist/assets/endpoint/generic.js +8 -20
  10. package/dist/assets/endpoint/loadImage.d.ts +11 -0
  11. package/dist/assets/endpoint/loadImage.js +19 -0
  12. package/dist/assets/endpoint/shared.js +7 -2
  13. package/dist/assets/fonts/config.d.ts +4 -4
  14. package/dist/assets/fonts/core/optimize-fallbacks.js +38 -13
  15. package/dist/assets/fonts/definitions.d.ts +2 -2
  16. package/dist/assets/fonts/infra/system-fallbacks-provider.d.ts +2 -2
  17. package/dist/assets/fonts/infra/system-fallbacks-provider.js +46 -9
  18. package/dist/assets/fonts/types.d.ts +1 -0
  19. package/dist/assets/index.d.ts +1 -0
  20. package/dist/assets/index.js +2 -0
  21. package/dist/assets/internal.js +22 -3
  22. package/dist/assets/services/service.d.ts +1 -1
  23. package/dist/assets/services/service.js +9 -9
  24. package/dist/assets/services/sharp.js +53 -18
  25. package/dist/assets/utils/generateImageStylesCSS.js +26 -6
  26. package/dist/assets/utils/index.d.ts +1 -0
  27. package/dist/assets/utils/index.js +2 -0
  28. package/dist/assets/utils/inferSourceFormat.d.ts +8 -3
  29. package/dist/assets/utils/inferSourceFormat.js +15 -4
  30. package/dist/assets/utils/metadata.js +1 -1
  31. package/dist/assets/utils/redirectValidation.d.ts +48 -0
  32. package/dist/assets/utils/redirectValidation.js +48 -0
  33. package/dist/assets/utils/remoteProbe.js +25 -2
  34. package/dist/assets/utils/vendor/image-size/types/svg.js +1 -1
  35. package/dist/cli/add/index.js +7 -58
  36. package/dist/cli/dev/background.d.ts +16 -0
  37. package/dist/cli/dev/background.js +116 -0
  38. package/dist/cli/dev/index.js +82 -3
  39. package/dist/cli/dev/logs.d.ts +6 -0
  40. package/dist/cli/dev/logs.js +72 -0
  41. package/dist/cli/dev/status.d.ts +15 -0
  42. package/dist/cli/dev/status.js +27 -0
  43. package/dist/cli/dev/stop.d.ts +12 -0
  44. package/dist/cli/dev/stop.js +43 -0
  45. package/dist/cli/infra/build-time-astro-version-provider.js +1 -1
  46. package/dist/container/index.js +18 -14
  47. package/dist/content/content-layer.js +16 -11
  48. package/dist/content/data-store.d.ts +1 -1
  49. package/dist/content/loaders/types.d.ts +1 -1
  50. package/dist/content/runtime-assets.d.ts +2 -2
  51. package/dist/content/runtime.d.ts +1 -1
  52. package/dist/content/runtime.js +9 -4
  53. package/dist/content/server-listeners.js +0 -4
  54. package/dist/content/types-generator.js +5 -1
  55. package/dist/content/utils.d.ts +1 -1
  56. package/dist/content/utils.js +1 -1
  57. package/dist/content/vite-plugin-content-assets.js +1 -0
  58. package/dist/content/vite-plugin-content-virtual-mod.js +9 -1
  59. package/dist/core/app/base.d.ts +42 -15
  60. package/dist/core/app/base.js +151 -375
  61. package/dist/core/app/dev/app.d.ts +3 -2
  62. package/dist/core/app/dev/app.js +4 -60
  63. package/dist/core/app/entrypoints/node.d.ts +1 -1
  64. package/dist/core/app/entrypoints/node.js +2 -0
  65. package/dist/core/app/entrypoints/virtual/dev.js +2 -0
  66. package/dist/core/app/entrypoints/virtual/prod.js +4 -1
  67. package/dist/core/app/node.d.ts +16 -0
  68. package/dist/core/app/node.js +59 -13
  69. package/dist/core/app/prepare-response.d.ts +11 -0
  70. package/dist/core/app/prepare-response.js +18 -0
  71. package/dist/core/app/render-options.d.ts +11 -0
  72. package/dist/core/app/render-options.js +11 -0
  73. package/dist/core/base-pipeline.d.ts +48 -1
  74. package/dist/core/base-pipeline.js +63 -8
  75. package/dist/core/build/app.d.ts +3 -4
  76. package/dist/core/build/app.js +3 -17
  77. package/dist/core/build/generate.js +8 -1
  78. package/dist/core/build/index.d.ts +0 -11
  79. package/dist/core/build/index.js +0 -3
  80. package/dist/core/build/internal.d.ts +7 -0
  81. package/dist/core/build/plugins/plugin-chunk-imports.d.ts +6 -0
  82. package/dist/core/build/plugins/plugin-chunk-imports.js +29 -17
  83. package/dist/core/build/plugins/plugin-css.js +40 -1
  84. package/dist/core/build/plugins/plugin-internals.js +1 -1
  85. package/dist/core/build/plugins/plugin-manifest.js +11 -1
  86. package/dist/core/build/static-build.js +22 -141
  87. package/dist/core/build/types.d.ts +0 -1
  88. package/dist/core/build/util.js +8 -1
  89. package/dist/core/build/vite-build-config.d.ts +28 -0
  90. package/dist/core/build/vite-build-config.js +165 -0
  91. package/dist/core/cache/handler.d.ts +29 -0
  92. package/dist/core/cache/handler.js +81 -0
  93. package/dist/core/compile/style.js +18 -1
  94. package/dist/core/config/index.d.ts +1 -1
  95. package/dist/core/config/index.js +4 -1
  96. package/dist/core/config/merge.js +4 -0
  97. package/dist/core/config/schemas/base.d.ts +25 -13
  98. package/dist/core/config/schemas/base.js +39 -10
  99. package/dist/core/config/schemas/relative.d.ts +76 -49
  100. package/dist/core/config/schemas/relative.js +2 -3
  101. package/dist/core/config/settings.js +2 -4
  102. package/dist/core/config/tsconfig.d.ts +24 -9
  103. package/dist/core/config/tsconfig.js +54 -45
  104. package/dist/core/config/validate.js +59 -0
  105. package/dist/core/constants.d.ts +27 -1
  106. package/dist/core/constants.js +14 -1
  107. package/dist/core/cookies/cookies.d.ts +7 -2
  108. package/dist/core/cookies/cookies.js +11 -4
  109. package/dist/core/cookies/response.d.ts +1 -1
  110. package/dist/core/cookies/response.js +1 -2
  111. package/dist/core/create-vite.js +18 -1
  112. package/dist/core/csp/config.js +17 -5
  113. package/dist/core/csp/runtime.js +6 -4
  114. package/dist/core/dev/dev.d.ts +1 -0
  115. package/dist/core/dev/dev.js +4 -13
  116. package/dist/core/dev/lockfile.d.ts +54 -0
  117. package/dist/core/dev/lockfile.js +93 -0
  118. package/dist/core/errors/build-handler.d.ts +17 -0
  119. package/dist/core/errors/build-handler.js +22 -0
  120. package/dist/core/errors/default-handler.d.ts +14 -0
  121. package/dist/core/errors/default-handler.js +144 -0
  122. package/dist/core/errors/dev-handler.d.ts +21 -0
  123. package/dist/core/errors/dev-handler.js +82 -0
  124. package/dist/core/errors/errors-data.d.ts +43 -38
  125. package/dist/core/errors/errors-data.js +79 -73
  126. package/dist/core/errors/handler.d.ts +9 -0
  127. package/dist/core/errors/handler.js +0 -0
  128. package/dist/core/errors/zod-error-map.js +30 -1
  129. package/dist/core/fetch/default-handler.d.ts +17 -0
  130. package/dist/core/fetch/default-handler.js +45 -0
  131. package/dist/core/fetch/fetch-state.d.ts +230 -0
  132. package/dist/core/fetch/fetch-state.js +896 -0
  133. package/dist/core/fetch/index.d.ts +61 -0
  134. package/dist/core/fetch/index.js +121 -0
  135. package/dist/core/fetch/types.d.ts +25 -0
  136. package/dist/core/fetch/types.js +0 -0
  137. package/dist/core/fetch/vite-plugin.d.ts +5 -0
  138. package/dist/core/fetch/vite-plugin.js +76 -0
  139. package/dist/core/hono/index.d.ts +21 -0
  140. package/dist/core/hono/index.js +101 -0
  141. package/dist/core/i18n/domain.d.ts +12 -0
  142. package/dist/core/i18n/domain.js +66 -0
  143. package/dist/core/i18n/handler.d.ts +18 -0
  144. package/dist/core/i18n/handler.js +122 -0
  145. package/dist/core/logger/core.d.ts +9 -1
  146. package/dist/core/logger/core.js +17 -1
  147. package/dist/core/messages/runtime.d.ts +0 -3
  148. package/dist/core/messages/runtime.js +1 -9
  149. package/dist/core/middleware/astro-middleware.d.ts +27 -0
  150. package/dist/core/middleware/astro-middleware.js +51 -0
  151. package/dist/core/module-loader/vite.js +1 -2
  152. package/dist/core/pages/handler.d.ts +20 -0
  153. package/dist/core/pages/handler.js +75 -0
  154. package/dist/core/preview/index.js +6 -5
  155. package/dist/core/preview/static-preview-server.js +5 -2
  156. package/dist/core/redirects/render.d.ts +2 -2
  157. package/dist/core/redirects/render.js +7 -8
  158. package/dist/core/render/params-and-props.js +2 -2
  159. package/dist/core/render/route-cache.d.ts +1 -0
  160. package/dist/core/render/route-cache.js +4 -4
  161. package/dist/core/render/slots.js +9 -2
  162. package/dist/core/rewrites/handler.d.ts +37 -0
  163. package/dist/core/rewrites/handler.js +67 -0
  164. package/dist/core/routing/3xx.js +8 -4
  165. package/dist/core/routing/create-manifest.js +11 -1
  166. package/dist/core/routing/handler.d.ts +17 -0
  167. package/dist/core/routing/handler.js +171 -0
  168. package/dist/core/routing/match.d.ts +0 -7
  169. package/dist/core/routing/match.js +0 -5
  170. package/dist/core/routing/parse-route.js +1 -1
  171. package/dist/core/routing/pattern.js +1 -1
  172. package/dist/core/routing/rewrite.js +2 -5
  173. package/dist/core/routing/router.d.ts +8 -0
  174. package/dist/core/routing/router.js +28 -0
  175. package/dist/core/routing/trailing-slash-handler.d.ts +18 -0
  176. package/dist/core/routing/trailing-slash-handler.js +67 -0
  177. package/dist/core/routing/validation.js +1 -1
  178. package/dist/core/server-islands/vite-plugin-server-islands.d.ts +6 -1
  179. package/dist/core/server-islands/vite-plugin-server-islands.js +13 -3
  180. package/dist/core/session/config.d.ts +1 -1
  181. package/dist/core/session/drivers.d.ts +1 -1
  182. package/dist/core/session/handler.d.ts +11 -0
  183. package/dist/core/session/handler.js +33 -0
  184. package/dist/core/session/runtime.js +7 -2
  185. package/dist/core/util/normalized-url.d.ts +10 -0
  186. package/dist/core/util/normalized-url.js +24 -0
  187. package/dist/core/util/pathname.d.ts +10 -1
  188. package/dist/core/util/pathname.js +13 -4
  189. package/dist/environments.js +1 -1
  190. package/dist/events/session.d.ts +8 -0
  191. package/dist/events/session.js +11 -0
  192. package/dist/i18n/middleware.d.ts +10 -0
  193. package/dist/i18n/middleware.js +4 -88
  194. package/dist/i18n/utils.js +2 -2
  195. package/dist/jsx/rehype.d.ts +1 -1
  196. package/dist/manifest/virtual-module.js +3 -1
  197. package/dist/markdown/index.d.ts +4 -0
  198. package/dist/markdown/index.js +14 -0
  199. package/dist/prefetch/index.js +12 -7
  200. package/dist/prerender/utils.js +5 -1
  201. package/dist/runtime/client/dev-toolbar/apps/audit/rules/a11y.js +9 -0
  202. package/dist/runtime/server/astro-island.js +57 -20
  203. package/dist/runtime/server/astro-island.prebuilt-dev.d.ts +1 -1
  204. package/dist/runtime/server/astro-island.prebuilt-dev.js +1 -1
  205. package/dist/runtime/server/astro-island.prebuilt.d.ts +1 -1
  206. package/dist/runtime/server/astro-island.prebuilt.js +1 -1
  207. package/dist/runtime/server/jsx.js +1 -1
  208. package/dist/runtime/server/render/common.js +10 -4
  209. package/dist/runtime/server/render/component.js +8 -6
  210. package/dist/runtime/server/render/head.js +1 -5
  211. package/dist/runtime/server/render/server-islands.js +2 -1
  212. package/dist/runtime/server/render/util.js +2 -2
  213. package/dist/runtime/server/scripts.js +6 -0
  214. package/dist/runtime/server/transition.d.ts +1 -6
  215. package/dist/runtime/server/transition.js +0 -8
  216. package/dist/transitions/events.d.ts +0 -14
  217. package/dist/transitions/events.js +0 -14
  218. package/dist/transitions/index.d.ts +0 -1
  219. package/dist/transitions/index.js +0 -2
  220. package/dist/transitions/vite-plugin-transitions.js +2 -4
  221. package/dist/types/public/config.d.ts +96 -14
  222. package/dist/types/public/content.d.ts +5 -5
  223. package/dist/types/public/index.d.ts +2 -1
  224. package/dist/types/public/integrations.d.ts +11 -3
  225. package/dist/types/public/internal.d.ts +1 -1
  226. package/dist/types/public/manifest.d.ts +1 -1
  227. package/dist/virtual-modules/i18n.d.ts +2 -2
  228. package/dist/virtual-modules/i18n.js +1 -1
  229. package/dist/vite-plugin-app/app.d.ts +13 -6
  230. package/dist/vite-plugin-app/app.js +51 -89
  231. package/dist/vite-plugin-app/createAstroServerApp.d.ts +3 -1
  232. package/dist/vite-plugin-app/createAstroServerApp.js +4 -3
  233. package/dist/vite-plugin-astro-server/plugin.js +11 -5
  234. package/dist/vite-plugin-astro-server/route-guard.d.ts +33 -0
  235. package/dist/vite-plugin-astro-server/route-guard.js +42 -23
  236. package/dist/vite-plugin-dev-status/index.d.ts +2 -0
  237. package/dist/vite-plugin-dev-status/index.js +15 -0
  238. package/dist/vite-plugin-head/index.js +36 -19
  239. package/dist/vite-plugin-hmr-reload/index.d.ts +1 -1
  240. package/dist/vite-plugin-hmr-reload/index.js +23 -1
  241. package/dist/vite-plugin-integrations-container/index.js +15 -6
  242. package/dist/vite-plugin-markdown/content-entry-type.js +7 -4
  243. package/dist/vite-plugin-markdown/images.js +9 -11
  244. package/dist/vite-plugin-markdown/index.js +12 -11
  245. package/dist/vite-plugin-utils/index.d.ts +1 -0
  246. package/dist/vite-plugin-utils/index.js +10 -1
  247. package/package.json +23 -16
  248. package/templates/content/types.d.ts +1 -0
  249. package/types/transitions.d.ts +0 -7
  250. package/dist/core/render-context.d.ts +0 -77
  251. package/dist/core/render-context.js +0 -826
@@ -136,7 +136,7 @@ class AstroLogger {
136
136
  }
137
137
  }
138
138
  /**
139
- * It calls the `flush` function of the provided destinatin, if it exists.
139
+ * It calls the `flush` function of the provided destination, if it exists.
140
140
  */
141
141
  flush() {
142
142
  if (this.options.destination.flush) {
@@ -169,6 +169,22 @@ class AstroIntegrationLogger {
169
169
  debug(message) {
170
170
  debug(this.label, message);
171
171
  }
172
+ /**
173
+ * It calls the `flush` function of the provided destination, if it exists.
174
+ */
175
+ flush() {
176
+ if (this.options.destination.flush) {
177
+ this.options.destination.flush();
178
+ }
179
+ }
180
+ /**
181
+ * It calls the `close` function of the provided destination, if it exists.
182
+ */
183
+ close() {
184
+ if (this.options.destination.close) {
185
+ this.options.destination.close();
186
+ }
187
+ }
172
188
  }
173
189
  export {
174
190
  AstroIntegrationLogger,
@@ -41,9 +41,6 @@ export declare function preferenceReset(name: string): string;
41
41
  export declare function telemetryDisabled(): string;
42
42
  export declare function telemetryReset(): string;
43
43
  export declare function fsStrictWarning(): string;
44
- export declare function vite8Warning({ viteVersion }: {
45
- viteVersion: string;
46
- }): string;
47
44
  export declare function prerelease({ currentVersion }: {
48
45
  currentVersion: string;
49
46
  }): string;
@@ -134,13 +134,6 @@ function fsStrictWarning() {
134
134
  ${subtitle}
135
135
  `;
136
136
  }
137
- function vite8Warning({ viteVersion }) {
138
- const title = yellow(`\u25B6 Vite ${bold(viteVersion)} detected in your project.`);
139
- const subtitle = ` Astro requires Vite 7. Add ${bold('"overrides": { "vite": "^7" }')} to your ${bold("package.json")} to avoid issues.`;
140
- return `${title}
141
- ${subtitle}
142
- `;
143
- }
144
137
  function prerelease({ currentVersion }) {
145
138
  const tag = currentVersion.split("-").slice(1).join("-").replace(/\..*$/, "") || "unknown";
146
139
  const badge = bgYellow(black(` ${tag} `));
@@ -276,7 +269,7 @@ function printHelp({
276
269
  message.push(
277
270
  linebreak(),
278
271
  ` ${bgGreen(black(` ${commandName} `))} ${green(
279
- `v${"7.0.0-alpha.0"}`
272
+ `v${"7.0.0-alpha.2"}`
280
273
  )} ${headline}`
281
274
  );
282
275
  }
@@ -334,6 +327,5 @@ export {
334
327
  telemetryEnabled,
335
328
  telemetryNotice,
336
329
  telemetryReset,
337
- vite8Warning,
338
330
  warnIfCspWithShiki
339
331
  };
@@ -0,0 +1,27 @@
1
+ import type { FetchState } from '../fetch/fetch-state.js';
2
+ import type { APIContext } from '../../types/public/context.js';
3
+ import { type Pipeline } from '../base-pipeline.js';
4
+ /**
5
+ * Callback invoked at the bottom of the middleware chain to dispatch the
6
+ * request to the matched route (endpoint / redirect / page / fallback).
7
+ *
8
+ * Callers of `AstroMiddleware.handle` pass their owned `PagesHandler`'s
9
+ * `handle` method (bound) so route dispatch logic stays out of the
10
+ * middleware layer.
11
+ */
12
+ export type RenderRouteCallback = (state: FetchState, ctx: APIContext) => Promise<Response>;
13
+ /**
14
+ * Handles the execution of Astro's middleware chain (internal + user) for a
15
+ * single render. Holds a reference to the `Pipeline` and composes the
16
+ * internal and user middleware at render time.
17
+ *
18
+ * Reads per-request data (componentInstance, slots, props, API contexts)
19
+ * off the supplied `FetchState`. The actual route dispatch (endpoint /
20
+ * redirect / page / fallback) is supplied by the caller as
21
+ * `renderRouteCallback` — typically bound to a `PagesHandler.handle`.
22
+ */
23
+ export declare class AstroMiddleware {
24
+ #private;
25
+ constructor(pipeline: Pipeline);
26
+ handle(state: FetchState, renderRouteCallback: RenderRouteCallback): Promise<Response>;
27
+ }
@@ -0,0 +1,51 @@
1
+ import { PipelineFeatures } from "../base-pipeline.js";
2
+ import { attachCookiesToResponse } from "../cookies/index.js";
3
+ import { applyRewriteToState } from "../rewrites/handler.js";
4
+ import { callMiddleware } from "./callMiddleware.js";
5
+ import { sequence } from "./index.js";
6
+ class AstroMiddleware {
7
+ #pipeline;
8
+ constructor(pipeline) {
9
+ this.#pipeline = pipeline;
10
+ }
11
+ async handle(state, renderRouteCallback) {
12
+ state.pipeline.usedFeatures |= PipelineFeatures.middleware;
13
+ const pipeline = this.#pipeline;
14
+ await state.getProps();
15
+ const apiContext = state.getAPIContext();
16
+ state.counter++;
17
+ if (state.counter === 4) {
18
+ return new Response("Loop Detected", {
19
+ // https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/508
20
+ status: 508,
21
+ statusText: "Astro detected a loop where you tried to call the rewriting logic more than four times."
22
+ });
23
+ }
24
+ const next = async (ctx, payload) => {
25
+ if (payload) {
26
+ pipeline.logger.debug("router", "Called rewriting to:", payload);
27
+ const result = await pipeline.tryRewrite(payload, state.request);
28
+ applyRewriteToState(state, payload, result);
29
+ }
30
+ return renderRouteCallback(state, ctx);
31
+ };
32
+ let response;
33
+ if (state.skipMiddleware) {
34
+ response = await next(apiContext);
35
+ } else {
36
+ const pipelineMiddleware = await pipeline.getMiddleware();
37
+ const composed = sequence(...pipeline.internalMiddleware, pipelineMiddleware);
38
+ response = await callMiddleware(composed, apiContext, next);
39
+ }
40
+ response = this.#finalize(state, response);
41
+ state.response = response;
42
+ return response;
43
+ }
44
+ #finalize(state, response) {
45
+ attachCookiesToResponse(response, state.cookies);
46
+ return response;
47
+ }
48
+ }
49
+ export {
50
+ AstroMiddleware
51
+ };
@@ -3,7 +3,6 @@ import path from "node:path";
3
3
  import { pathToFileURL } from "node:url";
4
4
  import { collectErrorMetadata } from "../errors/dev/utils.js";
5
5
  import { getViteErrorPayload } from "../errors/dev/vite.js";
6
- import { ASTRO_VITE_ENVIRONMENT_NAMES } from "../constants.js";
7
6
  function createViteLoader(viteServer, ssrEnvironment) {
8
7
  const events = new EventEmitter();
9
8
  let isTsconfigUpdated = false;
@@ -90,7 +89,7 @@ function createViteLoader(viteServer, ssrEnvironment) {
90
89
  return viteServer.environments.client.hot.send(msg);
91
90
  },
92
91
  getSSREnvironment() {
93
- return viteServer.environments[ASTRO_VITE_ENVIRONMENT_NAMES.ssr];
92
+ return ssrEnvironment;
94
93
  },
95
94
  isHttps() {
96
95
  return !!ssrEnvironment.config.server.https;
@@ -0,0 +1,20 @@
1
+ import type { APIContext } from '../../types/public/context.js';
2
+ import type { FetchState } from '../fetch/fetch-state.js';
3
+ import type { Pipeline } from '../base-pipeline.js';
4
+ /**
5
+ * Handles dispatch of a matched route (endpoint / redirect / page / fallback)
6
+ * at the bottom of the middleware chain. This is a pure dispatch layer — it
7
+ * renders whatever route the `FetchState` currently points to without any
8
+ * rewrite logic. Rewrites are handled upstream: `Rewrites.execute()` for
9
+ * `Astro.rewrite()` and `AstroMiddleware` for `next(payload)`.
10
+ *
11
+ * `PagesHandler` is the `next` callback that `AstroMiddleware` invokes at
12
+ * the end of the middleware chain. `AstroHandler` owns a single instance
13
+ * and passes its `handle` method as the callback. Error handlers and the
14
+ * container also use `PagesHandler` directly for the same dispatch behavior.
15
+ */
16
+ export declare class PagesHandler {
17
+ #private;
18
+ constructor(pipeline: Pipeline);
19
+ handle(state: FetchState, ctx: APIContext): Promise<Response>;
20
+ }
@@ -0,0 +1,75 @@
1
+ import { renderEndpoint } from "../../runtime/server/endpoint.js";
2
+ import { renderPage } from "../../runtime/server/index.js";
3
+ import {
4
+ ASTRO_ERROR_HEADER,
5
+ REROUTE_DIRECTIVE_HEADER,
6
+ REWRITE_DIRECTIVE_HEADER_KEY,
7
+ REWRITE_DIRECTIVE_HEADER_VALUE,
8
+ ROUTE_TYPE_HEADER
9
+ } from "../constants.js";
10
+ import { getCookiesFromResponse } from "../cookies/response.js";
11
+ const EMPTY_SLOTS = Object.freeze({});
12
+ class PagesHandler {
13
+ #pipeline;
14
+ constructor(pipeline) {
15
+ this.#pipeline = pipeline;
16
+ }
17
+ async handle(state, ctx) {
18
+ const pipeline = this.#pipeline;
19
+ const { logger, streaming } = pipeline;
20
+ let response;
21
+ const componentInstance = await state.loadComponentInstance();
22
+ switch (state.routeData.type) {
23
+ case "endpoint": {
24
+ response = await renderEndpoint(
25
+ componentInstance,
26
+ ctx,
27
+ state.routeData.prerender,
28
+ logger
29
+ );
30
+ break;
31
+ }
32
+ case "page": {
33
+ const props = await state.getProps();
34
+ const actionApiContext = state.getActionAPIContext();
35
+ const result = await state.createResult(componentInstance, actionApiContext);
36
+ try {
37
+ response = await renderPage(
38
+ result,
39
+ componentInstance?.default,
40
+ props,
41
+ state.slots ?? EMPTY_SLOTS,
42
+ streaming,
43
+ state.routeData
44
+ );
45
+ } catch (e) {
46
+ result.cancelled = true;
47
+ throw e;
48
+ }
49
+ response.headers.set(ROUTE_TYPE_HEADER, "page");
50
+ if (state.routeData.route === "/404" || state.routeData.route === "/500") {
51
+ response.headers.set(REROUTE_DIRECTIVE_HEADER, "no");
52
+ }
53
+ if (state.isRewriting) {
54
+ response.headers.set(REWRITE_DIRECTIVE_HEADER_KEY, REWRITE_DIRECTIVE_HEADER_VALUE);
55
+ }
56
+ break;
57
+ }
58
+ case "redirect": {
59
+ return new Response(null, { status: 404, headers: { [ASTRO_ERROR_HEADER]: "true" } });
60
+ }
61
+ case "fallback": {
62
+ return new Response(null, { status: 500, headers: { [ROUTE_TYPE_HEADER]: "fallback" } });
63
+ }
64
+ }
65
+ const responseCookies = getCookiesFromResponse(response);
66
+ if (responseCookies) {
67
+ state.cookies.merge(responseCookies);
68
+ }
69
+ state.response = response;
70
+ return response;
71
+ }
72
+ }
73
+ export {
74
+ PagesHandler
75
+ };
@@ -9,7 +9,7 @@ import { resolveConfig } from "../config/config.js";
9
9
  import { loadOrCreateNodeLogger } from "../logger/load.js";
10
10
  import { createSettings } from "../config/settings.js";
11
11
  import { createRoutesList } from "../routing/create-manifest.js";
12
- import { getPrerenderDefault } from "../../prerender/utils.js";
12
+ import { getClientOutputDirectory, getPrerenderDefault } from "../../prerender/utils.js";
13
13
  import { ensureProcessNodeEnv } from "../util.js";
14
14
  import createStaticPreviewServer from "./static-preview-server.js";
15
15
  import { getResolvedHostForHttpServer } from "./util.js";
@@ -28,12 +28,13 @@ async function preview(inlineConfig) {
28
28
  command: "preview",
29
29
  logger
30
30
  });
31
- await createRoutesList({ settings, cwd: inlineConfig.root }, logger);
32
31
  settings.buildOutput = getPrerenderDefault(settings.config) ? "static" : "server";
32
+ await createRoutesList({ settings, cwd: inlineConfig.root }, logger);
33
33
  await runHookConfigDone({ settings, logger, command: "preview" });
34
- if (settings.buildOutput === "static") {
35
- if (!fs.existsSync(settings.config.outDir)) {
36
- const outDirPath = fileURLToPath(settings.config.outDir);
34
+ if (settings.buildOutput === "static" && !settings.adapter?.previewEntrypoint) {
35
+ const clientOutDir = getClientOutputDirectory(settings);
36
+ if (!fs.existsSync(clientOutDir)) {
37
+ const outDirPath = fileURLToPath(clientOutDir);
37
38
  throw new Error(
38
39
  `[preview] The output directory ${outDirPath} does not exist. Did you run \`astro build\`?`
39
40
  );
@@ -1,6 +1,7 @@
1
1
  import { performance } from "node:perf_hooks";
2
2
  import { fileURLToPath } from "node:url";
3
3
  import { mergeConfig, preview } from "vite";
4
+ import { getClientOutputDirectory } from "../../prerender/utils.js";
4
5
  import * as msg from "../messages/runtime.js";
5
6
  import { getResolvedHostForHttpServer } from "./util.js";
6
7
  import { vitePluginAstroPreview } from "./vite-plugin-astro-preview.js";
@@ -15,7 +16,7 @@ async function createStaticPreviewServer(settings, logger) {
15
16
  base: settings.config.base,
16
17
  appType: "mpa",
17
18
  build: {
18
- outDir: fileURLToPath(settings.config.outDir)
19
+ outDir: fileURLToPath(getClientOutputDirectory(settings))
19
20
  },
20
21
  root: fileURLToPath(settings.config.root),
21
22
  preview: {
@@ -67,9 +68,11 @@ async function createStaticPreviewServer(settings, logger) {
67
68
  previewServer.httpServer.addListener("error", reject);
68
69
  });
69
70
  }
71
+ const address = previewServer.httpServer.address();
72
+ const actualPort = address && typeof address === "object" ? address.port : settings.config.server.port;
70
73
  return {
71
74
  host: getResolvedHostForHttpServer(settings.config.server.host),
72
- port: settings.config.server.port,
75
+ port: actualPort,
73
76
  closed,
74
77
  server: previewServer.httpServer,
75
78
  stop: previewServer.close.bind(previewServer)
@@ -1,7 +1,7 @@
1
1
  import type { Params } from '../../types/public/common.js';
2
2
  import type { RedirectConfig } from '../../types/public/index.js';
3
3
  import type { RouteData } from '../../types/public/internal.js';
4
- import type { RenderContext } from '../render-context.js';
4
+ import type { FetchState } from '../fetch/fetch-state.js';
5
5
  export declare function redirectIsExternal(redirect: RedirectConfig): boolean;
6
6
  /**
7
7
  * Computes the HTTP status code for a redirect response.
@@ -18,4 +18,4 @@ export declare function computeRedirectStatus(method: string, redirect: Redirect
18
18
  * are substituted manually into the string redirect target.
19
19
  */
20
20
  export declare function resolveRedirectTarget(params: Params, redirect: RedirectConfig | undefined, redirectRoute: RouteData | undefined, trailingSlash: 'always' | 'never' | 'ignore'): string;
21
- export declare function renderRedirect(renderContext: RenderContext): Promise<Response>;
21
+ export declare function renderRedirect(state: FetchState): Promise<Response>;
@@ -1,3 +1,4 @@
1
+ import { PipelineFeatures } from "../base-pipeline.js";
1
2
  import { getRouteGenerator } from "../routing/generator.js";
2
3
  function isExternalURL(url) {
3
4
  return url.startsWith("http://") || url.startsWith("https://") || url.startsWith("//");
@@ -32,20 +33,18 @@ function resolveRedirectTarget(params, redirect, redirectRoute, trailingSlash) {
32
33
  }
33
34
  return redirect.destination;
34
35
  }
35
- async function renderRedirect(renderContext) {
36
- const {
37
- request: { method },
38
- routeData
39
- } = renderContext;
36
+ async function renderRedirect(state) {
37
+ state.pipeline.usedFeatures |= PipelineFeatures.redirects;
38
+ const routeData = state.routeData;
40
39
  const { redirect, redirectRoute } = routeData;
41
- const status = computeRedirectStatus(method, redirect, redirectRoute);
40
+ const status = computeRedirectStatus(state.request.method, redirect, redirectRoute);
42
41
  const headers = {
43
42
  location: encodeURI(
44
43
  resolveRedirectTarget(
45
- renderContext.params,
44
+ state.params,
46
45
  redirect,
47
46
  redirectRoute,
48
- renderContext.pipeline.manifest.trailingSlash
47
+ state.pipeline.manifest.trailingSlash
49
48
  )
50
49
  )
51
50
  };
@@ -29,7 +29,7 @@ async function getProps(opts) {
29
29
  });
30
30
  const params = getParams(route, pathname);
31
31
  const matchedStaticPath = findPathItemByKey(staticPaths, params, route, logger, trailingSlash);
32
- if (!matchedStaticPath && (serverLike ? route.prerender : true)) {
32
+ if (!matchedStaticPath && route.origin !== "internal" && (serverLike ? route.prerender : true)) {
33
33
  throw new AstroError({
34
34
  ...AstroErrorData.NoMatchingStaticPathFound,
35
35
  message: AstroErrorData.NoMatchingStaticPathFound.message(pathname),
@@ -44,7 +44,7 @@ async function getProps(opts) {
44
44
  }
45
45
  function getParams(route, pathname) {
46
46
  if (!route.params.length) return {};
47
- const path = pathname.endsWith(".html") && !routeHasHtmlExtension(route) ? pathname.slice(0, -5) : pathname;
47
+ const path = pathname.endsWith(".html") && route.type === "page" && !routeHasHtmlExtension(route) ? pathname.slice(0, -5) : pathname;
48
48
  const allPatterns = [route, ...route.fallbackRoutes].map((r) => r.pattern);
49
49
  const paramsMatch = allPatterns.map((pattern) => pattern.exec(path)).find((x) => x);
50
50
  if (!paramsMatch) return {};
@@ -13,6 +13,7 @@ interface CallGetStaticPathsOptions {
13
13
  }
14
14
  export declare function callGetStaticPaths({ mod, route, routeCache, ssr, base, trailingSlash, }: CallGetStaticPathsOptions): Promise<GetStaticPathsResultKeyed>;
15
15
  interface RouteCacheEntry {
16
+ mod: ComponentInstance;
16
17
  staticPaths: GetStaticPathsResultKeyed;
17
18
  }
18
19
  /**
@@ -13,13 +13,13 @@ async function callGetStaticPaths({
13
13
  if (!mod) {
14
14
  throw new Error("This is an error caused by Astro and not your code. Please file an issue.");
15
15
  }
16
- if (cached?.staticPaths) {
16
+ if (cached?.staticPaths && cached.mod === mod) {
17
17
  return cached.staticPaths;
18
18
  }
19
19
  validateDynamicRouteModule(mod, { ssr, route });
20
- if (ssr && !route.prerender) {
20
+ if (ssr && !route.prerender || route.origin === "internal") {
21
21
  const entry = Object.assign([], { keyed: /* @__PURE__ */ new Map() });
22
- routeCache.set(route, { ...cached, staticPaths: entry });
22
+ routeCache.set(route, { ...cached, mod, staticPaths: entry });
23
23
  return entry;
24
24
  }
25
25
  let staticPaths = [];
@@ -39,7 +39,7 @@ async function callGetStaticPaths({
39
39
  const paramsKey = stringifyParams(sp.params, route, trailingSlash);
40
40
  keyedStaticPaths.keyed.set(paramsKey, sp);
41
41
  }
42
- routeCache.set(route, { ...cached, staticPaths: keyedStaticPaths });
42
+ routeCache.set(route, { ...cached, mod, staticPaths: keyedStaticPaths });
43
43
  return keyedStaticPaths;
44
44
  }
45
45
  class RouteCache {
@@ -1,13 +1,20 @@
1
1
  import { renderSlotToString } from "../../runtime/server/index.js";
2
2
  import { renderJSX } from "../../runtime/server/jsx.js";
3
+ import { isRenderTemplateResult } from "../../runtime/server/render/astro/index.js";
3
4
  import { chunkToString } from "../../runtime/server/render/index.js";
4
5
  import { isRenderInstruction } from "../../runtime/server/render/instruction.js";
5
6
  import { AstroError, AstroErrorData } from "../errors/index.js";
6
7
  function getFunctionExpression(slot) {
7
8
  if (!slot) return;
8
- const expressions = slot?.expressions?.filter((e) => isRenderInstruction(e) === false);
9
+ const expressions = slot?.expressions?.filter(
10
+ (e) => isRenderInstruction(e) === false || isRenderTemplateResult(e)
11
+ );
9
12
  if (expressions?.length !== 1) return;
10
- return expressions[0];
13
+ const expression = expressions[0];
14
+ if (isRenderTemplateResult(expression)) {
15
+ return getFunctionExpression(expression);
16
+ }
17
+ return expression;
11
18
  }
12
19
  class Slots {
13
20
  #result;
@@ -0,0 +1,37 @@
1
+ import type { ComponentInstance } from '../../types/astro.js';
2
+ import type { FetchState } from '../fetch/fetch-state.js';
3
+ import type { RewritePayload } from '../../types/public/common.js';
4
+ import type { RouteData } from '../../types/public/internal.js';
5
+ interface TryRewriteResult {
6
+ routeData: RouteData;
7
+ componentInstance: ComponentInstance;
8
+ newUrl: URL;
9
+ pathname: string;
10
+ }
11
+ /**
12
+ * Validates and applies a rewrite target to the given `FetchState`.
13
+ *
14
+ * - Validates that SSR→prerender rewrites are not attempted (except
15
+ * for i18n fallback routes).
16
+ * - Mutates `state` to reflect the new route: request, URL, cookies,
17
+ * params, pathname, component instance, etc.
18
+ * - Invalidates cached API contexts so they're re-derived from the
19
+ * new route.
20
+ *
21
+ * Called by both `Rewrites.execute()` (user-triggered `Astro.rewrite`)
22
+ * and `AstroMiddleware` (middleware `next(payload)`).
23
+ */
24
+ export declare function applyRewriteToState(state: FetchState, payload: RewritePayload, { routeData, componentInstance, newUrl, pathname }: TryRewriteResult, { mergeCookies }?: {
25
+ mergeCookies?: boolean;
26
+ }): void;
27
+ /**
28
+ * Executes a user-triggered rewrite (`Astro.rewrite(...)` /
29
+ * `ctx.rewrite(...)`) against a `FetchState`. Resolves the rewrite
30
+ * target via `pipeline.tryRewrite`, validates it, mutates the
31
+ * `FetchState` to reflect the new route, and re-runs the middleware
32
+ * and page dispatch to produce the new response.
33
+ */
34
+ export declare class Rewrites {
35
+ execute(state: FetchState, payload: RewritePayload): Promise<Response>;
36
+ }
37
+ export {};
@@ -0,0 +1,67 @@
1
+ import { AstroCookies } from "../cookies/index.js";
2
+ import { ForbiddenRewrite } from "../errors/errors-data.js";
3
+ import { AstroError } from "../errors/errors.js";
4
+ import { AstroMiddleware } from "../middleware/astro-middleware.js";
5
+ import { PagesHandler } from "../pages/handler.js";
6
+ import { getParams } from "../render/index.js";
7
+ import { copyRequest, setOriginPathname } from "../routing/rewrite.js";
8
+ import { createNormalizedUrl } from "../util/normalized-url.js";
9
+ function applyRewriteToState(state, payload, { routeData, componentInstance, newUrl, pathname }, { mergeCookies = false } = {}) {
10
+ const pipeline = state.pipeline;
11
+ const oldPathname = state.pathname;
12
+ const isI18nFallback = routeData.fallbackRoutes && routeData.fallbackRoutes.length > 0;
13
+ if (pipeline.manifest.serverLike && !state.routeData.prerender && routeData.prerender && !isI18nFallback) {
14
+ throw new AstroError({
15
+ ...ForbiddenRewrite,
16
+ message: ForbiddenRewrite.message(state.pathname, pathname, routeData.component),
17
+ hint: ForbiddenRewrite.hint(routeData.component)
18
+ });
19
+ }
20
+ state.routeData = routeData;
21
+ state.componentInstance = componentInstance;
22
+ if (payload instanceof Request) {
23
+ state.request = payload;
24
+ } else {
25
+ state.request = copyRequest(
26
+ newUrl,
27
+ state.request,
28
+ routeData.prerender,
29
+ pipeline.logger,
30
+ state.routeData.route
31
+ );
32
+ }
33
+ state.url = createNormalizedUrl(state.request.url);
34
+ if (mergeCookies) {
35
+ const newCookies = new AstroCookies(state.request);
36
+ if (state.cookies) {
37
+ newCookies.merge(state.cookies);
38
+ }
39
+ state.cookies = newCookies;
40
+ }
41
+ state.params = getParams(routeData, pathname);
42
+ state.pathname = pathname;
43
+ state.isRewriting = true;
44
+ state.status = 200;
45
+ setOriginPathname(
46
+ state.request,
47
+ oldPathname,
48
+ pipeline.manifest.trailingSlash,
49
+ pipeline.manifest.buildFormat
50
+ );
51
+ state.invalidateContexts();
52
+ }
53
+ class Rewrites {
54
+ async execute(state, payload) {
55
+ const pipeline = state.pipeline;
56
+ pipeline.logger.debug("router", "Calling rewrite: ", payload);
57
+ const result = await pipeline.tryRewrite(payload, state.request);
58
+ applyRewriteToState(state, payload, result, { mergeCookies: true });
59
+ const middleware = new AstroMiddleware(pipeline);
60
+ const pagesHandler = new PagesHandler(pipeline);
61
+ return middleware.handle(state, pagesHandler.handle.bind(pagesHandler));
62
+ }
63
+ }
64
+ export {
65
+ Rewrites,
66
+ applyRewriteToState
67
+ };
@@ -1,3 +1,4 @@
1
+ import { escape } from "html-escaper";
1
2
  function redirectTemplate({
2
3
  status,
3
4
  absoluteLocation,
@@ -5,13 +6,16 @@ function redirectTemplate({
5
6
  from
6
7
  }) {
7
8
  const delay = status === 302 ? 2 : 0;
9
+ const rel = escape(String(relativeLocation));
10
+ const abs = escape(String(absoluteLocation));
11
+ const fromHtml = from ? `from <code>${escape(from)}</code> ` : "";
8
12
  return `<!doctype html>
9
- <title>Redirecting to: ${relativeLocation}</title>
10
- <meta http-equiv="refresh" content="${delay};url=${relativeLocation}">
13
+ <title>Redirecting to: ${rel}</title>
14
+ <meta http-equiv="refresh" content="${delay};url=${rel}">
11
15
  <meta name="robots" content="noindex">
12
- <link rel="canonical" href="${absoluteLocation}">
16
+ <link rel="canonical" href="${abs}">
13
17
  <body>
14
- <a href="${relativeLocation}">Redirecting ${from ? `from <code>${from}</code> ` : ""}to <code>${relativeLocation}</code></a>
18
+ <a href="${rel}">Redirecting ${fromHtml}to <code>${rel}</code></a>
15
19
  </body>`;
16
20
  }
17
21
  export {
@@ -388,6 +388,16 @@ function createRedirectRoutes({ settings }, routeMap) {
388
388
  message: InvalidRedirectDestination.message(from, destination)
389
389
  });
390
390
  }
391
+ if (params.length > 0 && redirectRoute && !URL.canParse(destination) && getPrerenderDefault(config)) {
392
+ const destParams = redirectRoute.params ?? [];
393
+ const missingParams = params.filter((p) => !destParams.includes(p));
394
+ if (missingParams.length > 0) {
395
+ throw new AstroError({
396
+ ...InvalidRedirectDestination,
397
+ message: InvalidRedirectDestination.message(from, destination, missingParams)
398
+ });
399
+ }
400
+ }
391
401
  routes.push({
392
402
  type: "redirect",
393
403
  // For backwards compatibility, a redirect is never considered an index route.
@@ -667,7 +677,7 @@ function joinSegments(segments) {
667
677
  const arr = segments.map((segment) => {
668
678
  return segment.map((rp) => rp.dynamic ? `[${rp.content}]` : rp.content).join("");
669
679
  });
670
- return `/${arr.join("/")}`.toLowerCase();
680
+ return `/${arr.join("/")}`;
671
681
  }
672
682
  function replaceOrKeep(original, from, to) {
673
683
  if (original.startsWith(`/${to}/`) || original === `/${to}`) return original;
@@ -0,0 +1,17 @@
1
+ import type { FetchState } from '../fetch/fetch-state.js';
2
+ import type { BaseApp } from '../app/base.js';
3
+ import { type Pipeline } from '../base-pipeline.js';
4
+ export declare class AstroHandler {
5
+ #private;
6
+ constructor(app: BaseApp<Pipeline>);
7
+ handle(state: FetchState): Promise<Response>;
8
+ /**
9
+ * Renders a response for the given `FetchState`. Assumes
10
+ * trailing-slash redirects and routeData resolution have already run.
11
+ *
12
+ * User-triggered rewrites (`Astro.rewrite` / `ctx.rewrite`) go through
13
+ * `Rewrites.execute` on the current `FetchState` — they mutate the
14
+ * existing state in place and re-run middleware + page dispatch.
15
+ */
16
+ render(state: FetchState): Promise<Response>;
17
+ }