astro 6.2.2 → 6.3.1

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 (113) 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 +8 -20
  8. package/dist/assets/endpoint/loadImage.d.ts +11 -0
  9. package/dist/assets/endpoint/loadImage.js +19 -0
  10. package/dist/assets/endpoint/shared.js +7 -2
  11. package/dist/assets/index.d.ts +1 -0
  12. package/dist/assets/index.js +2 -0
  13. package/dist/assets/services/sharp.js +7 -0
  14. package/dist/assets/utils/index.d.ts +1 -0
  15. package/dist/assets/utils/index.js +2 -0
  16. package/dist/assets/utils/redirectValidation.d.ts +48 -0
  17. package/dist/assets/utils/redirectValidation.js +48 -0
  18. package/dist/assets/utils/remoteProbe.js +25 -2
  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/server-listeners.js +0 -4
  23. package/dist/content/vite-plugin-content-virtual-mod.js +9 -1
  24. package/dist/core/app/base.d.ts +33 -15
  25. package/dist/core/app/base.js +120 -324
  26. package/dist/core/app/dev/app.d.ts +3 -2
  27. package/dist/core/app/dev/app.js +4 -60
  28. package/dist/core/app/entrypoints/virtual/dev.js +2 -0
  29. package/dist/core/app/entrypoints/virtual/prod.js +4 -1
  30. package/dist/core/app/prepare-response.d.ts +11 -0
  31. package/dist/core/app/prepare-response.js +18 -0
  32. package/dist/core/app/render-options.d.ts +11 -0
  33. package/dist/core/app/render-options.js +11 -0
  34. package/dist/core/base-pipeline.d.ts +38 -1
  35. package/dist/core/base-pipeline.js +50 -7
  36. package/dist/core/build/app.d.ts +3 -4
  37. package/dist/core/build/app.js +3 -17
  38. package/dist/core/cache/handler.d.ts +29 -0
  39. package/dist/core/cache/handler.js +81 -0
  40. package/dist/core/config/schemas/base.d.ts +4 -0
  41. package/dist/core/config/schemas/base.js +4 -0
  42. package/dist/core/config/schemas/relative.d.ts +6 -0
  43. package/dist/core/constants.d.ts +27 -1
  44. package/dist/core/constants.js +14 -1
  45. package/dist/core/cookies/cookies.d.ts +7 -2
  46. package/dist/core/cookies/cookies.js +11 -4
  47. package/dist/core/cookies/response.d.ts +1 -1
  48. package/dist/core/cookies/response.js +1 -2
  49. package/dist/core/create-vite.js +15 -0
  50. package/dist/core/csp/runtime.js +6 -4
  51. package/dist/core/dev/dev.js +1 -1
  52. package/dist/core/errors/build-handler.d.ts +17 -0
  53. package/dist/core/errors/build-handler.js +22 -0
  54. package/dist/core/errors/default-handler.d.ts +14 -0
  55. package/dist/core/errors/default-handler.js +144 -0
  56. package/dist/core/errors/dev-handler.d.ts +21 -0
  57. package/dist/core/errors/dev-handler.js +82 -0
  58. package/dist/core/errors/handler.d.ts +9 -0
  59. package/dist/core/errors/handler.js +0 -0
  60. package/dist/core/fetch/default-handler.d.ts +17 -0
  61. package/dist/core/fetch/default-handler.js +45 -0
  62. package/dist/core/fetch/fetch-state.d.ts +244 -0
  63. package/dist/core/fetch/fetch-state.js +779 -0
  64. package/dist/core/fetch/index.d.ts +61 -0
  65. package/dist/core/fetch/index.js +121 -0
  66. package/dist/core/fetch/types.d.ts +6 -0
  67. package/dist/core/fetch/types.js +0 -0
  68. package/dist/core/fetch/vite-plugin.d.ts +5 -0
  69. package/dist/core/fetch/vite-plugin.js +69 -0
  70. package/dist/core/hono/index.d.ts +21 -0
  71. package/dist/core/hono/index.js +98 -0
  72. package/dist/core/i18n/handler.d.ts +18 -0
  73. package/dist/core/i18n/handler.js +119 -0
  74. package/dist/core/logger/core.d.ts +8 -0
  75. package/dist/core/logger/core.js +16 -0
  76. package/dist/core/messages/runtime.js +1 -1
  77. package/dist/core/middleware/astro-middleware.d.ts +27 -0
  78. package/dist/core/middleware/astro-middleware.js +53 -0
  79. package/dist/core/pages/handler.d.ts +20 -0
  80. package/dist/core/pages/handler.js +74 -0
  81. package/dist/core/preview/static-preview-server.js +3 -1
  82. package/dist/core/redirects/render.d.ts +2 -2
  83. package/dist/core/redirects/render.js +7 -8
  84. package/dist/core/rewrites/handler.d.ts +37 -0
  85. package/dist/core/rewrites/handler.js +67 -0
  86. package/dist/core/routing/3xx.js +8 -4
  87. package/dist/core/routing/handler.d.ts +17 -0
  88. package/dist/core/routing/handler.js +172 -0
  89. package/dist/core/routing/match.d.ts +0 -7
  90. package/dist/core/routing/match.js +0 -5
  91. package/dist/core/routing/trailing-slash-handler.d.ts +18 -0
  92. package/dist/core/routing/trailing-slash-handler.js +67 -0
  93. package/dist/core/session/drivers.d.ts +1 -1
  94. package/dist/core/session/handler.d.ts +11 -0
  95. package/dist/core/session/handler.js +33 -0
  96. package/dist/core/util/normalized-url.d.ts +10 -0
  97. package/dist/core/util/normalized-url.js +21 -0
  98. package/dist/i18n/middleware.d.ts +10 -0
  99. package/dist/i18n/middleware.js +4 -88
  100. package/dist/i18n/utils.js +2 -2
  101. package/dist/runtime/server/astro-island.js +57 -20
  102. package/dist/runtime/server/astro-island.prebuilt-dev.d.ts +1 -1
  103. package/dist/runtime/server/astro-island.prebuilt-dev.js +1 -1
  104. package/dist/runtime/server/astro-island.prebuilt.d.ts +1 -1
  105. package/dist/runtime/server/astro-island.prebuilt.js +1 -1
  106. package/dist/runtime/server/render/server-islands.js +2 -1
  107. package/dist/types/public/config.d.ts +46 -12
  108. package/dist/types/public/internal.d.ts +1 -1
  109. package/dist/vite-plugin-app/app.d.ts +4 -5
  110. package/dist/vite-plugin-app/app.js +20 -65
  111. package/package.json +11 -7
  112. package/dist/core/render-context.d.ts +0 -77
  113. package/dist/core/render-context.js +0 -826
@@ -1,826 +0,0 @@
1
- import colors from "piccolore";
2
- import { deserializeActionResult } from "../actions/runtime/client.js";
3
- import { getActionContext } from "../actions/runtime/server.js";
4
- import { createCallAction, createGetActionResult, hasActionPayload } from "../actions/utils.js";
5
- import {
6
- computeCurrentLocale,
7
- computeCurrentLocaleFromParams,
8
- computePreferredLocale,
9
- computePreferredLocaleList
10
- } from "../i18n/utils.js";
11
- import { renderEndpoint } from "../runtime/server/endpoint.js";
12
- import { renderPage } from "../runtime/server/index.js";
13
- import {
14
- ASTRO_GENERATOR,
15
- pipelineSymbol,
16
- REROUTE_DIRECTIVE_HEADER,
17
- REWRITE_DIRECTIVE_HEADER_KEY,
18
- REWRITE_DIRECTIVE_HEADER_VALUE,
19
- ROUTE_TYPE_HEADER,
20
- responseSentSymbol
21
- } from "./constants.js";
22
- import { AstroCookies, attachCookiesToResponse } from "./cookies/index.js";
23
- import { getCookiesFromResponse } from "./cookies/response.js";
24
- import { pushDirective } from "./csp/runtime.js";
25
- import { generateCspDigest } from "./encryption.js";
26
- import { ForbiddenRewrite } from "./errors/errors-data.js";
27
- import { AstroError, AstroErrorData } from "./errors/index.js";
28
- import { callMiddleware } from "./middleware/callMiddleware.js";
29
- import { sequence } from "./middleware/index.js";
30
- import { renderRedirect } from "./redirects/render.js";
31
- import { getParams, getProps, Slots } from "./render/index.js";
32
- import { isRoute404or500, isRouteExternalRedirect, isRouteServerIsland } from "./routing/match.js";
33
- import { copyRequest, getOriginPathname, setOriginPathname } from "./routing/rewrite.js";
34
- import { AstroCache } from "./cache/runtime/cache.js";
35
- import { NoopAstroCache, DisabledAstroCache } from "./cache/runtime/noop.js";
36
- import { compileCacheRoutes, matchCacheRoute } from "./cache/runtime/route-matching.js";
37
- import { AstroSession } from "./session/runtime.js";
38
- import { collapseDuplicateSlashes } from "@astrojs/internal-helpers/path";
39
- import { validateAndDecodePathname } from "./util/pathname.js";
40
- class RenderContext {
41
- pipeline;
42
- locals;
43
- middleware;
44
- actions;
45
- serverIslands;
46
- // It must be a DECODED pathname
47
- pathname;
48
- request;
49
- routeData;
50
- status;
51
- clientAddress;
52
- cookies;
53
- params;
54
- url;
55
- props;
56
- partial;
57
- shouldInjectCspMetaTags;
58
- session;
59
- cache;
60
- skipMiddleware;
61
- constructor(pipeline, locals, middleware, actions, serverIslands, pathname, request, routeData, status, clientAddress, cookies = new AstroCookies(request), params = getParams(routeData, pathname), url = RenderContext.#createNormalizedUrl(request.url), props = {}, partial = void 0, shouldInjectCspMetaTags = pipeline.manifest.shouldInjectCspMetaTags, session = void 0, cache, skipMiddleware = false) {
62
- this.pipeline = pipeline;
63
- this.locals = locals;
64
- this.middleware = middleware;
65
- this.actions = actions;
66
- this.serverIslands = serverIslands;
67
- this.pathname = pathname;
68
- this.request = request;
69
- this.routeData = routeData;
70
- this.status = status;
71
- this.clientAddress = clientAddress;
72
- this.cookies = cookies;
73
- this.params = params;
74
- this.url = url;
75
- this.props = props;
76
- this.partial = partial;
77
- this.shouldInjectCspMetaTags = shouldInjectCspMetaTags;
78
- this.session = session;
79
- this.cache = cache;
80
- this.skipMiddleware = skipMiddleware;
81
- }
82
- static #createNormalizedUrl(requestUrl) {
83
- const url = new URL(requestUrl);
84
- try {
85
- url.pathname = validateAndDecodePathname(url.pathname);
86
- } catch {
87
- try {
88
- url.pathname = decodeURI(url.pathname);
89
- } catch {
90
- }
91
- }
92
- url.pathname = collapseDuplicateSlashes(url.pathname);
93
- return url;
94
- }
95
- /**
96
- * A flag that tells the render content if the rewriting was triggered
97
- */
98
- isRewriting = false;
99
- /**
100
- * A safety net in case of loops
101
- */
102
- counter = 0;
103
- result = void 0;
104
- static async create({
105
- locals = {},
106
- pathname,
107
- pipeline,
108
- request,
109
- routeData,
110
- clientAddress,
111
- status = 200,
112
- props,
113
- partial = void 0,
114
- shouldInjectCspMetaTags,
115
- skipMiddleware = false
116
- }) {
117
- const pipelineMiddleware = await pipeline.getMiddleware();
118
- const pipelineActions = await pipeline.getActions();
119
- const pipelineSessionDriver = await pipeline.getSessionDriver();
120
- const serverIslands = await pipeline.getServerIslands();
121
- setOriginPathname(
122
- request,
123
- pathname,
124
- pipeline.manifest.trailingSlash,
125
- pipeline.manifest.buildFormat
126
- );
127
- const cookies = new AstroCookies(request);
128
- const session = pipeline.manifest.sessionConfig && pipelineSessionDriver ? new AstroSession({
129
- cookies,
130
- config: pipeline.manifest.sessionConfig,
131
- runtimeMode: pipeline.runtimeMode,
132
- driverFactory: pipelineSessionDriver,
133
- mockStorage: null
134
- }) : void 0;
135
- let cache;
136
- if (!pipeline.cacheConfig) {
137
- cache = new DisabledAstroCache(pipeline.logger);
138
- } else if (pipeline.runtimeMode === "development") {
139
- cache = new NoopAstroCache();
140
- } else {
141
- const cacheProvider = await pipeline.getCacheProvider();
142
- cache = new AstroCache(cacheProvider);
143
- if (pipeline.cacheConfig?.routes) {
144
- if (!pipeline.compiledCacheRoutes) {
145
- pipeline.compiledCacheRoutes = compileCacheRoutes(
146
- pipeline.cacheConfig.routes,
147
- pipeline.manifest.base,
148
- pipeline.manifest.trailingSlash
149
- );
150
- }
151
- const matched = matchCacheRoute(pathname, pipeline.compiledCacheRoutes);
152
- if (matched) {
153
- cache.set(matched);
154
- }
155
- }
156
- }
157
- return new RenderContext(
158
- pipeline,
159
- locals,
160
- sequence(...pipeline.internalMiddleware, pipelineMiddleware),
161
- pipelineActions,
162
- serverIslands,
163
- pathname,
164
- request,
165
- routeData,
166
- status,
167
- clientAddress,
168
- cookies,
169
- void 0,
170
- void 0,
171
- props,
172
- partial,
173
- shouldInjectCspMetaTags ?? pipeline.manifest.shouldInjectCspMetaTags,
174
- session,
175
- cache,
176
- skipMiddleware
177
- );
178
- }
179
- /**
180
- * The main function of the RenderContext.
181
- *
182
- * Use this function to render any route known to Astro.
183
- * It attempts to render a route. A route can be a:
184
- *
185
- * - page
186
- * - redirect
187
- * - endpoint
188
- * - fallback
189
- */
190
- async render(componentInstance, slots = {}) {
191
- const { middleware, pipeline } = this;
192
- const { logger, streaming, manifest } = pipeline;
193
- const props = Object.keys(this.props).length > 0 ? this.props : await getProps({
194
- mod: componentInstance,
195
- routeData: this.routeData,
196
- routeCache: this.pipeline.routeCache,
197
- pathname: this.pathname,
198
- logger,
199
- serverLike: manifest.serverLike,
200
- base: manifest.base,
201
- trailingSlash: manifest.trailingSlash
202
- });
203
- const actionApiContext = this.createActionAPIContext();
204
- const apiContext = this.createAPIContext(props, actionApiContext);
205
- this.counter++;
206
- if (this.counter === 4) {
207
- return new Response("Loop Detected", {
208
- // https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/508
209
- status: 508,
210
- statusText: "Astro detected a loop where you tried to call the rewriting logic more than four times."
211
- });
212
- }
213
- const lastNext = async (ctx, payload) => {
214
- if (payload) {
215
- const oldPathname = this.pathname;
216
- pipeline.logger.debug("router", "Called rewriting to:", payload);
217
- const {
218
- routeData,
219
- componentInstance: newComponent,
220
- pathname,
221
- newUrl
222
- } = await pipeline.tryRewrite(payload, this.request);
223
- if (this.pipeline.manifest.serverLike === true && this.routeData.prerender === false && routeData.prerender === true) {
224
- throw new AstroError({
225
- ...ForbiddenRewrite,
226
- message: ForbiddenRewrite.message(this.pathname, pathname, routeData.component),
227
- hint: ForbiddenRewrite.hint(routeData.component)
228
- });
229
- }
230
- this.routeData = routeData;
231
- componentInstance = newComponent;
232
- if (payload instanceof Request) {
233
- this.request = payload;
234
- } else {
235
- this.request = copyRequest(
236
- newUrl,
237
- this.request,
238
- // need to send the flag of the previous routeData
239
- routeData.prerender,
240
- this.pipeline.logger,
241
- this.routeData.route
242
- );
243
- }
244
- this.isRewriting = true;
245
- this.url = RenderContext.#createNormalizedUrl(this.request.url);
246
- this.params = getParams(routeData, pathname);
247
- this.pathname = pathname;
248
- this.status = 200;
249
- setOriginPathname(
250
- this.request,
251
- oldPathname,
252
- this.pipeline.manifest.trailingSlash,
253
- this.pipeline.manifest.buildFormat
254
- );
255
- }
256
- let response2;
257
- if (!ctx.isPrerendered && !this.skipMiddleware) {
258
- const { action, setActionResult, serializeActionResult } = getActionContext(ctx);
259
- if (action?.calledFrom === "form") {
260
- const actionResult = await action.handler();
261
- setActionResult(action.name, serializeActionResult(actionResult));
262
- }
263
- }
264
- switch (this.routeData.type) {
265
- case "endpoint": {
266
- response2 = await renderEndpoint(
267
- componentInstance,
268
- ctx,
269
- this.routeData.prerender,
270
- logger
271
- );
272
- break;
273
- }
274
- case "redirect":
275
- return renderRedirect(this);
276
- case "page": {
277
- this.result = await this.createResult(componentInstance, actionApiContext);
278
- try {
279
- response2 = await renderPage(
280
- this.result,
281
- componentInstance?.default,
282
- props,
283
- slots,
284
- streaming,
285
- this.routeData
286
- );
287
- } catch (e) {
288
- this.result.cancelled = true;
289
- throw e;
290
- }
291
- response2.headers.set(ROUTE_TYPE_HEADER, "page");
292
- if (this.routeData.route === "/404" || this.routeData.route === "/500") {
293
- response2.headers.set(REROUTE_DIRECTIVE_HEADER, "no");
294
- }
295
- if (this.isRewriting) {
296
- response2.headers.set(REWRITE_DIRECTIVE_HEADER_KEY, REWRITE_DIRECTIVE_HEADER_VALUE);
297
- }
298
- break;
299
- }
300
- case "fallback": {
301
- return new Response(null, { status: 500, headers: { [ROUTE_TYPE_HEADER]: "fallback" } });
302
- }
303
- }
304
- const responseCookies = getCookiesFromResponse(response2);
305
- if (responseCookies) {
306
- this.cookies.merge(responseCookies);
307
- }
308
- return response2;
309
- };
310
- if (isRouteExternalRedirect(this.routeData)) {
311
- return renderRedirect(this);
312
- }
313
- const response = this.skipMiddleware ? await lastNext(apiContext) : await callMiddleware(middleware, apiContext, lastNext);
314
- if (response.headers.get(ROUTE_TYPE_HEADER)) {
315
- response.headers.delete(ROUTE_TYPE_HEADER);
316
- }
317
- attachCookiesToResponse(response, this.cookies);
318
- return response;
319
- }
320
- createAPIContext(props, context) {
321
- const redirect = (path, status = 302) => new Response(null, { status, headers: { Location: path } });
322
- const rewrite = async (reroutePayload) => {
323
- return await this.#executeRewrite(reroutePayload);
324
- };
325
- Reflect.set(context, pipelineSymbol, this.pipeline);
326
- return Object.assign(context, {
327
- props,
328
- redirect,
329
- rewrite,
330
- getActionResult: createGetActionResult(context.locals),
331
- callAction: createCallAction(context)
332
- });
333
- }
334
- async #executeRewrite(reroutePayload) {
335
- this.pipeline.logger.debug("router", "Calling rewrite: ", reroutePayload);
336
- const oldPathname = this.pathname;
337
- const { routeData, componentInstance, newUrl, pathname } = await this.pipeline.tryRewrite(
338
- reroutePayload,
339
- this.request
340
- );
341
- const isI18nFallback = routeData.fallbackRoutes && routeData.fallbackRoutes.length > 0;
342
- if (this.pipeline.manifest.serverLike && !this.routeData.prerender && routeData.prerender && !isI18nFallback) {
343
- throw new AstroError({
344
- ...ForbiddenRewrite,
345
- message: ForbiddenRewrite.message(this.pathname, pathname, routeData.component),
346
- hint: ForbiddenRewrite.hint(routeData.component)
347
- });
348
- }
349
- this.routeData = routeData;
350
- if (reroutePayload instanceof Request) {
351
- this.request = reroutePayload;
352
- } else {
353
- this.request = copyRequest(
354
- newUrl,
355
- this.request,
356
- // need to send the flag of the previous routeData
357
- routeData.prerender,
358
- this.pipeline.logger,
359
- this.routeData.route
360
- );
361
- }
362
- this.url = RenderContext.#createNormalizedUrl(this.request.url);
363
- const newCookies = new AstroCookies(this.request);
364
- if (this.cookies) {
365
- newCookies.merge(this.cookies);
366
- }
367
- this.cookies = newCookies;
368
- this.params = getParams(routeData, pathname);
369
- this.pathname = pathname;
370
- this.isRewriting = true;
371
- this.status = 200;
372
- setOriginPathname(
373
- this.request,
374
- oldPathname,
375
- this.pipeline.manifest.trailingSlash,
376
- this.pipeline.manifest.buildFormat
377
- );
378
- return await this.render(componentInstance);
379
- }
380
- createActionAPIContext() {
381
- const renderContext = this;
382
- const { params, pipeline, url } = this;
383
- return {
384
- // Don't allow reassignment of cookies because it doesn't work
385
- get cookies() {
386
- return renderContext.cookies;
387
- },
388
- routePattern: this.routeData.route,
389
- isPrerendered: this.routeData.prerender,
390
- get clientAddress() {
391
- return renderContext.getClientAddress();
392
- },
393
- get currentLocale() {
394
- return renderContext.computeCurrentLocale();
395
- },
396
- generator: ASTRO_GENERATOR,
397
- get locals() {
398
- return renderContext.locals;
399
- },
400
- set locals(_) {
401
- throw new AstroError(AstroErrorData.LocalsReassigned);
402
- },
403
- params,
404
- get preferredLocale() {
405
- return renderContext.computePreferredLocale();
406
- },
407
- get preferredLocaleList() {
408
- return renderContext.computePreferredLocaleList();
409
- },
410
- request: this.request,
411
- site: pipeline.site,
412
- url,
413
- get originPathname() {
414
- return getOriginPathname(renderContext.request);
415
- },
416
- get session() {
417
- if (this.isPrerendered) {
418
- pipeline.logger.warn(
419
- "session",
420
- `context.session was used when rendering the route ${colors.green(this.routePattern)}, but it is not available on prerendered routes. If you need access to sessions, make sure that the route is server-rendered using \`export const prerender = false;\` or by setting \`output\` to \`"server"\` in your Astro config to make all your routes server-rendered by default. For more information, see https://docs.astro.build/en/guides/sessions/`
421
- );
422
- return void 0;
423
- }
424
- if (!renderContext.session) {
425
- pipeline.logger.warn(
426
- "session",
427
- `context.session was used when rendering the route ${colors.green(this.routePattern)}, but no storage configuration was provided. Either configure the storage manually or use an adapter that provides session storage. For more information, see https://docs.astro.build/en/guides/sessions/`
428
- );
429
- return void 0;
430
- }
431
- return renderContext.session;
432
- },
433
- get cache() {
434
- return renderContext.cache;
435
- },
436
- get csp() {
437
- if (!pipeline.manifest.csp) {
438
- if (pipeline.runtimeMode === "production") {
439
- pipeline.logger.warn(
440
- "csp",
441
- `context.csp was used when rendering the route ${colors.green(this.routePattern)}, but CSP was not configured. For more information, see https://docs.astro.build/en/reference/experimental-flags/csp/`
442
- );
443
- }
444
- return void 0;
445
- }
446
- return {
447
- insertDirective(payload) {
448
- if (renderContext?.result?.directives) {
449
- renderContext.result.directives = pushDirective(
450
- renderContext.result.directives,
451
- payload
452
- );
453
- } else {
454
- renderContext?.result?.directives.push(payload);
455
- }
456
- },
457
- insertScriptResource(resource) {
458
- renderContext.result?.scriptResources.push(resource);
459
- },
460
- insertStyleResource(resource) {
461
- renderContext.result?.styleResources.push(resource);
462
- },
463
- insertStyleHash(hash) {
464
- renderContext.result?.styleHashes.push(hash);
465
- },
466
- insertScriptHash(hash) {
467
- renderContext.result?.scriptHashes.push(hash);
468
- }
469
- };
470
- },
471
- get logger() {
472
- if (!pipeline.manifest.experimentalLogger) {
473
- pipeline.logger.warn(
474
- null,
475
- "The Astro.logger is available only when experimental.logger is defined."
476
- );
477
- return void 0;
478
- }
479
- return {
480
- info(msg) {
481
- pipeline.logger.info(null, msg);
482
- },
483
- warn(msg) {
484
- pipeline.logger.warn(null, msg);
485
- },
486
- error(msg) {
487
- pipeline.logger.error(null, msg);
488
- }
489
- };
490
- }
491
- };
492
- }
493
- async createResult(mod, ctx) {
494
- const { cookies, pathname, pipeline, routeData, status } = this;
495
- const { clientDirectives, inlinedScripts, compressHTML, manifest, renderers, resolve } = pipeline;
496
- const { links, scripts, styles } = await pipeline.headElements(routeData);
497
- const extraStyleHashes = [];
498
- const extraScriptHashes = [];
499
- const shouldInjectCspMetaTags = this.shouldInjectCspMetaTags;
500
- const cspAlgorithm = manifest.csp?.algorithm ?? "SHA-256";
501
- if (shouldInjectCspMetaTags) {
502
- for (const style of styles) {
503
- extraStyleHashes.push(await generateCspDigest(style.children, cspAlgorithm));
504
- }
505
- for (const script of scripts) {
506
- extraScriptHashes.push(await generateCspDigest(script.children, cspAlgorithm));
507
- }
508
- }
509
- const componentMetadata = await pipeline.componentMetadata(routeData) ?? manifest.componentMetadata;
510
- const headers = new Headers({ "Content-Type": "text/html" });
511
- const partial = typeof this.partial === "boolean" ? this.partial : Boolean(mod.partial);
512
- const actionResult = hasActionPayload(this.locals) ? deserializeActionResult(this.locals._actionPayload.actionResult) : void 0;
513
- const response = {
514
- status: actionResult?.error ? actionResult?.error.status : status,
515
- statusText: actionResult?.error ? actionResult?.error.type : "OK",
516
- get headers() {
517
- return headers;
518
- },
519
- // Disallow `Astro.response.headers = new Headers`
520
- set headers(_) {
521
- throw new AstroError(AstroErrorData.AstroResponseHeadersReassigned);
522
- }
523
- };
524
- const result = {
525
- base: manifest.base,
526
- userAssetsBase: manifest.userAssetsBase,
527
- cancelled: false,
528
- clientDirectives,
529
- inlinedScripts,
530
- componentMetadata,
531
- compressHTML,
532
- cookies,
533
- /** This function returns the `Astro` faux-global */
534
- createAstro: (props, slots) => this.createAstro(result, props, slots, ctx),
535
- links,
536
- params: this.params,
537
- partial,
538
- pathname,
539
- renderers,
540
- resolve,
541
- response,
542
- request: this.request,
543
- scripts,
544
- styles,
545
- actionResult,
546
- serverIslandNameMap: this.serverIslands.serverIslandNameMap ?? /* @__PURE__ */ new Map(),
547
- key: manifest.key,
548
- trailingSlash: manifest.trailingSlash,
549
- _experimentalQueuedRendering: {
550
- pool: pipeline.nodePool,
551
- htmlStringCache: pipeline.htmlStringCache,
552
- enabled: manifest.experimentalQueuedRendering?.enabled,
553
- poolSize: manifest.experimentalQueuedRendering?.poolSize,
554
- contentCache: manifest.experimentalQueuedRendering?.contentCache
555
- },
556
- _metadata: {
557
- hasHydrationScript: false,
558
- rendererSpecificHydrationScripts: /* @__PURE__ */ new Set(),
559
- hasRenderedHead: false,
560
- renderedScripts: /* @__PURE__ */ new Set(),
561
- hasDirectives: /* @__PURE__ */ new Set(),
562
- hasRenderedServerIslandRuntime: false,
563
- headInTree: false,
564
- extraHead: [],
565
- extraStyleHashes,
566
- extraScriptHashes,
567
- propagators: /* @__PURE__ */ new Set(),
568
- templateDepth: 0
569
- },
570
- cspDestination: manifest.csp?.cspDestination ?? (routeData.prerender ? "meta" : "header"),
571
- shouldInjectCspMetaTags,
572
- cspAlgorithm,
573
- // The following arrays must be cloned; otherwise, they become mutable across routes.
574
- scriptHashes: manifest.csp?.scriptHashes ? [...manifest.csp.scriptHashes] : [],
575
- scriptResources: manifest.csp?.scriptResources ? [...manifest.csp.scriptResources] : [],
576
- styleHashes: manifest.csp?.styleHashes ? [...manifest.csp.styleHashes] : [],
577
- styleResources: manifest.csp?.styleResources ? [...manifest.csp.styleResources] : [],
578
- directives: manifest.csp?.directives ? [...manifest.csp.directives] : [],
579
- isStrictDynamic: manifest.csp?.isStrictDynamic ?? false,
580
- internalFetchHeaders: manifest.internalFetchHeaders
581
- };
582
- return result;
583
- }
584
- #astroPagePartial;
585
- /**
586
- * The Astro global is sourced in 3 different phases:
587
- * - **Static**: `.generator` and `.glob` is printed by the compiler, instantiated once per process per astro file
588
- * - **Page-level**: `.request`, `.cookies`, `.locals` etc. These remain the same for the duration of the request.
589
- * - **Component-level**: `.props`, `.slots`, and `.self` are unique to each _use_ of each component.
590
- *
591
- * 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.
592
- */
593
- createAstro(result, props, slotValues, apiContext) {
594
- let astroPagePartial;
595
- if (this.isRewriting) {
596
- astroPagePartial = this.#astroPagePartial = this.createAstroPagePartial(result, apiContext);
597
- } else {
598
- astroPagePartial = this.#astroPagePartial ??= this.createAstroPagePartial(result, apiContext);
599
- }
600
- const astroComponentPartial = { props, self: null };
601
- const Astro = Object.assign(
602
- Object.create(astroPagePartial),
603
- astroComponentPartial
604
- );
605
- let _slots;
606
- Object.defineProperty(Astro, "slots", {
607
- get: () => {
608
- if (!_slots) {
609
- _slots = new Slots(
610
- result,
611
- slotValues,
612
- this.pipeline.logger
613
- );
614
- }
615
- return _slots;
616
- }
617
- });
618
- return Astro;
619
- }
620
- createAstroPagePartial(result, apiContext) {
621
- const renderContext = this;
622
- const { cookies, locals, params, pipeline, url } = this;
623
- const { response } = result;
624
- const redirect = (path, status = 302) => {
625
- if (this.request[responseSentSymbol]) {
626
- throw new AstroError({
627
- ...AstroErrorData.ResponseSentError
628
- });
629
- }
630
- return new Response(null, { status, headers: { Location: path } });
631
- };
632
- const rewrite = async (reroutePayload) => {
633
- return await this.#executeRewrite(reroutePayload);
634
- };
635
- const callAction = createCallAction(apiContext);
636
- return {
637
- generator: ASTRO_GENERATOR,
638
- routePattern: this.routeData.route,
639
- isPrerendered: this.routeData.prerender,
640
- cookies,
641
- get session() {
642
- if (this.isPrerendered) {
643
- pipeline.logger.warn(
644
- "session",
645
- `Astro.session was used when rendering the route ${colors.green(this.routePattern)}, but it is not available on prerendered pages. If you need access to sessions, make sure that the page is server-rendered using \`export const prerender = false;\` or by setting \`output\` to \`"server"\` in your Astro config to make all your pages server-rendered by default. For more information, see https://docs.astro.build/en/guides/sessions/`
646
- );
647
- return void 0;
648
- }
649
- if (!renderContext.session) {
650
- pipeline.logger.warn(
651
- "session",
652
- `Astro.session was used when rendering the route ${colors.green(this.routePattern)}, but no storage configuration was provided. Either configure the storage manually or use an adapter that provides session storage. For more information, see https://docs.astro.build/en/guides/sessions/`
653
- );
654
- return void 0;
655
- }
656
- return renderContext.session;
657
- },
658
- get cache() {
659
- return renderContext.cache;
660
- },
661
- get clientAddress() {
662
- return renderContext.getClientAddress();
663
- },
664
- get currentLocale() {
665
- return renderContext.computeCurrentLocale();
666
- },
667
- params,
668
- get preferredLocale() {
669
- return renderContext.computePreferredLocale();
670
- },
671
- get preferredLocaleList() {
672
- return renderContext.computePreferredLocaleList();
673
- },
674
- locals,
675
- redirect,
676
- rewrite,
677
- request: this.request,
678
- response,
679
- site: pipeline.site,
680
- getActionResult: createGetActionResult(locals),
681
- get callAction() {
682
- return callAction;
683
- },
684
- url,
685
- get originPathname() {
686
- return getOriginPathname(renderContext.request);
687
- },
688
- get csp() {
689
- if (!pipeline.manifest.csp) {
690
- if (pipeline.runtimeMode === "production") {
691
- pipeline.logger.warn(
692
- "csp",
693
- `Astro.csp was used when rendering the route ${colors.green(this.routePattern)}, but CSP was not configured. For more information, see https://docs.astro.build/en/reference/experimental-flags/csp/`
694
- );
695
- }
696
- return void 0;
697
- }
698
- return {
699
- insertDirective(payload) {
700
- if (renderContext?.result?.directives) {
701
- renderContext.result.directives = pushDirective(
702
- renderContext.result.directives,
703
- payload
704
- );
705
- } else {
706
- renderContext?.result?.directives.push(payload);
707
- }
708
- },
709
- insertScriptResource(resource) {
710
- renderContext.result?.scriptResources.push(resource);
711
- },
712
- insertStyleResource(resource) {
713
- renderContext.result?.styleResources.push(resource);
714
- },
715
- insertStyleHash(hash) {
716
- renderContext.result?.styleHashes.push(hash);
717
- },
718
- insertScriptHash(hash) {
719
- renderContext.result?.scriptHashes.push(hash);
720
- }
721
- };
722
- },
723
- get logger() {
724
- return {
725
- info(msg) {
726
- pipeline.logger.info(null, msg);
727
- },
728
- warn(msg) {
729
- pipeline.logger.warn(null, msg);
730
- },
731
- error(msg) {
732
- pipeline.logger.error(null, msg);
733
- }
734
- };
735
- }
736
- };
737
- }
738
- getClientAddress() {
739
- const { pipeline, routeData, clientAddress } = this;
740
- if (routeData.prerender) {
741
- throw new AstroError({
742
- ...AstroErrorData.PrerenderClientAddressNotAvailable,
743
- message: AstroErrorData.PrerenderClientAddressNotAvailable.message(routeData.component)
744
- });
745
- }
746
- if (clientAddress) {
747
- return clientAddress;
748
- }
749
- if (pipeline.adapterName) {
750
- throw new AstroError({
751
- ...AstroErrorData.ClientAddressNotAvailable,
752
- message: AstroErrorData.ClientAddressNotAvailable.message(pipeline.adapterName)
753
- });
754
- }
755
- throw new AstroError(AstroErrorData.StaticClientAddressNotAvailable);
756
- }
757
- /**
758
- * API Context may be created multiple times per request, i18n data needs to be computed only once.
759
- * So, it is computed and saved here on creation of the first APIContext and reused for later ones.
760
- */
761
- #currentLocale;
762
- computeCurrentLocale() {
763
- const {
764
- url,
765
- pipeline: { i18n },
766
- routeData
767
- } = this;
768
- if (!i18n) return;
769
- const { defaultLocale, locales, strategy } = i18n;
770
- const fallbackTo = strategy === "pathname-prefix-other-locales" || strategy === "domains-prefix-other-locales" ? defaultLocale : void 0;
771
- if (this.#currentLocale) {
772
- return this.#currentLocale;
773
- }
774
- let computedLocale;
775
- if (isRouteServerIsland(routeData)) {
776
- let referer = this.request.headers.get("referer");
777
- if (referer) {
778
- if (URL.canParse(referer)) {
779
- referer = new URL(referer).pathname;
780
- }
781
- computedLocale = computeCurrentLocale(referer, locales, defaultLocale);
782
- }
783
- } else {
784
- let pathname = routeData.pathname;
785
- if (!routeData.pattern.test(url.pathname)) {
786
- for (const fallbackRoute of routeData.fallbackRoutes) {
787
- if (fallbackRoute.pattern.test(url.pathname)) {
788
- pathname = fallbackRoute.pathname;
789
- break;
790
- }
791
- }
792
- }
793
- pathname = pathname && !isRoute404or500(routeData) ? pathname : url.pathname;
794
- computedLocale = computeCurrentLocale(pathname, locales, defaultLocale);
795
- if (routeData.params.length > 0) {
796
- const localeFromParams = computeCurrentLocaleFromParams(this.params, locales);
797
- if (localeFromParams) {
798
- computedLocale = localeFromParams;
799
- }
800
- }
801
- }
802
- this.#currentLocale = computedLocale ?? fallbackTo;
803
- return this.#currentLocale;
804
- }
805
- #preferredLocale;
806
- computePreferredLocale() {
807
- const {
808
- pipeline: { i18n },
809
- request
810
- } = this;
811
- if (!i18n) return;
812
- return this.#preferredLocale ??= computePreferredLocale(request, i18n.locales);
813
- }
814
- #preferredLocaleList;
815
- computePreferredLocaleList() {
816
- const {
817
- pipeline: { i18n },
818
- request
819
- } = this;
820
- if (!i18n) return;
821
- return this.#preferredLocaleList ??= computePreferredLocaleList(request, i18n.locales);
822
- }
823
- }
824
- export {
825
- RenderContext
826
- };