astro 6.2.1 → 6.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (137) hide show
  1. package/dist/actions/handler.d.ts +32 -0
  2. package/dist/actions/handler.js +45 -0
  3. package/dist/actions/runtime/server.js +1 -1
  4. package/dist/assets/build/generate.js +1 -1
  5. package/dist/assets/build/remote.d.ts +3 -2
  6. package/dist/assets/build/remote.js +16 -9
  7. package/dist/assets/endpoint/generic.js +4 -7
  8. package/dist/assets/endpoint/shared.js +7 -2
  9. package/dist/assets/index.d.ts +1 -0
  10. package/dist/assets/index.js +2 -0
  11. package/dist/assets/internal.js +16 -1
  12. package/dist/assets/services/sharp.js +16 -1
  13. package/dist/assets/utils/index.d.ts +1 -0
  14. package/dist/assets/utils/index.js +2 -0
  15. package/dist/assets/utils/redirectValidation.d.ts +48 -0
  16. package/dist/assets/utils/redirectValidation.js +48 -0
  17. package/dist/assets/utils/remoteProbe.js +25 -2
  18. package/dist/cli/add/index.js +7 -4
  19. package/dist/cli/infra/build-time-astro-version-provider.js +1 -1
  20. package/dist/container/index.js +18 -14
  21. package/dist/content/content-layer.js +3 -4
  22. package/dist/content/loaders/types.d.ts +1 -1
  23. package/dist/content/server-listeners.js +0 -4
  24. package/dist/content/vite-plugin-content-virtual-mod.js +9 -1
  25. package/dist/core/app/base.d.ts +33 -15
  26. package/dist/core/app/base.js +120 -324
  27. package/dist/core/app/dev/app.d.ts +3 -2
  28. package/dist/core/app/dev/app.js +4 -60
  29. package/dist/core/app/entrypoints/virtual/dev.js +2 -0
  30. package/dist/core/app/entrypoints/virtual/prod.js +4 -1
  31. package/dist/core/app/prepare-response.d.ts +11 -0
  32. package/dist/core/app/prepare-response.js +18 -0
  33. package/dist/core/app/render-options.d.ts +11 -0
  34. package/dist/core/app/render-options.js +11 -0
  35. package/dist/core/base-pipeline.d.ts +38 -1
  36. package/dist/core/base-pipeline.js +50 -7
  37. package/dist/core/build/app.d.ts +3 -4
  38. package/dist/core/build/app.js +3 -17
  39. package/dist/core/build/plugins/plugin-css.js +7 -1
  40. package/dist/core/build/plugins/plugin-manifest.js +11 -1
  41. package/dist/core/build/static-build.js +16 -2
  42. package/dist/core/cache/handler.d.ts +29 -0
  43. package/dist/core/cache/handler.js +81 -0
  44. package/dist/core/compile/style.js +18 -1
  45. package/dist/core/config/index.d.ts +1 -1
  46. package/dist/core/config/index.js +4 -1
  47. package/dist/core/config/schemas/base.d.ts +4 -0
  48. package/dist/core/config/schemas/base.js +4 -0
  49. package/dist/core/config/schemas/relative.d.ts +6 -0
  50. package/dist/core/config/settings.js +2 -4
  51. package/dist/core/config/tsconfig.d.ts +24 -9
  52. package/dist/core/config/tsconfig.js +54 -45
  53. package/dist/core/constants.d.ts +27 -1
  54. package/dist/core/constants.js +14 -1
  55. package/dist/core/cookies/cookies.d.ts +7 -2
  56. package/dist/core/cookies/cookies.js +11 -4
  57. package/dist/core/cookies/response.d.ts +1 -1
  58. package/dist/core/cookies/response.js +1 -2
  59. package/dist/core/create-vite.js +15 -0
  60. package/dist/core/csp/runtime.js +6 -4
  61. package/dist/core/dev/dev.js +1 -1
  62. package/dist/core/errors/build-handler.d.ts +17 -0
  63. package/dist/core/errors/build-handler.js +22 -0
  64. package/dist/core/errors/default-handler.d.ts +14 -0
  65. package/dist/core/errors/default-handler.js +144 -0
  66. package/dist/core/errors/dev-handler.d.ts +21 -0
  67. package/dist/core/errors/dev-handler.js +82 -0
  68. package/dist/core/errors/handler.d.ts +9 -0
  69. package/dist/core/errors/handler.js +0 -0
  70. package/dist/core/fetch/default-handler.d.ts +17 -0
  71. package/dist/core/fetch/default-handler.js +45 -0
  72. package/dist/core/fetch/fetch-state.d.ts +244 -0
  73. package/dist/core/fetch/fetch-state.js +779 -0
  74. package/dist/core/fetch/index.d.ts +61 -0
  75. package/dist/core/fetch/index.js +121 -0
  76. package/dist/core/fetch/types.d.ts +6 -0
  77. package/dist/core/fetch/types.js +0 -0
  78. package/dist/core/fetch/vite-plugin.d.ts +5 -0
  79. package/dist/core/fetch/vite-plugin.js +69 -0
  80. package/dist/core/hono/index.d.ts +21 -0
  81. package/dist/core/hono/index.js +98 -0
  82. package/dist/core/i18n/handler.d.ts +18 -0
  83. package/dist/core/i18n/handler.js +119 -0
  84. package/dist/core/logger/core.d.ts +8 -0
  85. package/dist/core/logger/core.js +16 -0
  86. package/dist/core/messages/runtime.js +1 -1
  87. package/dist/core/middleware/astro-middleware.d.ts +27 -0
  88. package/dist/core/middleware/astro-middleware.js +53 -0
  89. package/dist/core/pages/handler.d.ts +20 -0
  90. package/dist/core/pages/handler.js +74 -0
  91. package/dist/core/redirects/render.d.ts +2 -2
  92. package/dist/core/redirects/render.js +7 -8
  93. package/dist/core/render/params-and-props.js +1 -1
  94. package/dist/core/render/slots.js +9 -2
  95. package/dist/core/rewrites/handler.d.ts +37 -0
  96. package/dist/core/rewrites/handler.js +67 -0
  97. package/dist/core/routing/3xx.js +8 -4
  98. package/dist/core/routing/handler.d.ts +17 -0
  99. package/dist/core/routing/handler.js +172 -0
  100. package/dist/core/routing/match.d.ts +0 -7
  101. package/dist/core/routing/match.js +0 -5
  102. package/dist/core/routing/pattern.js +1 -1
  103. package/dist/core/routing/rewrite.js +1 -4
  104. package/dist/core/routing/trailing-slash-handler.d.ts +18 -0
  105. package/dist/core/routing/trailing-slash-handler.js +67 -0
  106. package/dist/core/session/drivers.d.ts +1 -1
  107. package/dist/core/session/handler.d.ts +11 -0
  108. package/dist/core/session/handler.js +33 -0
  109. package/dist/core/session/runtime.js +7 -2
  110. package/dist/core/util/normalized-url.d.ts +10 -0
  111. package/dist/core/util/normalized-url.js +21 -0
  112. package/dist/i18n/middleware.d.ts +10 -0
  113. package/dist/i18n/middleware.js +4 -88
  114. package/dist/i18n/utils.js +2 -2
  115. package/dist/prefetch/index.js +12 -7
  116. package/dist/runtime/server/astro-island.js +57 -20
  117. package/dist/runtime/server/astro-island.prebuilt-dev.d.ts +1 -1
  118. package/dist/runtime/server/astro-island.prebuilt-dev.js +1 -1
  119. package/dist/runtime/server/astro-island.prebuilt.d.ts +1 -1
  120. package/dist/runtime/server/astro-island.prebuilt.js +1 -1
  121. package/dist/runtime/server/render/common.js +10 -4
  122. package/dist/runtime/server/render/server-islands.js +2 -1
  123. package/dist/runtime/server/scripts.js +6 -0
  124. package/dist/types/public/config.d.ts +46 -12
  125. package/dist/types/public/content.d.ts +4 -4
  126. package/dist/types/public/internal.d.ts +1 -1
  127. package/dist/vite-plugin-app/app.d.ts +4 -5
  128. package/dist/vite-plugin-app/app.js +20 -68
  129. package/dist/vite-plugin-astro/compile.js +2 -2
  130. package/dist/vite-plugin-astro/utils.d.ts +1 -0
  131. package/dist/vite-plugin-astro/utils.js +9 -1
  132. package/dist/vite-plugin-head/index.js +36 -19
  133. package/dist/vite-plugin-utils/index.d.ts +1 -0
  134. package/dist/vite-plugin-utils/index.js +3 -0
  135. package/package.json +13 -6
  136. package/dist/core/render-context.d.ts +0 -77
  137. package/dist/core/render-context.js +0 -826
@@ -1328,23 +1328,25 @@ export interface AstroUserConfig<TLocales extends Locales = never, TDriver exten
1328
1328
  * @description
1329
1329
  *
1330
1330
  * Configures session storage for your Astro project. This is used to store session data in a persistent way, so that it can be accessed across different requests.
1331
- * Some adapters may provide a default session driver, but you can override it with your own configuration.
1332
1331
  *
1333
- * See [the sessions guide](https://docs.astro.build/en/guides/sessions/) for more information.
1332
+ * Some adapters may provide a default session driver, but you can override it with your own configuration:
1334
1333
  *
1335
1334
  * ```js title="astro.config.mjs"
1336
- * {
1337
- * session: {
1338
- * // The name of the Unstorage driver
1339
- * driver: 'redis',
1340
- * // The required options depend on the driver
1341
- * options: {
1342
- * url: process.env.REDIS_URL,
1343
- * },
1344
- * ttl: 3600, // 1 hour
1345
- * }
1335
+ * import { defineConfig, sessionDrivers } from 'astro/config';
1336
+ *
1337
+ * export default defineConfig({
1338
+ * session: {
1339
+ * driver: sessionDrivers.redis({
1340
+ * // The options are driver-dependent and some may be required.
1341
+ * url: process.env.REDIS_URL
1342
+ * }),
1346
1343
  * }
1344
+ * });
1347
1345
  * ```
1346
+ *
1347
+ * Session drivers are configured at build time. This means environment variables used in the driver configuration are inlined. You must create your own driver entrypoint to [override the configuration at runtime](https://docs.astro.build/en/guides/sessions/#overriding-the-configuration-at-runtime).
1348
+ *
1349
+ * See [the sessions guide](https://docs.astro.build/en/guides/sessions/) for more information.
1348
1350
  */
1349
1351
  session?: SessionConfig<TDriver>;
1350
1352
  /**
@@ -1626,6 +1628,19 @@ export interface AstroUserConfig<TLocales extends Locales = never, TDriver exten
1626
1628
  * ```
1627
1629
  */
1628
1630
  service?: ImageServiceConfig;
1631
+ /**
1632
+ * @docs
1633
+ * @name image.dangerouslyProcessSVG
1634
+ * @type {boolean}
1635
+ * @default `false`
1636
+ * @version 6.3.0
1637
+ * @description
1638
+ *
1639
+ * Allows SVG source images to be processed by the image optimization pipeline.
1640
+ *
1641
+ * This is disabled by default as specifically formed SVGs can be prohibitively expensive to process and used by malicious actors to execute denial of service attacks. Only enable this option if you trust the source of your SVG images and understand the risks of processing them.
1642
+ */
1643
+ dangerouslyProcessSVG?: boolean;
1629
1644
  /**
1630
1645
  * @docs
1631
1646
  * @name image.service.config.limitInputPixels
@@ -1766,6 +1781,8 @@ export interface AstroUserConfig<TLocales extends Locales = never, TDriver exten
1766
1781
  * `pathname` patterns:
1767
1782
  * - End with `/**` to allow all sub-routes (like `startsWith`).
1768
1783
  * - End with `/*` to allow only one level of sub-route.
1784
+ *
1785
+ * HTTP redirects are also followed when an image URL matches a remote pattern. The final destination URL must be among the allowed remote patterns to be loaded.
1769
1786
 
1770
1787
  */
1771
1788
  remotePatterns?: Partial<RemotePattern>[];
@@ -2628,6 +2645,23 @@ export interface AstroUserConfig<TLocales extends Locales = never, TDriver exten
2628
2645
  * These flags are not guaranteed to be stable.
2629
2646
  */
2630
2647
  experimental?: {
2648
+ /**
2649
+ * @name experimental.advancedRouting
2650
+ * @type {boolean}
2651
+ * @default `false`
2652
+ * @description
2653
+ * Enables `src/app.ts` as an advanced routing entrypoint, allowing you to
2654
+ * compose Astro's request pipeline with the Web Fetch standard or your own Hono middleware.
2655
+ *
2656
+ * ```js
2657
+ * export default defineConfig({
2658
+ * experimental: {
2659
+ * advancedRouting: true,
2660
+ * },
2661
+ * });
2662
+ * ```
2663
+ */
2664
+ advancedRouting?: boolean;
2631
2665
  /**
2632
2666
  *
2633
2667
  * @name experimental.clientPrerender
@@ -142,7 +142,7 @@ export interface CacheHint {
142
142
  /** Last modified time of the content */
143
143
  lastModified?: Date;
144
144
  }
145
- export interface LiveDataEntry<TData extends Record<string, any> = Record<string, unknown>> {
145
+ export interface LiveDataEntry<TData extends Record<string, any> = Record<string, any>> {
146
146
  /** The ID of the entry. Unique per collection. */
147
147
  id: string;
148
148
  /** The parsed entry data */
@@ -154,17 +154,17 @@ export interface LiveDataEntry<TData extends Record<string, any> = Record<string
154
154
  /** A hint for how to cache this entry */
155
155
  cacheHint?: CacheHint;
156
156
  }
157
- export interface LiveDataCollection<TData extends Record<string, any> = Record<string, unknown>> {
157
+ export interface LiveDataCollection<TData extends Record<string, any> = Record<string, any>> {
158
158
  entries: Array<LiveDataEntry<TData>>;
159
159
  /** A hint for how to cache this collection. Individual entries can also have cache hints */
160
160
  cacheHint?: CacheHint;
161
161
  }
162
- export interface LiveDataCollectionResult<TData extends Record<string, any> = Record<string, unknown>, TError extends Error = Error> {
162
+ export interface LiveDataCollectionResult<TData extends Record<string, any> = Record<string, any>, TError extends Error = Error> {
163
163
  entries?: Array<LiveDataEntry<TData>>;
164
164
  error?: TError | LiveCollectionError;
165
165
  cacheHint?: CacheHint;
166
166
  }
167
- export interface LiveDataEntryResult<TData extends Record<string, any> = Record<string, unknown>, TError extends Error = Error> {
167
+ export interface LiveDataEntryResult<TData extends Record<string, any> = Record<string, any>, TError extends Error = Error> {
168
168
  entry?: LiveDataEntry<TData>;
169
169
  error?: TError | LiveCollectionError;
170
170
  cacheHint?: CacheHint;
@@ -207,7 +207,7 @@ export interface SSRResult {
207
207
  */
208
208
  pathname: string;
209
209
  cookies: AstroCookies | undefined;
210
- serverIslandNameMap: Map<string, string>;
210
+ getServerIslandNameMap: () => Promise<Map<string, string>>;
211
211
  trailingSlash: AstroConfig['trailingSlash'];
212
212
  key: Promise<CryptoKey>;
213
213
  _metadata: SSRMetadata;
@@ -1,18 +1,18 @@
1
1
  import type http from 'node:http';
2
- import { BaseApp, type RenderErrorOptions } from '../core/app/entrypoints/index.js';
2
+ import { BaseApp } from '../core/app/entrypoints/index.js';
3
+ import type { ErrorHandler } from '../core/errors/handler.js';
3
4
  import type { AstroLogger } from '../core/logger/core.js';
4
5
  import type { ModuleLoader } from '../core/module-loader/index.js';
5
- import type { CreateRenderContext, RenderContext } from '../core/render-context.js';
6
6
  import type { AstroSettings, RoutesList } from '../types/astro.js';
7
7
  import type { RouteData, SSRManifest } from '../types/public/index.js';
8
8
  import type { DevServerController } from '../vite-plugin-astro-server/controller.js';
9
9
  import { RunnablePipeline } from './pipeline.js';
10
10
  import type { DevMatch, LogRequestPayload } from '../core/app/base.js';
11
11
  export declare class AstroServerApp extends BaseApp<RunnablePipeline> {
12
+ #private;
12
13
  settings: AstroSettings;
13
14
  loader: ModuleLoader;
14
15
  manifestData: RoutesList;
15
- currentRenderContext: RenderContext | undefined;
16
16
  constructor(manifest: SSRManifest, streaming: boolean | undefined, logger: AstroLogger, manifestData: RoutesList, loader: ModuleLoader, settings: AstroSettings, getDebugInfo: () => Promise<string>);
17
17
  isDev(): boolean;
18
18
  /**
@@ -33,10 +33,9 @@ export declare class AstroServerApp extends BaseApp<RunnablePipeline> {
33
33
  devMatch(pathname: string): Promise<DevMatch | undefined>;
34
34
  static create(manifest: SSRManifest, routesList: RoutesList, logger: AstroLogger, loader: ModuleLoader, settings: AstroSettings, getDebugInfo: () => Promise<string>): Promise<AstroServerApp>;
35
35
  createPipeline(_streaming: boolean, manifest: SSRManifest, settings: AstroSettings, logger: AstroLogger, loader: ModuleLoader, manifestData: RoutesList, getDebugInfo: () => Promise<string>): RunnablePipeline;
36
- createRenderContext(payload: CreateRenderContext): Promise<RenderContext>;
37
36
  handleRequest({ controller, incomingRequest, incomingResponse, isHttps, }: HandleRequest): Promise<void>;
38
37
  match(request: Request, _allowPrerenderedRoutes: boolean): RouteData | undefined;
39
- renderError(request: Request, { skipMiddleware, error, status, response: _response, ...resolvedRenderOptions }: RenderErrorOptions): Promise<Response>;
38
+ protected createErrorHandler(): ErrorHandler;
40
39
  logRequest({ pathname, method, statusCode, isRewrite, reqTime }: LogRequestPayload): void;
41
40
  }
42
41
  type HandleRequest = {
@@ -3,17 +3,13 @@ import { BaseApp } from "../core/app/entrypoints/index.js";
3
3
  import { getFirstForwardedValue, validateForwardedHeaders } from "../core/app/validate-headers.js";
4
4
  import { shouldAppendForwardSlash } from "../core/build/util.js";
5
5
  import { clientLocalsSymbol } from "../core/constants.js";
6
- import {
7
- MiddlewareNoDataOrNextCalled,
8
- MiddlewareNotAResponse
9
- } from "../core/errors/errors-data.js";
10
- import { createSafeError, isAstroError } from "../core/errors/index.js";
6
+ import { createSafeError } from "../core/errors/index.js";
7
+ import { DevErrorHandler } from "../core/errors/dev-handler.js";
11
8
  import { createRequest } from "../core/request.js";
12
9
  import { recordServerError } from "../vite-plugin-astro-server/error.js";
13
10
  import { runWithErrorHandling } from "../vite-plugin-astro-server/index.js";
14
11
  import { handle500Response, writeSSRResult } from "../vite-plugin-astro-server/response.js";
15
12
  import { RunnablePipeline } from "./pipeline.js";
16
- import { getCustom404Route, getCustom500Route } from "../core/routing/helpers.js";
17
13
  import { ensure404Route } from "../core/routing/astro-designed-error-pages.js";
18
14
  import { matchRoute } from "../core/routing/dev.js";
19
15
  import { req } from "../core/messages/runtime.js";
@@ -21,13 +17,27 @@ class AstroServerApp extends BaseApp {
21
17
  settings;
22
18
  loader;
23
19
  manifestData;
24
- currentRenderContext = void 0;
25
20
  constructor(manifest, streaming = true, logger, manifestData, loader, settings, getDebugInfo) {
26
21
  super(manifest, streaming, settings, logger, loader, manifestData, getDebugInfo);
27
22
  this.settings = settings;
28
23
  this.loader = loader;
29
24
  this.manifestData = manifestData;
30
25
  }
26
+ /**
27
+ * Loads the user's `src/app.ts` (via `virtual:astro:fetchable`) and
28
+ * sets it as the fetch handler. Called on every request so that HMR
29
+ * invalidation of the virtual module is picked up automatically.
30
+ * Vite caches the module internally so repeated calls are cheap.
31
+ */
32
+ async #loadFetchHandler() {
33
+ try {
34
+ const mod = await this.loader.import("virtual:astro:fetchable");
35
+ if (mod?.default) {
36
+ this.setFetchHandler(mod.default);
37
+ }
38
+ } catch {
39
+ }
40
+ }
31
41
  isDev() {
32
42
  return true;
33
43
  }
@@ -82,10 +92,6 @@ class AstroServerApp extends BaseApp {
82
92
  });
83
93
  return pipeline;
84
94
  }
85
- async createRenderContext(payload) {
86
- this.currentRenderContext = await super.createRenderContext(payload);
87
- return this.currentRenderContext;
88
- }
89
95
  async handleRequest({
90
96
  controller,
91
97
  incomingRequest,
@@ -108,9 +114,6 @@ class AstroServerApp extends BaseApp {
108
114
  } else {
109
115
  pathname = decodeURI(url.pathname);
110
116
  }
111
- if (this.manifest.trailingSlash === "never" && pathname === "/" && this.manifest.base !== "/") {
112
- pathname = "";
113
- }
114
117
  url.pathname = removeTrailingForwardSlash(this.manifest.base) + url.pathname;
115
118
  if (url.pathname.endsWith("/") && !shouldAppendForwardSlash(this.manifest.trailingSlash, this.manifest.buildFormat)) {
116
119
  url.pathname = url.pathname.slice(0, -1);
@@ -127,6 +130,7 @@ class AstroServerApp extends BaseApp {
127
130
  body = Buffer.concat(bytes);
128
131
  }
129
132
  const self = this;
133
+ await self.#loadFetchHandler();
130
134
  await runWithErrorHandling({
131
135
  controller,
132
136
  pathname,
@@ -174,60 +178,8 @@ class AstroServerApp extends BaseApp {
174
178
  match(request, _allowPrerenderedRoutes) {
175
179
  return super.match(request, true);
176
180
  }
177
- async renderError(request, {
178
- skipMiddleware = false,
179
- error,
180
- status,
181
- response: _response,
182
- ...resolvedRenderOptions
183
- }) {
184
- if (isAstroError(error) && [MiddlewareNoDataOrNextCalled.name, MiddlewareNotAResponse.name].includes(error.name)) {
185
- throw error;
186
- }
187
- const renderRoute = async (routeData) => {
188
- try {
189
- const preloadedComponent = await this.pipeline.getComponentByRoute(routeData);
190
- const renderContext = await this.createRenderContext({
191
- locals: resolvedRenderOptions.locals,
192
- pipeline: this.pipeline,
193
- pathname: this.getPathnameFromRequest(request),
194
- skipMiddleware,
195
- request,
196
- routeData,
197
- clientAddress: resolvedRenderOptions.clientAddress,
198
- status,
199
- shouldInjectCspMetaTags: !!this.manifest.csp
200
- });
201
- renderContext.props.error = error;
202
- const response = await renderContext.render(preloadedComponent);
203
- if (error) {
204
- this.logger.error("router", error.stack || error.message);
205
- }
206
- return response;
207
- } catch (_err) {
208
- if (skipMiddleware === false) {
209
- return this.renderError(request, {
210
- ...resolvedRenderOptions,
211
- status: 500,
212
- skipMiddleware: true,
213
- error: _err
214
- });
215
- }
216
- throw _err;
217
- }
218
- };
219
- if (status === 404) {
220
- const custom404 = getCustom404Route(this.manifestData);
221
- if (custom404) {
222
- return renderRoute(custom404);
223
- }
224
- }
225
- const custom500 = getCustom500Route(this.manifestData);
226
- if (!custom500) {
227
- throw error;
228
- } else {
229
- return renderRoute(custom500);
230
- }
181
+ createErrorHandler() {
182
+ return new DevErrorHandler(this, { shouldInjectCspMetaTags: true });
231
183
  }
232
184
  logRequest({ pathname, method, statusCode, isRewrite, reqTime }) {
233
185
  if (pathname === "/favicon.ico") {
@@ -1,7 +1,7 @@
1
1
  import { transformWithEsbuild } from "vite";
2
2
  import { compile } from "../core/compile/index.js";
3
3
  import { getFileInfo } from "../vite-plugin-utils/index.js";
4
- import { frontmatterRE } from "./utils.js";
4
+ import { frontmatterRE, replaceTopLevelReturns } from "./utils.js";
5
5
  async function compileAstro({
6
6
  compileProps,
7
7
  astroFileToCompileMetadata,
@@ -70,7 +70,7 @@ async function enhanceCompileError({
70
70
  const lineText = err.loc?.lineText;
71
71
  const scannedFrontmatter = frontmatterRE.exec(source);
72
72
  if (scannedFrontmatter) {
73
- const frontmatter = scannedFrontmatter[1].replace(/\breturn\s*;/g, "throw 0;").replace(/\breturn\b/g, "throw ");
73
+ const frontmatter = replaceTopLevelReturns(scannedFrontmatter[1]);
74
74
  if (lineText && !frontmatter.includes(lineText)) throw err;
75
75
  try {
76
76
  await transformWithEsbuild(frontmatter, id, {
@@ -1,3 +1,4 @@
1
1
  import type { PluginContainer } from 'vite';
2
2
  export declare const frontmatterRE: RegExp;
3
+ export declare function replaceTopLevelReturns(code: string): string;
3
4
  export declare function loadId(pluginContainer: PluginContainer, id: string): Promise<string | undefined>;
@@ -1,5 +1,12 @@
1
1
  import fs from "node:fs/promises";
2
2
  const frontmatterRE = /^---(.*?)^---/ms;
3
+ const RETURN_REPLACE_RE = /(\/\/[^\n]*|\/\*[\s\S]*?\*\/|`(?:[^`\\]|\\.)*`|"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*')|(?<!\.)\breturn(\s*;|\b)/g;
4
+ function replaceTopLevelReturns(code) {
5
+ return code.replace(RETURN_REPLACE_RE, (_match, skip, tail) => {
6
+ if (skip !== void 0) return skip;
7
+ return tail.trim() === ";" ? "throw 0;" : "throw ";
8
+ });
9
+ }
3
10
  async function loadId(pluginContainer, id) {
4
11
  const result = await pluginContainer.load(id, { ssr: true });
5
12
  if (result) {
@@ -16,5 +23,6 @@ async function loadId(pluginContainer, id) {
16
23
  }
17
24
  export {
18
25
  frontmatterRE,
19
- loadId
26
+ loadId,
27
+ replaceTopLevelReturns
20
28
  };
@@ -9,11 +9,20 @@ import { ASTRO_VITE_ENVIRONMENT_NAMES } from "../core/constants.js";
9
9
  const VIRTUAL_COMPONENT_METADATA = "virtual:astro:component-metadata";
10
10
  const RESOLVED_VIRTUAL_COMPONENT_METADATA = `\0${VIRTUAL_COMPONENT_METADATA}`;
11
11
  function configHeadVitePlugin() {
12
- let environment;
12
+ let environments = [];
13
+ function findModule(id) {
14
+ for (const env of environments) {
15
+ const mod = env.moduleGraph.getModuleById(id);
16
+ if (mod) return mod;
17
+ }
18
+ return void 0;
19
+ }
13
20
  function invalidateComponentMetadataModule() {
14
- const virtualMod = environment.moduleGraph.getModuleById(RESOLVED_VIRTUAL_COMPONENT_METADATA);
15
- if (virtualMod) {
16
- environment.moduleGraph.invalidateModule(virtualMod);
21
+ for (const env of environments) {
22
+ const virtualMod = env.moduleGraph.getModuleById(RESOLVED_VIRTUAL_COMPONENT_METADATA);
23
+ if (virtualMod) {
24
+ env.moduleGraph.invalidateModule(virtualMod);
25
+ }
17
26
  }
18
27
  }
19
28
  function buildImporterGraphFromEnvironment(seed) {
@@ -23,7 +32,7 @@ function configHeadVitePlugin() {
23
32
  const current = queue.pop();
24
33
  if (collected.has(current)) continue;
25
34
  collected.add(current);
26
- const mod = environment.moduleGraph.getModuleById(current);
35
+ const mod = findModule(current);
27
36
  for (const importer of mod?.importers ?? []) {
28
37
  if (importer.id) {
29
38
  queue.push(importer.id);
@@ -31,7 +40,7 @@ function configHeadVitePlugin() {
31
40
  }
32
41
  }
33
42
  return buildImporterGraphFromModuleInfo(collected, (id) => {
34
- const mod = environment.moduleGraph.getModuleById(id);
43
+ const mod = findModule(id);
35
44
  if (!mod) return null;
36
45
  return {
37
46
  importers: Array.from(mod.importers).map((importer) => importer.id).filter((moduleId) => !!moduleId),
@@ -61,7 +70,10 @@ function configHeadVitePlugin() {
61
70
  enforce: "pre",
62
71
  apply: "serve",
63
72
  configureServer(devServer) {
64
- environment = devServer.environments[ASTRO_VITE_ENVIRONMENT_NAMES.ssr];
73
+ environments = [
74
+ devServer.environments[ASTRO_VITE_ENVIRONMENT_NAMES.ssr],
75
+ devServer.environments[ASTRO_VITE_ENVIRONMENT_NAMES.prerender]
76
+ ].filter((e) => !!e);
65
77
  devServer.watcher.on("add", invalidateComponentMetadataModule);
66
78
  devServer.watcher.on("unlink", invalidateComponentMetadataModule);
67
79
  devServer.watcher.on("change", invalidateComponentMetadataModule);
@@ -70,19 +82,24 @@ function configHeadVitePlugin() {
70
82
  if (id !== RESOLVED_VIRTUAL_COMPONENT_METADATA) {
71
83
  return;
72
84
  }
85
+ const seen = /* @__PURE__ */ new Set();
73
86
  const componentMetadataEntries = [];
74
- for (const [moduleId, mod] of environment.moduleGraph.idToModuleMap) {
75
- const info = this.getModuleInfo(moduleId) ?? (mod.id ? this.getModuleInfo(mod.id) : null);
76
- if (!info) continue;
77
- const astro = getAstroMetadata(info);
78
- if (!astro) continue;
79
- componentMetadataEntries.push([
80
- moduleId,
81
- {
82
- containsHead: astro.containsHead,
83
- propagation: astro.propagation
84
- }
85
- ]);
87
+ for (const env of environments) {
88
+ for (const [moduleId, mod] of env.moduleGraph.idToModuleMap) {
89
+ if (seen.has(moduleId)) continue;
90
+ const info = this.getModuleInfo(moduleId) ?? (mod.id ? this.getModuleInfo(mod.id) : null);
91
+ if (!info) continue;
92
+ const astro = getAstroMetadata(info);
93
+ if (!astro) continue;
94
+ seen.add(moduleId);
95
+ componentMetadataEntries.push([
96
+ moduleId,
97
+ {
98
+ containsHead: astro.containsHead,
99
+ propagation: astro.propagation
100
+ }
101
+ ]);
102
+ }
86
103
  }
87
104
  return {
88
105
  code: `export const componentMetadataEntries = ${JSON.stringify(componentMetadataEntries)};`
@@ -8,6 +8,7 @@ export declare function getFileInfo(id: string, config: AstroConfig): {
8
8
  *
9
9
  * - /@fs/home/user/project/src/pages/index.astro
10
10
  * - /src/pages/index.astro
11
+ * - ./src/pages/index.astro
11
12
  *
12
13
  * as absolute file paths with forward slashes.
13
14
  */
@@ -23,6 +23,9 @@ function getFileInfo(id, config) {
23
23
  function normalizeFilename(filename, root) {
24
24
  if (filename.startsWith("/@fs")) {
25
25
  filename = filename.slice("/@fs".length);
26
+ } else if (filename.startsWith(".")) {
27
+ const url = new URL(filename, root);
28
+ filename = viteID(url);
26
29
  } else if (filename.startsWith("/") && !commonAncestorPath(filename, fileURLToPath(root))) {
27
30
  const url = new URL("." + filename, root);
28
31
  filename = viteID(url);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "astro",
3
- "version": "6.2.1",
3
+ "version": "6.3.0",
4
4
  "description": "Astro is a modern site builder with web best practices, performance, and DX front-of-mind.",
5
5
  "type": "module",
6
6
  "author": "withastro",
@@ -21,6 +21,9 @@
21
21
  "app/*": [
22
22
  "./dist/core/app/*"
23
23
  ],
24
+ "hono": [
25
+ "./dist/core/hono/index"
26
+ ],
24
27
  "middleware": [
25
28
  "./dist/virtual-modules/middleware.d.ts"
26
29
  ]
@@ -55,6 +58,7 @@
55
58
  "./app/entrypoint/dev": "./dist/core/app/entrypoints/virtual/dev.js",
56
59
  "./app/entrypoint/prod": "./dist/core/app/entrypoints/virtual/prod.js",
57
60
  "./app/manifest": "./dist/core/app/entrypoints/manifest.js",
61
+ "./app/fetch/default-handler": "./dist/core/fetch/default-handler.js",
58
62
  "./entrypoints/prerender": "./dist/entrypoints/prerender.js",
59
63
  "./entrypoints/legacy": "./dist/entrypoints/legacy.js",
60
64
  "./client/*": "./dist/runtime/client/*",
@@ -71,6 +75,8 @@
71
75
  "./assets/services/sharp": "./dist/assets/services/sharp.js",
72
76
  "./assets/services/noop": "./dist/assets/services/noop.js",
73
77
  "./cache/memory": "./dist/core/cache/memory-provider.js",
78
+ "./fetch": "./dist/core/fetch/index.js",
79
+ "./hono": "./dist/core/hono/index.js",
74
80
  "./assets/fonts/runtime.js": "./dist/assets/fonts/runtime.js",
75
81
  "./loaders": "./dist/content/loaders/index.js",
76
82
  "./content/config": "./dist/content/config.js",
@@ -124,10 +130,12 @@
124
130
  "esbuild": "^0.27.3",
125
131
  "flattie": "^1.1.1",
126
132
  "fontace": "~0.4.1",
133
+ "get-tsconfig": "5.0.0-beta.4",
127
134
  "github-slugger": "^2.0.0",
128
135
  "html-escaper": "3.0.3",
129
136
  "http-cache-semantics": "^4.2.0",
130
137
  "js-yaml": "^4.1.1",
138
+ "jsonc-parser": "^3.3.1",
131
139
  "magic-string": "^0.30.21",
132
140
  "magicast": "^0.5.2",
133
141
  "mrmime": "^2.0.1",
@@ -146,7 +154,6 @@
146
154
  "tinyclip": "^0.1.12",
147
155
  "tinyexec": "^1.0.4",
148
156
  "tinyglobby": "^0.2.15",
149
- "tsconfck": "^3.1.6",
150
157
  "ultrahtml": "^1.6.0",
151
158
  "unifont": "~0.7.4",
152
159
  "unist-util-visit": "^5.1.0",
@@ -157,9 +164,9 @@
157
164
  "xxhash-wasm": "^1.1.0",
158
165
  "yargs-parser": "^22.0.0",
159
166
  "zod": "^4.3.6",
167
+ "@astrojs/telemetry": "3.3.2",
160
168
  "@astrojs/internal-helpers": "0.9.0",
161
- "@astrojs/markdown-remark": "7.1.1",
162
- "@astrojs/telemetry": "3.3.1"
169
+ "@astrojs/markdown-remark": "7.1.1"
163
170
  },
164
171
  "optionalDependencies": {
165
172
  "sharp": "^0.34.0"
@@ -180,6 +187,7 @@
180
187
  "eol": "^0.10.0",
181
188
  "expect-type": "^1.3.0",
182
189
  "fs-fixture": "^2.13.0",
190
+ "hono": "^4.12.14",
183
191
  "mdast-util-mdx": "^3.0.0",
184
192
  "mdast-util-mdx-jsx": "^3.2.0",
185
193
  "node-mocks-http": "^1.17.2",
@@ -211,7 +219,7 @@
211
219
  },
212
220
  "scripts": {
213
221
  "prebuild": "astro-scripts prebuild --to-string \"src/runtime/server/astro-island.ts\" \"src/runtime/client/{idle,load,media,only,visible}.ts\"",
214
- "build": "pnpm run prebuild && astro-scripts build \"src/**/*.{ts,js}\" --copy-wasm && tsc && astro-check -- -- --root ./components",
222
+ "build": "pnpm run prebuild && astro-scripts build \"src/**/*.{ts,js}\" --copy-wasm && tsc -b && astro-check -- -- --root ./components",
215
223
  "build:ci": "pnpm run prebuild && astro-scripts build \"src/**/*.{ts,js}\" --copy-wasm",
216
224
  "dev": "astro-scripts dev --copy-wasm --prebuild \"src/runtime/server/astro-island.ts\" --prebuild \"src/runtime/client/{idle,load,media,only,visible}.ts\" \"src/**/*.{ts,js}\"",
217
225
  "test": "pnpm run test:unit && pnpm run test:integration && pnpm run test:types",
@@ -222,7 +230,6 @@
222
230
  "test:e2e:chrome": "playwright test",
223
231
  "test:e2e:firefox": "playwright test --config playwright.firefox.config.js",
224
232
  "test:types": "tsc --build test/types/tsconfig.json",
225
- "typecheck:tests": "tsc --build tsconfig.test.json",
226
233
  "test:unit": "astro-scripts test \"test/units/**/*.test.ts\" --strip-types --teardown ./test/units/teardown.ts",
227
234
  "test:integration": "pnpm run test:integration:js && pnpm run test:integration:ts",
228
235
  "test:integration:js": "astro-scripts test \"test/*.test.js\"",
@@ -1,77 +0,0 @@
1
- import type { ActionAPIContext } from '../actions/runtime/types.js';
2
- import type { ComponentInstance } from '../types/astro.js';
3
- import type { MiddlewareHandler, Params, Props } from '../types/public/common.js';
4
- import type { APIContext, AstroGlobal } from '../types/public/context.js';
5
- import type { RouteData, SSRResult } from '../types/public/internal.js';
6
- import type { ServerIslandMappings, SSRActions } from './app/types.js';
7
- import { AstroCookies } from './cookies/index.js';
8
- import { type Pipeline } from './render/index.js';
9
- import { type CacheLike } from './cache/runtime/cache.js';
10
- import { AstroSession } from './session/runtime.js';
11
- /**
12
- * Each request is rendered using a `RenderContext`.
13
- * It contains data unique to each request. It is responsible for executing middleware, calling endpoints, and rendering the page by gathering necessary data from a `Pipeline`.
14
- */
15
- export type CreateRenderContext = Pick<RenderContext, 'pathname' | 'pipeline' | 'request' | 'routeData' | 'clientAddress'> & Partial<Pick<RenderContext, 'locals' | 'status' | 'props' | 'partial' | 'actions' | 'shouldInjectCspMetaTags' | 'skipMiddleware'>>;
16
- export declare class RenderContext {
17
- #private;
18
- readonly pipeline: Pipeline;
19
- locals: App.Locals;
20
- readonly middleware: MiddlewareHandler;
21
- readonly actions: SSRActions;
22
- readonly serverIslands: ServerIslandMappings;
23
- pathname: string;
24
- request: Request;
25
- routeData: RouteData;
26
- status: number;
27
- clientAddress: string | undefined;
28
- protected cookies: AstroCookies;
29
- params: Params;
30
- protected url: URL;
31
- props: Props;
32
- partial: undefined | boolean;
33
- shouldInjectCspMetaTags: boolean;
34
- session: AstroSession | undefined;
35
- cache: CacheLike;
36
- skipMiddleware: boolean;
37
- private constructor();
38
- /**
39
- * A flag that tells the render content if the rewriting was triggered
40
- */
41
- isRewriting: boolean;
42
- /**
43
- * A safety net in case of loops
44
- */
45
- counter: number;
46
- result: SSRResult | undefined;
47
- static create({ locals, pathname, pipeline, request, routeData, clientAddress, status, props, partial, shouldInjectCspMetaTags, skipMiddleware, }: CreateRenderContext): Promise<RenderContext>;
48
- /**
49
- * The main function of the RenderContext.
50
- *
51
- * Use this function to render any route known to Astro.
52
- * It attempts to render a route. A route can be a:
53
- *
54
- * - page
55
- * - redirect
56
- * - endpoint
57
- * - fallback
58
- */
59
- render(componentInstance: ComponentInstance | undefined, slots?: Record<string, any>): Promise<Response>;
60
- createAPIContext(props: APIContext['props'], context: ActionAPIContext): APIContext;
61
- createActionAPIContext(): ActionAPIContext;
62
- createResult(mod: ComponentInstance, ctx: ActionAPIContext): Promise<SSRResult>;
63
- /**
64
- * The Astro global is sourced in 3 different phases:
65
- * - **Static**: `.generator` and `.glob` is printed by the compiler, instantiated once per process per astro file
66
- * - **Page-level**: `.request`, `.cookies`, `.locals` etc. These remain the same for the duration of the request.
67
- * - **Component-level**: `.props`, `.slots`, and `.self` are unique to each _use_ of each component.
68
- *
69
- * The page level partial is used as the prototype of the user-visible `Astro` global object, which is instantiated once per use of a component.
70
- */
71
- createAstro(result: SSRResult, props: Record<string, any>, slotValues: Record<string, any> | null, apiContext: ActionAPIContext): AstroGlobal;
72
- createAstroPagePartial(result: SSRResult, apiContext: ActionAPIContext): Omit<AstroGlobal, 'props' | 'self' | 'slots'>;
73
- getClientAddress(): string;
74
- computeCurrentLocale(): string | undefined;
75
- computePreferredLocale(): string | undefined;
76
- computePreferredLocaleList(): string[] | undefined;
77
- }