@patternfly/patternfly-doc-core 1.9.1 → 1.11.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 (118) hide show
  1. package/astro.config.mjs +3 -4
  2. package/cli/cli.ts +60 -19
  3. package/cli/convertToMDX.ts +77 -22
  4. package/dist/.assetsignore +2 -0
  5. package/dist/_astro/ClientRouter.astro_astro_type_script_index_0_lang.CtSceO8m.js +1 -0
  6. package/dist/{client/_astro/LiveExample.DZkxbJA_.js → _astro/LiveExample.DjPiO80i.js} +1 -1
  7. package/dist/_astro/client.DN8ES6L5.js +1 -0
  8. package/dist/_routes.json +20 -0
  9. package/dist/_worker.js/_@astrojs-ssr-adapter.mjs +2 -0
  10. package/dist/_worker.js/_astro-internal_middleware.mjs +21 -0
  11. package/dist/_worker.js/_noop-actions.mjs +4 -0
  12. package/dist/{server/chunks/AutoLinkHeader_C2GD0g-K.mjs → _worker.js/chunks/AutoLinkHeader_xh_mBOfs.mjs} +13 -14
  13. package/dist/{server/chunks/Button_BKhHR-ak.mjs → _worker.js/chunks/Button_ByndGYyw.mjs} +83 -13
  14. package/dist/{server/chunks/CSSTable_B8tlH3gz.mjs → _worker.js/chunks/CSSTable_DAbso55e.mjs} +3 -3
  15. package/dist/_worker.js/chunks/PropsTables_BZngJp47.mjs +6628 -0
  16. package/dist/_worker.js/chunks/_@astrojs-ssr-adapter_C9Nk07-M.mjs +1082 -0
  17. package/dist/_worker.js/chunks/angle-down-icon_yt3z9cvI.mjs +3686 -0
  18. package/dist/_worker.js/chunks/astro/server_BpfPtTmt.mjs +7278 -0
  19. package/dist/_worker.js/chunks/astro-designed-error-pages_4xWqsa9_.mjs +928 -0
  20. package/dist/_worker.js/chunks/cloudflare-kv-binding_DMly_2Gl.mjs +107 -0
  21. package/dist/_worker.js/chunks/index_Dc2aKkl4.mjs +57 -0
  22. package/dist/{server/chunks/_@astrojs-ssr-adapter_CbICuCdt.mjs → _worker.js/chunks/index_DlGha6WC.mjs} +1295 -1817
  23. package/dist/_worker.js/chunks/noop-middleware_Ct44Kk5Y.mjs +10 -0
  24. package/dist/_worker.js/chunks/parse_EttCPxrw.mjs +271 -0
  25. package/dist/{server/chunks/path_Cvt6sEOY.mjs → _worker.js/chunks/path_C-ZOwaTP.mjs} +2 -1
  26. package/dist/{server/entry.mjs → _worker.js/index.js} +12 -19
  27. package/dist/_worker.js/manifest_DcBPbZXQ.mjs +100 -0
  28. package/dist/_worker.js/pages/_image.astro.mjs +24 -0
  29. package/dist/_worker.js/pages/_section_/_page_/_---tab_.astro.mjs +1 -0
  30. package/dist/_worker.js/pages/index.astro.mjs +1 -0
  31. package/dist/{server → _worker.js}/pages/props.astro.mjs +3 -2
  32. package/dist/_worker.js/renderers.mjs +484 -0
  33. package/dist/cli/cli.js +46 -12
  34. package/dist/cli/convertToMDX.js +53 -16
  35. package/dist/components/accordion/index.html +60 -0
  36. package/dist/components/accordion/react/index.html +60 -0
  37. package/dist/components/all-components/index.html +47 -0
  38. package/dist/design-foundations/typography/index.html +198 -0
  39. package/dist/{client/design-foundations → design-foundations}/usage-and-behavior/index.html +4 -54
  40. package/dist/get-started/contribute/index.html +94 -0
  41. package/dist/index.html +43 -0
  42. package/package.json +12 -8
  43. package/public/.assetsignore +2 -0
  44. package/src/components/LiveExample.astro +2 -2
  45. package/src/components/LiveExample.tsx +38 -9
  46. package/src/pages/props.ts +2 -2
  47. package/wrangler.jsonc +14 -0
  48. package/dist/client/_astro/ClientRouter.astro_astro_type_script_index_0_lang.Cainpjm5.js +0 -1
  49. package/dist/client/_astro/client.zs76E0tG.js +0 -1
  50. package/dist/client/components/accordion/index.html +0 -110
  51. package/dist/client/components/accordion/react/index.html +0 -110
  52. package/dist/client/components/all-components/index.html +0 -97
  53. package/dist/client/design-foundations/typography/index.html +0 -248
  54. package/dist/client/get-started/contribute/index.html +0 -144
  55. package/dist/client/index.html +0 -43
  56. package/dist/server/_@astrojs-ssr-adapter.mjs +0 -1
  57. package/dist/server/_noop-middleware.mjs +0 -3
  58. package/dist/server/chunks/PropsTables_PVzRHJNB.mjs +0 -1750
  59. package/dist/server/chunks/_astro_assets_DaYumpRZ.mjs +0 -1507
  60. package/dist/server/chunks/angle-down-icon_BO1Ed-9Z.mjs +0 -3288
  61. package/dist/server/chunks/astro/server_Cl9jPh4p.mjs +0 -2859
  62. package/dist/server/chunks/astro-designed-error-pages_BFveJFnQ.mjs +0 -282
  63. package/dist/server/chunks/consts_BmVDRGlB.mjs +0 -32
  64. package/dist/server/chunks/sharp_CbOL3WDk.mjs +0 -88
  65. package/dist/server/manifest_DxJLmW-j.mjs +0 -102
  66. package/dist/server/pages/_image.astro.mjs +0 -132
  67. package/dist/server/renderers.mjs +0 -308
  68. /package/dist/{client/PF-HorizontalLogo-Color.svg → PF-HorizontalLogo-Color.svg} +0 -0
  69. /package/dist/{client/PF-HorizontalLogo-Reverse.svg → PF-HorizontalLogo-Reverse.svg} +0 -0
  70. /package/dist/{client/_astro → _astro}/Button.BQCwQ5pE.js +0 -0
  71. /package/dist/{client/_astro → _astro}/CSSTable.DC79W1Ct.js +0 -0
  72. /package/dist/{client/_astro → _astro}/Content.B4M2qzJY.js +0 -0
  73. /package/dist/{client/_astro → _astro}/DropdownList.cxp03sS4.js +0 -0
  74. /package/dist/{client/_astro → _astro}/LiveExample.CxJsMvEq.css +0 -0
  75. /package/dist/{client/_astro → _astro}/Navigation.kbLxctIo.js +0 -0
  76. /package/dist/{client/_astro → _astro}/PageContext.miTsIqVo.js +0 -0
  77. /package/dist/{client/_astro → _astro}/PageSidebarBody.B0AJe8Hg.js +0 -0
  78. /package/dist/{client/_astro → _astro}/PageToggle.CMZ3C1v1.js +0 -0
  79. /package/dist/{client/_astro → _astro}/RedHatDisplayVF-Italic.CRpusWc8.woff2 +0 -0
  80. /package/dist/{client/_astro → _astro}/RedHatDisplayVF.CYDHf1NI.woff2 +0 -0
  81. /package/dist/{client/_astro → _astro}/RedHatMonoVF-Italic.DGQo2ogW.woff2 +0 -0
  82. /package/dist/{client/_astro → _astro}/RedHatMonoVF.C4fMH6Vz.woff2 +0 -0
  83. /package/dist/{client/_astro → _astro}/RedHatTextVF-Italic.Dkj_WqbA.woff2 +0 -0
  84. /package/dist/{client/_astro → _astro}/RedHatTextVF.wYvZ7prR.woff2 +0 -0
  85. /package/dist/{client/_astro → _astro}/SearchInput.DhHo7yPx.js +0 -0
  86. /package/dist/{client/_astro → _astro}/SectionGallery.3ABpQwE4.js +0 -0
  87. /package/dist/{client/_astro → _astro}/Toolbar.CroDQcyv.js +0 -0
  88. /package/dist/{client/_astro → _astro}/ToolbarContent.UH3ZRlHp.js +0 -0
  89. /package/dist/{client/_astro → _astro}/_page_.Chv_bGyU.css +0 -0
  90. /package/dist/{client/_astro → _astro}/_page_.CtheD08_.css +0 -0
  91. /package/dist/{client/_astro → _astro}/_page_.D1z73Byz.css +0 -0
  92. /package/dist/{client/_astro → _astro}/_page_.DxJDkZPc.css +0 -0
  93. /package/dist/{client/_astro → _astro}/angle-left-icon.teo8GC0v.js +0 -0
  94. /package/dist/{client/_astro → _astro}/bars-icon.Dk6ua1rr.js +0 -0
  95. /package/dist/{client/_astro → _astro}/divider.tlrBPkzg.js +0 -0
  96. /package/dist/{client/_astro → _astro}/fa-solid-900.DguXoeIz.woff2 +0 -0
  97. /package/dist/{client/_astro → _astro}/github-icon.ByC5XEPt.js +0 -0
  98. /package/dist/{client/_astro → _astro}/index.BQFV5hT1.js +0 -0
  99. /package/dist/{client/_astro → _astro}/index.CAChmxYj.js +0 -0
  100. /package/dist/{client/_astro → _astro}/index.DYVB4vTo.js +0 -0
  101. /package/dist/{client/_astro → _astro}/index.eCxJ45ll.js +0 -0
  102. /package/dist/{client/_astro → _astro}/link-icon.BNHnRn73.js +0 -0
  103. /package/dist/{client/_astro → _astro}/page.BTC3Kf3x.js +0 -0
  104. /package/dist/{client/_astro → _astro}/pf-v6-pficon.Dy6oiu9u.woff2 +0 -0
  105. /package/dist/{server/chunks/Accordion_BJka4Qvb.mjs → _worker.js/chunks/Accordion_BNafbla6.mjs} +0 -0
  106. /package/dist/{server/chunks/Accordion_BQIphkaZ.mjs → _worker.js/chunks/Accordion_CZsuyu9E.mjs} +0 -0
  107. /package/dist/{server/chunks/AllComponents_CRhgTsiT.mjs → _worker.js/chunks/AllComponents_BrL9IHSc.mjs} +0 -0
  108. /package/dist/{server/chunks/AllComponents_CjOtwUH6.mjs → _worker.js/chunks/AllComponents_CI7S6uwA.mjs} +0 -0
  109. /package/dist/{server/chunks/_astro_data-layer-content_D4Ib_RjR.mjs → _worker.js/chunks/_astro_assets_vBCb4v6U.mjs} +0 -0
  110. /package/dist/{server/chunks/content-assets_DleWbedO.mjs → _worker.js/chunks/_astro_data-layer-content_CgXoS6Mm.mjs} +0 -0
  111. /package/dist/{server/chunks/content-modules_fX1c2JRG.mjs → _worker.js/chunks/content-assets_XqCgPAV2.mjs} +0 -0
  112. /package/dist/{server/pages/_section_/_---page_.astro.mjs → _worker.js/chunks/content-modules_CKq2j9RQ.mjs} +0 -0
  113. /package/dist/{server/pages/_section_/_page_/_---tab_.astro.mjs → _worker.js/chunks/sharp_CNjr3bU4.mjs} +0 -0
  114. /package/dist/{server/pages/index.astro.mjs → _worker.js/pages/_section_/_---page_.astro.mjs} +0 -0
  115. /package/dist/{client/avatarImg.svg → avatarImg.svg} +0 -0
  116. /package/dist/{client/avatarImgDark.svg → avatarImgDark.svg} +0 -0
  117. /package/dist/{client/content → content}/typography/line-height.png +0 -0
  118. /package/dist/{client/favicon.svg → favicon.svg} +0 -0
@@ -1,24 +1,34 @@
1
- import { t as decryptString, v as createSlotValueFromString, w as isAstroComponentFactory, r as renderComponent, b as renderTemplate, x as ROUTE_TYPE_HEADER, y as REROUTE_DIRECTIVE_HEADER, A as AstroError, z as i18nNoLocaleFoundInPath, B as ResponseSentError, M as MiddlewareNoDataOrNextCalled, C as MiddlewareNotAResponse, D as originPathnameSymbol, E as RewriteWithBodyUsed, G as GetStaticPathsRequired, I as InvalidGetStaticPathsReturn, F as InvalidGetStaticPathsEntry, H as GetStaticPathsExpectedParams, J as GetStaticPathsInvalidRouteParam, P as PageNumberParamNotFound, K as DEFAULT_404_COMPONENT, N as NoMatchingStaticPathFound, L as PrerenderDynamicEndpointPathCollide, O as ReservedSlotName, Q as renderSlotToString, o as renderJSX, S as chunkToString, T as isRenderInstruction, V as ForbiddenRewrite, W as SessionStorageSaveError, X as SessionStorageInitError, Y as ASTRO_VERSION, Z as LocalsReassigned, _ as PrerenderClientAddressNotAvailable, $ as clientAddressSymbol, a0 as ClientAddressNotAvailable, a1 as StaticClientAddressNotAvailable, a2 as AstroResponseHeadersReassigned, a3 as responseSentSymbol$1, a4 as renderPage, a5 as REWRITE_DIRECTIVE_HEADER_KEY, a6 as REWRITE_DIRECTIVE_HEADER_VALUE, a7 as renderEndpoint, a8 as LocalsNotAnObject, a9 as REROUTABLE_STATUS_CODES } from './astro/server_Cl9jPh4p.mjs';
2
- import { bold, red, yellow, dim, blue } from 'kleur/colors';
3
- import 'clsx';
4
- import { serialize, parse } from 'cookie';
5
- import { g as getActionQueryString, d as deserializeActionResult, D as DEFAULT_404_ROUTE, a as default404Instance, N as NOOP_MIDDLEWARE_FN, e as ensure404Route } from './astro-designed-error-pages_BFveJFnQ.mjs';
6
- import 'es-module-lexer';
7
- import buffer from 'node:buffer';
8
- import crypto$1 from 'node:crypto';
9
- import { Http2ServerResponse } from 'node:http2';
10
- import { a as appendForwardSlash$1, j as joinPaths, b as removeTrailingForwardSlash, p as prependForwardSlash$1, t as trimSlashes, f as fileExtension, s as slash, c as collapseDuplicateTrailingSlashes, h as hasFileExtension$1 } from './path_Cvt6sEOY.mjs';
11
- import { unflatten as unflatten$1, stringify as stringify$1 } from 'devalue';
12
- import { createStorage, builtinDrivers } from 'unstorage';
13
- import { AsyncLocalStorage } from 'node:async_hooks';
14
- import fs from 'node:fs';
15
- import http from 'node:http';
16
- import https from 'node:https';
17
- import enableDestroy from 'server-destroy';
18
- import os from 'node:os';
19
- import path from 'node:path';
20
- import url from 'node:url';
21
- import send from 'send';
1
+ globalThis.process ??= {}; globalThis.process.env ??= {};
2
+ import { g as getActionQueryString, a as deserializeActionResult, b as distExports, D as DEFAULT_404_ROUTE, A as ActionError, s as serializeActionResult, c as ACTION_RPC_ROUTE_PATTERN, f as ACTION_QUERY_PARAMS, h as stringify$2 } from './astro-designed-error-pages_4xWqsa9_.mjs';
3
+ import { J as decryptString, K as createSlotValueFromString, M as isAstroComponentFactory, r as renderComponent, b as renderTemplate, x as REROUTE_DIRECTIVE_HEADER, A as AstroError, N as i18nNoLocaleFoundInPath, O as ResponseSentError, P as originPathnameSymbol, Q as RewriteWithBodyUsed, S as MiddlewareNoDataOrNextCalled, T as MiddlewareNotAResponse, V as GetStaticPathsRequired, W as InvalidGetStaticPathsReturn, X as InvalidGetStaticPathsEntry, Y as GetStaticPathsExpectedParams, Z as GetStaticPathsInvalidRouteParam, _ as PageNumberParamNotFound, D as DEFAULT_404_COMPONENT, $ as NoMatchingStaticPathFound, a0 as PrerenderDynamicEndpointPathCollide, a1 as ReservedSlotName, a2 as renderSlotToString, q as renderJSX, a3 as chunkToString, a4 as isRenderInstruction, a5 as SessionStorageSaveError, a6 as SessionStorageInitError, w as ROUTE_TYPE_HEADER, a7 as ForbiddenRewrite, a8 as ASTRO_VERSION, a9 as CspNotEnabled, aa as green, ab as LocalsReassigned, ac as PrerenderClientAddressNotAvailable, G as clientAddressSymbol, ad as ClientAddressNotAvailable, ae as StaticClientAddressNotAvailable, af as AstroResponseHeadersReassigned, I as responseSentSymbol$1, ag as renderPage, ah as REWRITE_DIRECTIVE_HEADER_KEY, ai as REWRITE_DIRECTIVE_HEADER_VALUE, aj as renderEndpoint } from './astro/server_BpfPtTmt.mjs';
4
+ import { b as appendForwardSlash, j as joinPaths, a as removeTrailingForwardSlash, p as prependForwardSlash, t as trimSlashes } from './path_C-ZOwaTP.mjs';
5
+ import { u as unflatten$1 } from './parse_EttCPxrw.mjs';
6
+
7
+ const ACTION_API_CONTEXT_SYMBOL = Symbol.for("astro.actionAPIContext");
8
+ const formContentTypes = ["application/x-www-form-urlencoded", "multipart/form-data"];
9
+ function hasContentType(contentType, expected) {
10
+ const type = contentType.split(";")[0].toLowerCase();
11
+ return expected.some((t) => type === t);
12
+ }
13
+
14
+ function hasActionPayload(locals) {
15
+ return "_actionPayload" in locals;
16
+ }
17
+ function createGetActionResult(locals) {
18
+ return (actionFn) => {
19
+ if (!hasActionPayload(locals) || actionFn.toString() !== getActionQueryString(locals._actionPayload.actionName)) {
20
+ return void 0;
21
+ }
22
+ return deserializeActionResult(locals._actionPayload.actionResult);
23
+ };
24
+ }
25
+ function createCallAction(context) {
26
+ return (baseAction, input) => {
27
+ Reflect.set(context, ACTION_API_CONTEXT_SYMBOL, true);
28
+ const action = baseAction.bind(context);
29
+ return action(input);
30
+ };
31
+ }
22
32
 
23
33
  function shouldAppendForwardSlash(trailingSlash, buildFormat) {
24
34
  switch (trailingSlash) {
@@ -211,125 +221,6 @@ function isRouteExternalRedirect(route) {
211
221
  return !!(route.type === "redirect" && route.redirect && redirectIsExternal(route.redirect));
212
222
  }
213
223
 
214
- function createI18nMiddleware(i18n, base, trailingSlash, format) {
215
- if (!i18n) return (_, next) => next();
216
- const payload = {
217
- ...i18n,
218
- trailingSlash,
219
- base,
220
- format};
221
- const _redirectToDefaultLocale = redirectToDefaultLocale(payload);
222
- const _noFoundForNonLocaleRoute = notFound(payload);
223
- const _requestHasLocale = requestHasLocale(payload.locales);
224
- const _redirectToFallback = redirectToFallback(payload);
225
- const prefixAlways = (context, response) => {
226
- const url = context.url;
227
- if (url.pathname === base + "/" || url.pathname === base) {
228
- return _redirectToDefaultLocale(context);
229
- } else if (!_requestHasLocale(context)) {
230
- return _noFoundForNonLocaleRoute(context, response);
231
- }
232
- return void 0;
233
- };
234
- const prefixOtherLocales = (context, response) => {
235
- let pathnameContainsDefaultLocale = false;
236
- const url = context.url;
237
- for (const segment of url.pathname.split("/")) {
238
- if (normalizeTheLocale(segment) === normalizeTheLocale(i18n.defaultLocale)) {
239
- pathnameContainsDefaultLocale = true;
240
- break;
241
- }
242
- }
243
- if (pathnameContainsDefaultLocale) {
244
- const newLocation = url.pathname.replace(`/${i18n.defaultLocale}`, "");
245
- response.headers.set("Location", newLocation);
246
- return _noFoundForNonLocaleRoute(context);
247
- }
248
- return void 0;
249
- };
250
- return async (context, next) => {
251
- const response = await next();
252
- const type = response.headers.get(ROUTE_TYPE_HEADER);
253
- const isReroute = response.headers.get(REROUTE_DIRECTIVE_HEADER);
254
- if (isReroute === "no" && typeof i18n.fallback === "undefined") {
255
- return response;
256
- }
257
- if (type !== "page" && type !== "fallback") {
258
- return response;
259
- }
260
- if (requestIs404Or500(context.request, base)) {
261
- return response;
262
- }
263
- if (isRequestServerIsland(context.request, base)) {
264
- return response;
265
- }
266
- const { currentLocale } = context;
267
- switch (i18n.strategy) {
268
- // NOTE: theoretically, we should never hit this code path
269
- case "manual": {
270
- return response;
271
- }
272
- case "domains-prefix-other-locales": {
273
- if (localeHasntDomain(i18n, currentLocale)) {
274
- const result = prefixOtherLocales(context, response);
275
- if (result) {
276
- return result;
277
- }
278
- }
279
- break;
280
- }
281
- case "pathname-prefix-other-locales": {
282
- const result = prefixOtherLocales(context, response);
283
- if (result) {
284
- return result;
285
- }
286
- break;
287
- }
288
- case "domains-prefix-always-no-redirect": {
289
- if (localeHasntDomain(i18n, currentLocale)) {
290
- const result = _noFoundForNonLocaleRoute(context, response);
291
- if (result) {
292
- return result;
293
- }
294
- }
295
- break;
296
- }
297
- case "pathname-prefix-always-no-redirect": {
298
- const result = _noFoundForNonLocaleRoute(context, response);
299
- if (result) {
300
- return result;
301
- }
302
- break;
303
- }
304
- case "pathname-prefix-always": {
305
- const result = prefixAlways(context, response);
306
- if (result) {
307
- return result;
308
- }
309
- break;
310
- }
311
- case "domains-prefix-always": {
312
- if (localeHasntDomain(i18n, currentLocale)) {
313
- const result = prefixAlways(context, response);
314
- if (result) {
315
- return result;
316
- }
317
- }
318
- break;
319
- }
320
- }
321
- return _redirectToFallback(context, response);
322
- };
323
- }
324
- function localeHasntDomain(i18n, currentLocale) {
325
- for (const domainLocale of Object.values(i18n.domainLookupTable)) {
326
- if (domainLocale === currentLocale) {
327
- return false;
328
- }
329
- }
330
- return true;
331
- }
332
-
333
224
  function requestHasLocale(locales) {
334
225
  return function(context) {
335
226
  return pathHasLocale(context.url.pathname, locales);
@@ -369,14 +260,16 @@ function getPathByLocale(locale, locales) {
369
260
  function normalizeTheLocale(locale) {
370
261
  return locale.replaceAll("_", "-").toLowerCase();
371
262
  }
372
- function toCodes(locales) {
373
- return locales.map((loopLocale) => {
263
+ function getAllCodes(locales) {
264
+ const result = [];
265
+ for (const loopLocale of locales) {
374
266
  if (typeof loopLocale === "string") {
375
- return loopLocale;
267
+ result.push(loopLocale);
376
268
  } else {
377
- return loopLocale.codes[0];
269
+ result.push(...loopLocale.codes);
378
270
  }
379
- });
271
+ }
272
+ return result;
380
273
  }
381
274
  function redirectToDefaultLocale({
382
275
  trailingSlash,
@@ -386,7 +279,7 @@ function redirectToDefaultLocale({
386
279
  }) {
387
280
  return function(context, statusCode) {
388
281
  if (shouldAppendForwardSlash(trailingSlash, format)) {
389
- return context.redirect(`${appendForwardSlash$1(joinPaths(base, defaultLocale))}`, statusCode);
282
+ return context.redirect(`${appendForwardSlash(joinPaths(base, defaultLocale))}`, statusCode);
390
283
  } else {
391
284
  return context.redirect(`${joinPaths(base, defaultLocale)}`, statusCode);
392
285
  }
@@ -466,9 +359,146 @@ function redirectToFallback({
466
359
  };
467
360
  }
468
361
 
362
+ function parseLocale(header) {
363
+ if (header === "*") {
364
+ return [{ locale: header, qualityValue: void 0 }];
365
+ }
366
+ const result = [];
367
+ const localeValues = header.split(",").map((str) => str.trim());
368
+ for (const localeValue of localeValues) {
369
+ const split = localeValue.split(";").map((str) => str.trim());
370
+ const localeName = split[0];
371
+ const qualityValue = split[1];
372
+ if (!split) {
373
+ continue;
374
+ }
375
+ if (qualityValue && qualityValue.startsWith("q=")) {
376
+ const qualityValueAsFloat = Number.parseFloat(qualityValue.slice("q=".length));
377
+ if (Number.isNaN(qualityValueAsFloat) || qualityValueAsFloat > 1) {
378
+ result.push({
379
+ locale: localeName,
380
+ qualityValue: void 0
381
+ });
382
+ } else {
383
+ result.push({
384
+ locale: localeName,
385
+ qualityValue: qualityValueAsFloat
386
+ });
387
+ }
388
+ } else {
389
+ result.push({
390
+ locale: localeName,
391
+ qualityValue: void 0
392
+ });
393
+ }
394
+ }
395
+ return result;
396
+ }
397
+ function sortAndFilterLocales(browserLocaleList, locales) {
398
+ const normalizedLocales = getAllCodes(locales).map(normalizeTheLocale);
399
+ return browserLocaleList.filter((browserLocale) => {
400
+ if (browserLocale.locale !== "*") {
401
+ return normalizedLocales.includes(normalizeTheLocale(browserLocale.locale));
402
+ }
403
+ return true;
404
+ }).sort((a, b) => {
405
+ if (a.qualityValue && b.qualityValue) {
406
+ return Math.sign(b.qualityValue - a.qualityValue);
407
+ }
408
+ return 0;
409
+ });
410
+ }
411
+ function computePreferredLocale(request, locales) {
412
+ const acceptHeader = request.headers.get("Accept-Language");
413
+ let result = void 0;
414
+ if (acceptHeader) {
415
+ const browserLocaleList = sortAndFilterLocales(parseLocale(acceptHeader), locales);
416
+ const firstResult = browserLocaleList.at(0);
417
+ if (firstResult && firstResult.locale !== "*") {
418
+ for (const currentLocale of locales) {
419
+ if (typeof currentLocale === "string") {
420
+ if (normalizeTheLocale(currentLocale) === normalizeTheLocale(firstResult.locale)) {
421
+ result = currentLocale;
422
+ break;
423
+ }
424
+ } else {
425
+ for (const currentCode of currentLocale.codes) {
426
+ if (normalizeTheLocale(currentCode) === normalizeTheLocale(firstResult.locale)) {
427
+ result = currentCode;
428
+ break;
429
+ }
430
+ }
431
+ }
432
+ }
433
+ }
434
+ }
435
+ return result;
436
+ }
437
+ function computePreferredLocaleList(request, locales) {
438
+ const acceptHeader = request.headers.get("Accept-Language");
439
+ let result = [];
440
+ if (acceptHeader) {
441
+ const browserLocaleList = sortAndFilterLocales(parseLocale(acceptHeader), locales);
442
+ if (browserLocaleList.length === 1 && browserLocaleList.at(0).locale === "*") {
443
+ return getAllCodes(locales);
444
+ } else if (browserLocaleList.length > 0) {
445
+ for (const browserLocale of browserLocaleList) {
446
+ for (const loopLocale of locales) {
447
+ if (typeof loopLocale === "string") {
448
+ if (normalizeTheLocale(loopLocale) === normalizeTheLocale(browserLocale.locale)) {
449
+ result.push(loopLocale);
450
+ }
451
+ } else {
452
+ for (const code of loopLocale.codes) {
453
+ if (code === browserLocale.locale) {
454
+ result.push(code);
455
+ }
456
+ }
457
+ }
458
+ }
459
+ }
460
+ }
461
+ }
462
+ return result;
463
+ }
464
+ function computeCurrentLocale(pathname, locales, defaultLocale) {
465
+ for (const segment of pathname.split("/")) {
466
+ for (const locale of locales) {
467
+ if (typeof locale === "string") {
468
+ if (!segment.includes(locale)) continue;
469
+ if (normalizeTheLocale(locale) === normalizeTheLocale(segment)) {
470
+ return locale;
471
+ }
472
+ } else {
473
+ if (locale.path === segment) {
474
+ return locale.codes.at(0);
475
+ } else {
476
+ for (const code of locale.codes) {
477
+ if (normalizeTheLocale(code) === normalizeTheLocale(segment)) {
478
+ return code;
479
+ }
480
+ }
481
+ }
482
+ }
483
+ }
484
+ }
485
+ for (const locale of locales) {
486
+ if (typeof locale === "string") {
487
+ if (locale === defaultLocale) {
488
+ return locale;
489
+ }
490
+ } else {
491
+ if (locale.path === defaultLocale) {
492
+ return locale.codes.at(0);
493
+ }
494
+ }
495
+ }
496
+ }
497
+
469
498
  const DELETED_EXPIRATION = /* @__PURE__ */ new Date(0);
470
499
  const DELETED_VALUE = "deleted";
471
500
  const responseSentSymbol = Symbol.for("astro.responseSent");
501
+ const identity = (value) => value;
472
502
  class AstroCookie {
473
503
  constructor(value) {
474
504
  this.value = value;
@@ -519,7 +549,7 @@ class AstroCookies {
519
549
  };
520
550
  this.#ensureOutgoingMap().set(key, [
521
551
  DELETED_VALUE,
522
- serialize(key, DELETED_VALUE, serializeOptions),
552
+ distExports.serialize(key, DELETED_VALUE, serializeOptions),
523
553
  false
524
554
  ]);
525
555
  }
@@ -539,25 +569,29 @@ class AstroCookies {
539
569
  return void 0;
540
570
  }
541
571
  }
542
- const values = this.#ensureParsed(options);
572
+ const decode = options?.decode ?? decodeURIComponent;
573
+ const values = this.#ensureParsed();
543
574
  if (key in values) {
544
575
  const value = values[key];
545
- return new AstroCookie(value);
576
+ if (value) {
577
+ return new AstroCookie(decode(value));
578
+ }
546
579
  }
547
580
  }
548
581
  /**
549
582
  * Astro.cookies.has(key) returns a boolean indicating whether this cookie is either
550
583
  * part of the initial request or set via Astro.cookies.set(key)
551
584
  * @param key The cookie to check for.
585
+ * @param _options This parameter is no longer used.
552
586
  * @returns
553
587
  */
554
- has(key, options = void 0) {
588
+ has(key, _options) {
555
589
  if (this.#outgoing?.has(key)) {
556
590
  let [, , isSetValue] = this.#outgoing.get(key);
557
591
  return isSetValue;
558
592
  }
559
- const values = this.#ensureParsed(options);
560
- return !!values[key];
593
+ const values = this.#ensureParsed();
594
+ return values[key] !== void 0;
561
595
  }
562
596
  /**
563
597
  * Astro.cookies.set(key, value) is used to set a cookie's value. If provided
@@ -593,7 +627,7 @@ class AstroCookies {
593
627
  }
594
628
  this.#ensureOutgoingMap().set(key, [
595
629
  serializedValue,
596
- serialize(key, serializedValue, serializeOptions),
630
+ distExports.serialize(key, serializedValue, serializeOptions),
597
631
  true
598
632
  ]);
599
633
  if (this.#request[responseSentSymbol]) {
@@ -634,9 +668,9 @@ class AstroCookies {
634
668
  cookies.#consumed = true;
635
669
  return cookies.headers();
636
670
  }
637
- #ensureParsed(options = void 0) {
671
+ #ensureParsed() {
638
672
  if (!this.#requestValues) {
639
- this.#parse(options);
673
+ this.#parse();
640
674
  }
641
675
  if (!this.#requestValues) {
642
676
  this.#requestValues = {};
@@ -649,12 +683,12 @@ class AstroCookies {
649
683
  }
650
684
  return this.#outgoing;
651
685
  }
652
- #parse(options = void 0) {
686
+ #parse() {
653
687
  const raw = this.#request.headers.get("cookie");
654
688
  if (!raw) {
655
689
  return;
656
690
  }
657
- this.#requestValues = parse(raw, options);
691
+ this.#requestValues = distExports.parse(raw, { decode: identity });
658
692
  }
659
693
  }
660
694
 
@@ -681,298 +715,238 @@ function* getSetCookiesFromResponse(response) {
681
715
  return [];
682
716
  }
683
717
 
684
- const dateTimeFormat = new Intl.DateTimeFormat([], {
685
- hour: "2-digit",
686
- minute: "2-digit",
687
- second: "2-digit",
688
- hour12: false
689
- });
690
- const levels = {
691
- debug: 20,
692
- info: 30,
693
- warn: 40,
694
- error: 50,
695
- silent: 90
696
- };
697
- function log(opts, level, label, message, newLine = true) {
698
- const logLevel = opts.level;
699
- const dest = opts.dest;
700
- const event = {
701
- label,
702
- level,
703
- message,
704
- newLine
705
- };
706
- if (!isLogLevelEnabled(logLevel, level)) {
707
- return;
718
+ function createRequest({
719
+ url,
720
+ headers,
721
+ method = "GET",
722
+ body = void 0,
723
+ logger,
724
+ isPrerendered = false,
725
+ routePattern,
726
+ init
727
+ }) {
728
+ const headersObj = isPrerendered ? void 0 : headers instanceof Headers ? headers : new Headers(
729
+ // Filter out HTTP/2 pseudo-headers. These are internally-generated headers added to all HTTP/2 requests with trusted metadata about the request.
730
+ // Examples include `:method`, `:scheme`, `:authority`, and `:path`.
731
+ // They are always prefixed with a colon to distinguish them from other headers, and it is an error to add the to a Headers object manually.
732
+ // See https://httpwg.org/specs/rfc7540.html#HttpRequest
733
+ Object.entries(headers).filter(([name]) => !name.startsWith(":"))
734
+ );
735
+ if (typeof url === "string") url = new URL(url);
736
+ if (isPrerendered) {
737
+ url.search = "";
708
738
  }
709
- dest.write(event);
710
- }
711
- function isLogLevelEnabled(configuredLogLevel, level) {
712
- return levels[configuredLogLevel] <= levels[level];
713
- }
714
- function info(opts, label, message, newLine = true) {
715
- return log(opts, "info", label, message, newLine);
716
- }
717
- function warn(opts, label, message, newLine = true) {
718
- return log(opts, "warn", label, message, newLine);
719
- }
720
- function error(opts, label, message, newLine = true) {
721
- return log(opts, "error", label, message, newLine);
722
- }
723
- function debug(...args) {
724
- if ("_astroGlobalDebug" in globalThis) {
725
- globalThis._astroGlobalDebug(...args);
739
+ const request = new Request(url, {
740
+ method,
741
+ headers: headersObj,
742
+ // body is made available only if the request is for a page that will be on-demand rendered
743
+ body: isPrerendered ? null : body,
744
+ ...init
745
+ });
746
+ if (isPrerendered) {
747
+ let _headers = request.headers;
748
+ const { value, writable, ...headersDesc } = Object.getOwnPropertyDescriptor(request, "headers") || {};
749
+ Object.defineProperty(request, "headers", {
750
+ ...headersDesc,
751
+ get() {
752
+ logger.warn(
753
+ null,
754
+ `\`Astro.request.headers\` was used when rendering the route \`${routePattern}'\`. \`Astro.request.headers\` is not available on prerendered pages. If you need access to request headers, 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.`
755
+ );
756
+ return _headers;
757
+ },
758
+ set(newHeaders) {
759
+ _headers = newHeaders;
760
+ }
761
+ });
726
762
  }
763
+ return request;
727
764
  }
728
- function getEventPrefix({ level, label }) {
729
- const timestamp = `${dateTimeFormat.format(/* @__PURE__ */ new Date())}`;
730
- const prefix = [];
731
- if (level === "error" || level === "warn") {
732
- prefix.push(bold(timestamp));
733
- prefix.push(`[${level.toUpperCase()}]`);
734
- } else {
735
- prefix.push(timestamp);
736
- }
737
- if (label) {
738
- prefix.push(`[${label}]`);
739
- }
740
- if (level === "error") {
741
- return red(prefix.join(" "));
742
- }
743
- if (level === "warn") {
744
- return yellow(prefix.join(" "));
745
- }
746
- if (prefix.length === 1) {
747
- return dim(prefix[0]);
748
- }
749
- return dim(prefix[0]) + " " + blue(prefix.splice(1).join(" "));
750
- }
751
- class Logger {
752
- options;
753
- constructor(options) {
754
- this.options = options;
755
- }
756
- info(label, message, newLine = true) {
757
- info(this.options, label, message, newLine);
758
- }
759
- warn(label, message, newLine = true) {
760
- warn(this.options, label, message, newLine);
761
- }
762
- error(label, message, newLine = true) {
763
- error(this.options, label, message, newLine);
764
- }
765
- debug(label, ...messages) {
766
- debug(label, ...messages);
767
- }
768
- level() {
769
- return this.options.level;
770
- }
771
- forkIntegrationLogger(label) {
772
- return new AstroIntegrationLogger(this.options, label);
765
+
766
+ function findRouteToRewrite({
767
+ payload,
768
+ routes,
769
+ request,
770
+ trailingSlash,
771
+ buildFormat,
772
+ base,
773
+ outDir
774
+ }) {
775
+ let newUrl = void 0;
776
+ if (payload instanceof URL) {
777
+ newUrl = payload;
778
+ } else if (payload instanceof Request) {
779
+ newUrl = new URL(payload.url);
780
+ } else {
781
+ newUrl = new URL(payload, new URL(request.url).origin);
773
782
  }
774
- }
775
- class AstroIntegrationLogger {
776
- options;
777
- label;
778
- constructor(logging, label) {
779
- this.options = logging;
780
- this.label = label;
783
+ let pathname = newUrl.pathname;
784
+ const shouldAppendSlash = shouldAppendForwardSlash(trailingSlash, buildFormat);
785
+ if (base !== "/") {
786
+ const isBasePathRequest = newUrl.pathname === base || newUrl.pathname === removeTrailingForwardSlash(base);
787
+ if (isBasePathRequest) {
788
+ pathname = shouldAppendSlash ? "/" : "";
789
+ } else if (newUrl.pathname.startsWith(base)) {
790
+ pathname = shouldAppendSlash ? appendForwardSlash(newUrl.pathname) : removeTrailingForwardSlash(newUrl.pathname);
791
+ pathname = pathname.slice(base.length);
792
+ }
781
793
  }
782
- /**
783
- * Creates a new logger instance with a new label, but the same log options.
784
- */
785
- fork(label) {
786
- return new AstroIntegrationLogger(this.options, label);
794
+ if (!pathname.startsWith("/") && shouldAppendSlash && newUrl.pathname.endsWith("/")) {
795
+ pathname = prependForwardSlash(pathname);
787
796
  }
788
- info(message) {
789
- info(this.options, this.label, message);
797
+ if (pathname === "/" && base !== "/" && !shouldAppendSlash) {
798
+ pathname = "";
790
799
  }
791
- warn(message) {
792
- warn(this.options, this.label, message);
800
+ if (buildFormat === "file") {
801
+ pathname = pathname.replace(/\.html$/, "");
793
802
  }
794
- error(message) {
795
- error(this.options, this.label, message);
803
+ if (base !== "/" && (pathname === "" || pathname === "/") && !shouldAppendSlash) {
804
+ newUrl.pathname = removeTrailingForwardSlash(base);
805
+ } else {
806
+ newUrl.pathname = joinPaths(...[base, pathname].filter(Boolean));
796
807
  }
797
- debug(message) {
798
- debug(this.label, message);
808
+ const decodedPathname = decodeURI(pathname);
809
+ let foundRoute;
810
+ for (const route of routes) {
811
+ if (route.pattern.test(decodedPathname)) {
812
+ if (route.params && route.params.length !== 0 && route.distURL && route.distURL.length !== 0) {
813
+ if (!route.distURL.find(
814
+ (url) => url.href.replace(outDir.toString(), "").replace(/(?:\/index\.html|\.html)$/, "") == trimSlashes(decodedPathname)
815
+ )) {
816
+ continue;
817
+ }
818
+ }
819
+ foundRoute = route;
820
+ break;
821
+ }
799
822
  }
800
- }
801
-
802
- const consoleLogDestination = {
803
- write(event) {
804
- let dest = console.error;
805
- if (levels[event.level] < levels["error"]) {
806
- dest = console.log;
807
- }
808
- if (event.label === "SKIP_FORMAT") {
809
- dest(event.message);
823
+ if (foundRoute) {
824
+ return {
825
+ routeData: foundRoute,
826
+ newUrl,
827
+ pathname: decodedPathname
828
+ };
829
+ } else {
830
+ const custom404 = routes.find((route) => route.route === "/404");
831
+ if (custom404) {
832
+ return { routeData: custom404, newUrl, pathname };
810
833
  } else {
811
- dest(getEventPrefix(event) + " " + event.message);
834
+ return { routeData: DEFAULT_404_ROUTE, newUrl, pathname };
812
835
  }
813
- return true;
814
836
  }
815
- };
816
-
817
- const ACTION_API_CONTEXT_SYMBOL = Symbol.for("astro.actionAPIContext");
818
-
819
- function hasActionPayload(locals) {
820
- return "_actionPayload" in locals;
821
837
  }
822
- function createGetActionResult(locals) {
823
- return (actionFn) => {
824
- if (!hasActionPayload(locals) || actionFn.toString() !== getActionQueryString(locals._actionPayload.actionName)) {
825
- return void 0;
838
+ function copyRequest(newUrl, oldRequest, isPrerendered, logger, routePattern) {
839
+ if (oldRequest.bodyUsed) {
840
+ throw new AstroError(RewriteWithBodyUsed);
841
+ }
842
+ return createRequest({
843
+ url: newUrl,
844
+ method: oldRequest.method,
845
+ body: oldRequest.body,
846
+ isPrerendered,
847
+ logger,
848
+ headers: isPrerendered ? {} : oldRequest.headers,
849
+ routePattern,
850
+ init: {
851
+ referrer: oldRequest.referrer,
852
+ referrerPolicy: oldRequest.referrerPolicy,
853
+ mode: oldRequest.mode,
854
+ credentials: oldRequest.credentials,
855
+ cache: oldRequest.cache,
856
+ redirect: oldRequest.redirect,
857
+ integrity: oldRequest.integrity,
858
+ signal: oldRequest.signal,
859
+ keepalive: oldRequest.keepalive,
860
+ // https://fetch.spec.whatwg.org/#dom-request-duplex
861
+ // @ts-expect-error It isn't part of the types, but undici accepts it and it allows to carry over the body to a new request
862
+ duplex: "half"
826
863
  }
827
- return deserializeActionResult(locals._actionPayload.actionResult);
828
- };
864
+ });
829
865
  }
830
- function createCallAction(context) {
831
- return (baseAction, input) => {
832
- Reflect.set(context, ACTION_API_CONTEXT_SYMBOL, true);
833
- const action = baseAction.bind(context);
834
- return action(input);
835
- };
866
+ function setOriginPathname(request, pathname) {
867
+ Reflect.set(request, originPathnameSymbol, encodeURIComponent(pathname));
836
868
  }
837
-
838
- function parseLocale(header) {
839
- if (header === "*") {
840
- return [{ locale: header, qualityValue: void 0 }];
841
- }
842
- const result = [];
843
- const localeValues = header.split(",").map((str) => str.trim());
844
- for (const localeValue of localeValues) {
845
- const split = localeValue.split(";").map((str) => str.trim());
846
- const localeName = split[0];
847
- const qualityValue = split[1];
848
- if (!split) {
849
- continue;
850
- }
851
- if (qualityValue && qualityValue.startsWith("q=")) {
852
- const qualityValueAsFloat = Number.parseFloat(qualityValue.slice("q=".length));
853
- if (Number.isNaN(qualityValueAsFloat) || qualityValueAsFloat > 1) {
854
- result.push({
855
- locale: localeName,
856
- qualityValue: void 0
857
- });
858
- } else {
859
- result.push({
860
- locale: localeName,
861
- qualityValue: qualityValueAsFloat
862
- });
863
- }
864
- } else {
865
- result.push({
866
- locale: localeName,
867
- qualityValue: void 0
868
- });
869
- }
869
+ function getOriginPathname(request) {
870
+ const origin = Reflect.get(request, originPathnameSymbol);
871
+ if (origin) {
872
+ return decodeURIComponent(origin);
870
873
  }
871
- return result;
872
- }
873
- function sortAndFilterLocales(browserLocaleList, locales) {
874
- const normalizedLocales = toCodes(locales).map(normalizeTheLocale);
875
- return browserLocaleList.filter((browserLocale) => {
876
- if (browserLocale.locale !== "*") {
877
- return normalizedLocales.includes(normalizeTheLocale(browserLocale.locale));
878
- }
879
- return true;
880
- }).sort((a, b) => {
881
- if (a.qualityValue && b.qualityValue) {
882
- return Math.sign(b.qualityValue - a.qualityValue);
883
- }
884
- return 0;
885
- });
874
+ return new URL(request.url).pathname;
886
875
  }
887
- function computePreferredLocale(request, locales) {
888
- const acceptHeader = request.headers.get("Accept-Language");
889
- let result = void 0;
890
- if (acceptHeader) {
891
- const browserLocaleList = sortAndFilterLocales(parseLocale(acceptHeader), locales);
892
- const firstResult = browserLocaleList.at(0);
893
- if (firstResult && firstResult.locale !== "*") {
894
- for (const currentLocale of locales) {
895
- if (typeof currentLocale === "string") {
896
- if (normalizeTheLocale(currentLocale) === normalizeTheLocale(firstResult.locale)) {
897
- result = currentLocale;
898
- }
899
- } else {
900
- for (const currentCode of currentLocale.codes) {
901
- if (normalizeTheLocale(currentCode) === normalizeTheLocale(firstResult.locale)) {
902
- result = currentLocale.path;
903
- }
876
+
877
+ function getActionContext(context) {
878
+ const callerInfo = getCallerInfo(context);
879
+ const actionResultAlreadySet = Boolean(context.locals._actionPayload);
880
+ let action = void 0;
881
+ if (callerInfo && context.request.method === "POST" && !actionResultAlreadySet) {
882
+ action = {
883
+ calledFrom: callerInfo.from,
884
+ name: callerInfo.name,
885
+ handler: async () => {
886
+ const pipeline = Reflect.get(context, apiContextRoutesSymbol);
887
+ const callerInfoName = shouldAppendForwardSlash(
888
+ pipeline.manifest.trailingSlash,
889
+ pipeline.manifest.buildFormat
890
+ ) ? removeTrailingForwardSlash(callerInfo.name) : callerInfo.name;
891
+ const baseAction = await pipeline.getAction(callerInfoName);
892
+ let input;
893
+ try {
894
+ input = await parseRequestBody(context.request);
895
+ } catch (e) {
896
+ if (e instanceof TypeError) {
897
+ return { data: void 0, error: new ActionError({ code: "UNSUPPORTED_MEDIA_TYPE" }) };
904
898
  }
899
+ throw e;
905
900
  }
901
+ const omitKeys = ["props", "getActionResult", "callAction", "redirect"];
902
+ const actionAPIContext = Object.create(
903
+ Object.getPrototypeOf(context),
904
+ Object.fromEntries(
905
+ Object.entries(Object.getOwnPropertyDescriptors(context)).filter(
906
+ ([key]) => !omitKeys.includes(key)
907
+ )
908
+ )
909
+ );
910
+ Reflect.set(actionAPIContext, ACTION_API_CONTEXT_SYMBOL, true);
911
+ const handler = baseAction.bind(actionAPIContext);
912
+ return handler(input);
906
913
  }
907
- }
914
+ };
908
915
  }
909
- return result;
916
+ function setActionResult(actionName, actionResult) {
917
+ context.locals._actionPayload = {
918
+ actionResult,
919
+ actionName
920
+ };
921
+ }
922
+ return {
923
+ action,
924
+ setActionResult,
925
+ serializeActionResult,
926
+ deserializeActionResult
927
+ };
910
928
  }
911
- function computePreferredLocaleList(request, locales) {
912
- const acceptHeader = request.headers.get("Accept-Language");
913
- let result = [];
914
- if (acceptHeader) {
915
- const browserLocaleList = sortAndFilterLocales(parseLocale(acceptHeader), locales);
916
- if (browserLocaleList.length === 1 && browserLocaleList.at(0).locale === "*") {
917
- return locales.map((locale) => {
918
- if (typeof locale === "string") {
919
- return locale;
920
- } else {
921
- return locale.codes.at(0);
922
- }
923
- });
924
- } else if (browserLocaleList.length > 0) {
925
- for (const browserLocale of browserLocaleList) {
926
- for (const loopLocale of locales) {
927
- if (typeof loopLocale === "string") {
928
- if (normalizeTheLocale(loopLocale) === normalizeTheLocale(browserLocale.locale)) {
929
- result.push(loopLocale);
930
- }
931
- } else {
932
- for (const code of loopLocale.codes) {
933
- if (code === browserLocale.locale) {
934
- result.push(loopLocale.path);
935
- }
936
- }
937
- }
938
- }
939
- }
940
- }
929
+ function getCallerInfo(ctx) {
930
+ if (ctx.routePattern === ACTION_RPC_ROUTE_PATTERN) {
931
+ return { from: "rpc", name: ctx.url.pathname.replace(/^.*\/_actions\//, "") };
941
932
  }
942
- return result;
933
+ const queryParam = ctx.url.searchParams.get(ACTION_QUERY_PARAMS.actionName);
934
+ if (queryParam) {
935
+ return { from: "form", name: queryParam };
936
+ }
937
+ return void 0;
943
938
  }
944
- function computeCurrentLocale(pathname, locales, defaultLocale) {
945
- for (const segment of pathname.split("/")) {
946
- for (const locale of locales) {
947
- if (typeof locale === "string") {
948
- if (!segment.includes(locale)) continue;
949
- if (normalizeTheLocale(locale) === normalizeTheLocale(segment)) {
950
- return locale;
951
- }
952
- } else {
953
- if (locale.path === segment) {
954
- return locale.codes.at(0);
955
- } else {
956
- for (const code of locale.codes) {
957
- if (normalizeTheLocale(code) === normalizeTheLocale(segment)) {
958
- return code;
959
- }
960
- }
961
- }
962
- }
963
- }
939
+ async function parseRequestBody(request) {
940
+ const contentType = request.headers.get("content-type");
941
+ const contentLength = request.headers.get("Content-Length");
942
+ if (!contentType) return void 0;
943
+ if (hasContentType(contentType, formContentTypes)) {
944
+ return await request.clone().formData();
964
945
  }
965
- for (const locale of locales) {
966
- if (typeof locale === "string") {
967
- if (locale === defaultLocale) {
968
- return locale;
969
- }
970
- } else {
971
- if (locale.path === defaultLocale) {
972
- return locale.codes.at(0);
973
- }
974
- }
946
+ if (hasContentType(contentType, ["application/json"])) {
947
+ return contentLength === "0" ? void 0 : await request.clone().json();
975
948
  }
949
+ throw new TypeError("Unsupported content type");
976
950
  }
977
951
 
978
952
  async function callMiddleware(onRequest, apiContext, responseFunction) {
@@ -1008,190 +982,6 @@ async function callMiddleware(onRequest, apiContext, responseFunction) {
1008
982
  });
1009
983
  }
1010
984
 
1011
- function createRequest({
1012
- url,
1013
- headers,
1014
- method = "GET",
1015
- body = void 0,
1016
- logger,
1017
- isPrerendered = false,
1018
- routePattern,
1019
- init
1020
- }) {
1021
- const headersObj = isPrerendered ? void 0 : headers instanceof Headers ? headers : new Headers(
1022
- // Filter out HTTP/2 pseudo-headers. These are internally-generated headers added to all HTTP/2 requests with trusted metadata about the request.
1023
- // Examples include `:method`, `:scheme`, `:authority`, and `:path`.
1024
- // They are always prefixed with a colon to distinguish them from other headers, and it is an error to add the to a Headers object manually.
1025
- // See https://httpwg.org/specs/rfc7540.html#HttpRequest
1026
- Object.entries(headers).filter(([name]) => !name.startsWith(":"))
1027
- );
1028
- if (typeof url === "string") url = new URL(url);
1029
- if (isPrerendered) {
1030
- url.search = "";
1031
- }
1032
- const request = new Request(url, {
1033
- method,
1034
- headers: headersObj,
1035
- // body is made available only if the request is for a page that will be on-demand rendered
1036
- body: isPrerendered ? null : body,
1037
- ...init
1038
- });
1039
- if (isPrerendered) {
1040
- let _headers = request.headers;
1041
- const { value, writable, ...headersDesc } = Object.getOwnPropertyDescriptor(request, "headers") || {};
1042
- Object.defineProperty(request, "headers", {
1043
- ...headersDesc,
1044
- get() {
1045
- logger.warn(
1046
- null,
1047
- `\`Astro.request.headers\` was used when rendering the route \`${routePattern}'\`. \`Astro.request.headers\` is not available on prerendered pages. If you need access to request headers, 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.`
1048
- );
1049
- return _headers;
1050
- },
1051
- set(newHeaders) {
1052
- _headers = newHeaders;
1053
- }
1054
- });
1055
- }
1056
- return request;
1057
- }
1058
-
1059
- function findRouteToRewrite({
1060
- payload,
1061
- routes,
1062
- request,
1063
- trailingSlash,
1064
- buildFormat,
1065
- base
1066
- }) {
1067
- let newUrl = void 0;
1068
- if (payload instanceof URL) {
1069
- newUrl = payload;
1070
- } else if (payload instanceof Request) {
1071
- newUrl = new URL(payload.url);
1072
- } else {
1073
- newUrl = new URL(payload, new URL(request.url).origin);
1074
- }
1075
- let pathname = newUrl.pathname;
1076
- const shouldAppendSlash = shouldAppendForwardSlash(trailingSlash, buildFormat);
1077
- if (base !== "/" && newUrl.pathname.startsWith(base)) {
1078
- pathname = shouldAppendSlash ? appendForwardSlash$1(newUrl.pathname) : removeTrailingForwardSlash(newUrl.pathname);
1079
- pathname = pathname.slice(base.length);
1080
- }
1081
- if (!pathname.startsWith("/") && shouldAppendSlash && newUrl.pathname.endsWith("/")) {
1082
- pathname = prependForwardSlash$1(pathname);
1083
- }
1084
- if (pathname === "/" && base !== "/" && !shouldAppendSlash) {
1085
- pathname = "";
1086
- }
1087
- newUrl.pathname = joinPaths(...[base, pathname].filter(Boolean));
1088
- const decodedPathname = decodeURI(pathname);
1089
- let foundRoute;
1090
- for (const route of routes) {
1091
- if (route.pattern.test(decodedPathname)) {
1092
- foundRoute = route;
1093
- break;
1094
- }
1095
- }
1096
- if (foundRoute) {
1097
- return {
1098
- routeData: foundRoute,
1099
- newUrl,
1100
- pathname: decodedPathname
1101
- };
1102
- } else {
1103
- const custom404 = routes.find((route) => route.route === "/404");
1104
- if (custom404) {
1105
- return { routeData: custom404, newUrl, pathname };
1106
- } else {
1107
- return { routeData: DEFAULT_404_ROUTE, newUrl, pathname };
1108
- }
1109
- }
1110
- }
1111
- function copyRequest(newUrl, oldRequest, isPrerendered, logger, routePattern) {
1112
- if (oldRequest.bodyUsed) {
1113
- throw new AstroError(RewriteWithBodyUsed);
1114
- }
1115
- return createRequest({
1116
- url: newUrl,
1117
- method: oldRequest.method,
1118
- body: oldRequest.body,
1119
- isPrerendered,
1120
- logger,
1121
- headers: isPrerendered ? {} : oldRequest.headers,
1122
- routePattern,
1123
- init: {
1124
- referrer: oldRequest.referrer,
1125
- referrerPolicy: oldRequest.referrerPolicy,
1126
- mode: oldRequest.mode,
1127
- credentials: oldRequest.credentials,
1128
- cache: oldRequest.cache,
1129
- redirect: oldRequest.redirect,
1130
- integrity: oldRequest.integrity,
1131
- signal: oldRequest.signal,
1132
- keepalive: oldRequest.keepalive,
1133
- // https://fetch.spec.whatwg.org/#dom-request-duplex
1134
- // @ts-expect-error It isn't part of the types, but undici accepts it and it allows to carry over the body to a new request
1135
- duplex: "half"
1136
- }
1137
- });
1138
- }
1139
- function setOriginPathname(request, pathname) {
1140
- Reflect.set(request, originPathnameSymbol, encodeURIComponent(pathname));
1141
- }
1142
- function getOriginPathname(request) {
1143
- const origin = Reflect.get(request, originPathnameSymbol);
1144
- if (origin) {
1145
- return decodeURIComponent(origin);
1146
- }
1147
- return new URL(request.url).pathname;
1148
- }
1149
-
1150
- const FORM_CONTENT_TYPES = [
1151
- "application/x-www-form-urlencoded",
1152
- "multipart/form-data",
1153
- "text/plain"
1154
- ];
1155
- const SAFE_METHODS = ["GET", "HEAD", "OPTIONS"];
1156
- function createOriginCheckMiddleware() {
1157
- return defineMiddleware((context, next) => {
1158
- const { request, url, isPrerendered } = context;
1159
- if (isPrerendered) {
1160
- return next();
1161
- }
1162
- if (SAFE_METHODS.includes(request.method)) {
1163
- return next();
1164
- }
1165
- const isSameOrigin = request.headers.get("origin") === url.origin;
1166
- const hasContentType = request.headers.has("content-type");
1167
- if (hasContentType) {
1168
- const formLikeHeader = hasFormLikeHeader(request.headers.get("content-type"));
1169
- if (formLikeHeader && !isSameOrigin) {
1170
- return new Response(`Cross-site ${request.method} form submissions are forbidden`, {
1171
- status: 403
1172
- });
1173
- }
1174
- } else {
1175
- if (!isSameOrigin) {
1176
- return new Response(`Cross-site ${request.method} form submissions are forbidden`, {
1177
- status: 403
1178
- });
1179
- }
1180
- }
1181
- return next();
1182
- });
1183
- }
1184
- function hasFormLikeHeader(contentType) {
1185
- if (contentType) {
1186
- for (const FORM_CONTENT_TYPE of FORM_CONTENT_TYPES) {
1187
- if (contentType.toLowerCase().includes(FORM_CONTENT_TYPE)) {
1188
- return true;
1189
- }
1190
- }
1191
- }
1192
- return false;
1193
- }
1194
-
1195
985
  const VALID_PARAM_TYPES = ["string", "number", "undefined"];
1196
986
  function validateGetStaticPathsParameter([key, value], route) {
1197
987
  if (!VALID_PARAM_TYPES.includes(typeof value)) {
@@ -1418,74 +1208,6 @@ function findPathItemByKey(staticPaths, params, route, logger) {
1418
1208
  logger.debug("router", `findPathItemByKey() - Unexpected cache miss looking for ${paramsKey}`);
1419
1209
  }
1420
1210
 
1421
- function createDefaultRoutes(manifest) {
1422
- const root = new URL(manifest.hrefRoot);
1423
- return [
1424
- {
1425
- instance: default404Instance,
1426
- matchesComponent: (filePath) => filePath.href === new URL(DEFAULT_404_COMPONENT, root).href,
1427
- route: DEFAULT_404_ROUTE.route,
1428
- component: DEFAULT_404_COMPONENT
1429
- },
1430
- {
1431
- instance: createEndpoint(manifest),
1432
- matchesComponent: (filePath) => filePath.href === new URL(SERVER_ISLAND_COMPONENT, root).href,
1433
- route: SERVER_ISLAND_ROUTE,
1434
- component: SERVER_ISLAND_COMPONENT
1435
- }
1436
- ];
1437
- }
1438
-
1439
- class Pipeline {
1440
- constructor(logger, manifest, runtimeMode, renderers, resolve, serverLike, streaming, adapterName = manifest.adapterName, clientDirectives = manifest.clientDirectives, inlinedScripts = manifest.inlinedScripts, compressHTML = manifest.compressHTML, i18n = manifest.i18n, middleware = manifest.middleware, routeCache = new RouteCache(logger, runtimeMode), site = manifest.site ? new URL(manifest.site) : void 0, defaultRoutes = createDefaultRoutes(manifest)) {
1441
- this.logger = logger;
1442
- this.manifest = manifest;
1443
- this.runtimeMode = runtimeMode;
1444
- this.renderers = renderers;
1445
- this.resolve = resolve;
1446
- this.serverLike = serverLike;
1447
- this.streaming = streaming;
1448
- this.adapterName = adapterName;
1449
- this.clientDirectives = clientDirectives;
1450
- this.inlinedScripts = inlinedScripts;
1451
- this.compressHTML = compressHTML;
1452
- this.i18n = i18n;
1453
- this.middleware = middleware;
1454
- this.routeCache = routeCache;
1455
- this.site = site;
1456
- this.defaultRoutes = defaultRoutes;
1457
- this.internalMiddleware = [];
1458
- if (i18n?.strategy !== "manual") {
1459
- this.internalMiddleware.push(
1460
- createI18nMiddleware(i18n, manifest.base, manifest.trailingSlash, manifest.buildFormat)
1461
- );
1462
- }
1463
- }
1464
- internalMiddleware;
1465
- resolvedMiddleware = void 0;
1466
- /**
1467
- * Resolves the middleware from the manifest, and returns the `onRequest` function. If `onRequest` isn't there,
1468
- * it returns a no-op function
1469
- */
1470
- async getMiddleware() {
1471
- if (this.resolvedMiddleware) {
1472
- return this.resolvedMiddleware;
1473
- } else if (this.middleware) {
1474
- const middlewareInstance = await this.middleware();
1475
- const onRequest = middlewareInstance.onRequest ?? NOOP_MIDDLEWARE_FN;
1476
- if (this.manifest.checkOrigin) {
1477
- this.resolvedMiddleware = sequence(createOriginCheckMiddleware(), onRequest);
1478
- } else {
1479
- this.resolvedMiddleware = onRequest;
1480
- }
1481
- return this.resolvedMiddleware;
1482
- } else {
1483
- this.resolvedMiddleware = NOOP_MIDDLEWARE_FN;
1484
- return this.resolvedMiddleware;
1485
- }
1486
- }
1487
- }
1488
-
1489
1211
  function routeIsRedirect(route) {
1490
1212
  return route?.type === "redirect";
1491
1213
  }
@@ -1493,19 +1215,6 @@ function routeIsFallback(route) {
1493
1215
  return route?.type === "fallback";
1494
1216
  }
1495
1217
 
1496
- const RedirectComponentInstance = {
1497
- default() {
1498
- return new Response(null, {
1499
- status: 301
1500
- });
1501
- }
1502
- };
1503
- const RedirectSinglePageBuiltModule = {
1504
- page: () => Promise.resolve(RedirectComponentInstance),
1505
- onRequest: (_, next) => next(),
1506
- renderers: []
1507
- };
1508
-
1509
1218
  async function getProps(opts) {
1510
1219
  const { logger, mod, routeData: route, routeCache, pathname, serverLike, base } = opts;
1511
1220
  if (!route || route.pathname) {
@@ -1634,79 +1343,673 @@ class Slots {
1634
1343
  }
1635
1344
  }
1636
1345
 
1637
- function sequence(...handlers) {
1638
- const filtered = handlers.filter((h) => !!h);
1639
- const length = filtered.length;
1640
- if (!length) {
1641
- return defineMiddleware((_context, next) => {
1642
- return next();
1643
- });
1346
+ const suspectProtoRx = /"(?:_|\\u0{2}5[Ff]){2}(?:p|\\u0{2}70)(?:r|\\u0{2}72)(?:o|\\u0{2}6[Ff])(?:t|\\u0{2}74)(?:o|\\u0{2}6[Ff])(?:_|\\u0{2}5[Ff]){2}"\s*:/;
1347
+ const suspectConstructorRx = /"(?:c|\\u0063)(?:o|\\u006[Ff])(?:n|\\u006[Ee])(?:s|\\u0073)(?:t|\\u0074)(?:r|\\u0072)(?:u|\\u0075)(?:c|\\u0063)(?:t|\\u0074)(?:o|\\u006[Ff])(?:r|\\u0072)"\s*:/;
1348
+ const JsonSigRx = /^\s*["[{]|^\s*-?\d{1,16}(\.\d{1,17})?([Ee][+-]?\d+)?\s*$/;
1349
+ function jsonParseTransform(key, value) {
1350
+ if (key === "__proto__" || key === "constructor" && value && typeof value === "object" && "prototype" in value) {
1351
+ warnKeyDropped(key);
1352
+ return;
1644
1353
  }
1645
- return defineMiddleware((context, next) => {
1646
- let carriedPayload = void 0;
1647
- return applyHandle(0, context);
1648
- function applyHandle(i, handleContext) {
1649
- const handle = filtered[i];
1650
- const result = handle(handleContext, async (payload) => {
1651
- if (i < length - 1) {
1652
- if (payload) {
1653
- let newRequest;
1654
- if (payload instanceof Request) {
1655
- newRequest = payload;
1656
- } else if (payload instanceof URL) {
1657
- newRequest = new Request(payload, handleContext.request);
1658
- } else {
1659
- newRequest = new Request(
1660
- new URL(payload, handleContext.url.origin),
1661
- handleContext.request
1662
- );
1663
- }
1664
- const pipeline = Reflect.get(handleContext, apiContextRoutesSymbol);
1665
- const { routeData, pathname } = await pipeline.tryRewrite(
1666
- payload,
1667
- handleContext.request
1668
- );
1669
- if (pipeline.serverLike === true && handleContext.isPrerendered === false && routeData.prerender === true) {
1670
- throw new AstroError({
1671
- ...ForbiddenRewrite,
1672
- message: ForbiddenRewrite.message(
1673
- handleContext.url.pathname,
1674
- pathname,
1675
- routeData.component
1676
- ),
1677
- hint: ForbiddenRewrite.hint(routeData.component)
1678
- });
1679
- }
1680
- carriedPayload = payload;
1681
- handleContext.request = newRequest;
1682
- handleContext.url = new URL(newRequest.url);
1683
- handleContext.cookies = new AstroCookies(newRequest);
1684
- handleContext.params = getParams(routeData, pathname);
1685
- }
1686
- return applyHandle(i + 1, handleContext);
1687
- } else {
1688
- return next(payload ?? carriedPayload);
1689
- }
1690
- });
1691
- return result;
1354
+ return value;
1355
+ }
1356
+ function warnKeyDropped(key) {
1357
+ console.warn(`[destr] Dropping "${key}" key to prevent prototype pollution.`);
1358
+ }
1359
+ function destr(value, options = {}) {
1360
+ if (typeof value !== "string") {
1361
+ return value;
1362
+ }
1363
+ if (value[0] === '"' && value[value.length - 1] === '"' && value.indexOf("\\") === -1) {
1364
+ return value.slice(1, -1);
1365
+ }
1366
+ const _value = value.trim();
1367
+ if (_value.length <= 9) {
1368
+ switch (_value.toLowerCase()) {
1369
+ case "true": {
1370
+ return true;
1371
+ }
1372
+ case "false": {
1373
+ return false;
1374
+ }
1375
+ case "undefined": {
1376
+ return void 0;
1377
+ }
1378
+ case "null": {
1379
+ return null;
1380
+ }
1381
+ case "nan": {
1382
+ return Number.NaN;
1383
+ }
1384
+ case "infinity": {
1385
+ return Number.POSITIVE_INFINITY;
1386
+ }
1387
+ case "-infinity": {
1388
+ return Number.NEGATIVE_INFINITY;
1389
+ }
1692
1390
  }
1693
- });
1391
+ }
1392
+ if (!JsonSigRx.test(value)) {
1393
+ if (options.strict) {
1394
+ throw new SyntaxError("[destr] Invalid JSON");
1395
+ }
1396
+ return value;
1397
+ }
1398
+ try {
1399
+ if (suspectProtoRx.test(value) || suspectConstructorRx.test(value)) {
1400
+ if (options.strict) {
1401
+ throw new Error("[destr] Possible prototype pollution");
1402
+ }
1403
+ return JSON.parse(value, jsonParseTransform);
1404
+ }
1405
+ return JSON.parse(value);
1406
+ } catch (error) {
1407
+ if (options.strict) {
1408
+ throw error;
1409
+ }
1410
+ return value;
1411
+ }
1694
1412
  }
1695
1413
 
1696
- function defineMiddleware(fn) {
1697
- return fn;
1414
+ function wrapToPromise(value) {
1415
+ if (!value || typeof value.then !== "function") {
1416
+ return Promise.resolve(value);
1417
+ }
1418
+ return value;
1698
1419
  }
1699
-
1700
- const PERSIST_SYMBOL = Symbol();
1701
- const DEFAULT_COOKIE_NAME = "astro-session";
1702
- const VALID_COOKIE_REGEX = /^[\w-]+$/;
1703
- const unflatten = (parsed, _) => {
1704
- return unflatten$1(parsed, {
1705
- URL: (href) => new URL(href)
1706
- });
1420
+ function asyncCall(function_, ...arguments_) {
1421
+ try {
1422
+ return wrapToPromise(function_(...arguments_));
1423
+ } catch (error) {
1424
+ return Promise.reject(error);
1425
+ }
1426
+ }
1427
+ function isPrimitive(value) {
1428
+ const type = typeof value;
1429
+ return value === null || type !== "object" && type !== "function";
1430
+ }
1431
+ function isPureObject(value) {
1432
+ const proto = Object.getPrototypeOf(value);
1433
+ return !proto || proto.isPrototypeOf(Object);
1434
+ }
1435
+ function stringify$1(value) {
1436
+ if (isPrimitive(value)) {
1437
+ return String(value);
1438
+ }
1439
+ if (isPureObject(value) || Array.isArray(value)) {
1440
+ return JSON.stringify(value);
1441
+ }
1442
+ if (typeof value.toJSON === "function") {
1443
+ return stringify$1(value.toJSON());
1444
+ }
1445
+ throw new Error("[unstorage] Cannot stringify value!");
1446
+ }
1447
+ const BASE64_PREFIX = "base64:";
1448
+ function serializeRaw(value) {
1449
+ if (typeof value === "string") {
1450
+ return value;
1451
+ }
1452
+ return BASE64_PREFIX + base64Encode(value);
1453
+ }
1454
+ function deserializeRaw(value) {
1455
+ if (typeof value !== "string") {
1456
+ return value;
1457
+ }
1458
+ if (!value.startsWith(BASE64_PREFIX)) {
1459
+ return value;
1460
+ }
1461
+ return base64Decode(value.slice(BASE64_PREFIX.length));
1462
+ }
1463
+ function base64Decode(input) {
1464
+ if (globalThis.Buffer) {
1465
+ return Buffer.from(input, "base64");
1466
+ }
1467
+ return Uint8Array.from(
1468
+ globalThis.atob(input),
1469
+ (c) => c.codePointAt(0)
1470
+ );
1471
+ }
1472
+ function base64Encode(input) {
1473
+ if (globalThis.Buffer) {
1474
+ return Buffer.from(input).toString("base64");
1475
+ }
1476
+ return globalThis.btoa(String.fromCodePoint(...input));
1477
+ }
1478
+ function normalizeKey(key) {
1479
+ if (!key) {
1480
+ return "";
1481
+ }
1482
+ return key.split("?")[0]?.replace(/[/\\]/g, ":").replace(/:+/g, ":").replace(/^:|:$/g, "") || "";
1483
+ }
1484
+ function joinKeys(...keys) {
1485
+ return normalizeKey(keys.join(":"));
1486
+ }
1487
+ function normalizeBaseKey(base) {
1488
+ base = normalizeKey(base);
1489
+ return base ? base + ":" : "";
1490
+ }
1491
+ function filterKeyByDepth(key, depth) {
1492
+ if (depth === void 0) {
1493
+ return true;
1494
+ }
1495
+ let substrCount = 0;
1496
+ let index = key.indexOf(":");
1497
+ while (index > -1) {
1498
+ substrCount++;
1499
+ index = key.indexOf(":", index + 1);
1500
+ }
1501
+ return substrCount <= depth;
1502
+ }
1503
+ function filterKeyByBase(key, base) {
1504
+ if (base) {
1505
+ return key.startsWith(base) && key[key.length - 1] !== "$";
1506
+ }
1507
+ return key[key.length - 1] !== "$";
1508
+ }
1509
+
1510
+ function defineDriver(factory) {
1511
+ return factory;
1512
+ }
1513
+
1514
+ const DRIVER_NAME = "memory";
1515
+ const memory = defineDriver(() => {
1516
+ const data = /* @__PURE__ */ new Map();
1517
+ return {
1518
+ name: DRIVER_NAME,
1519
+ getInstance: () => data,
1520
+ hasItem(key) {
1521
+ return data.has(key);
1522
+ },
1523
+ getItem(key) {
1524
+ return data.get(key) ?? null;
1525
+ },
1526
+ getItemRaw(key) {
1527
+ return data.get(key) ?? null;
1528
+ },
1529
+ setItem(key, value) {
1530
+ data.set(key, value);
1531
+ },
1532
+ setItemRaw(key, value) {
1533
+ data.set(key, value);
1534
+ },
1535
+ removeItem(key) {
1536
+ data.delete(key);
1537
+ },
1538
+ getKeys() {
1539
+ return [...data.keys()];
1540
+ },
1541
+ clear() {
1542
+ data.clear();
1543
+ },
1544
+ dispose() {
1545
+ data.clear();
1546
+ }
1547
+ };
1548
+ });
1549
+
1550
+ function createStorage(options = {}) {
1551
+ const context = {
1552
+ mounts: { "": options.driver || memory() },
1553
+ mountpoints: [""],
1554
+ watching: false,
1555
+ watchListeners: [],
1556
+ unwatch: {}
1557
+ };
1558
+ const getMount = (key) => {
1559
+ for (const base of context.mountpoints) {
1560
+ if (key.startsWith(base)) {
1561
+ return {
1562
+ base,
1563
+ relativeKey: key.slice(base.length),
1564
+ driver: context.mounts[base]
1565
+ };
1566
+ }
1567
+ }
1568
+ return {
1569
+ base: "",
1570
+ relativeKey: key,
1571
+ driver: context.mounts[""]
1572
+ };
1573
+ };
1574
+ const getMounts = (base, includeParent) => {
1575
+ return context.mountpoints.filter(
1576
+ (mountpoint) => mountpoint.startsWith(base) || includeParent && base.startsWith(mountpoint)
1577
+ ).map((mountpoint) => ({
1578
+ relativeBase: base.length > mountpoint.length ? base.slice(mountpoint.length) : void 0,
1579
+ mountpoint,
1580
+ driver: context.mounts[mountpoint]
1581
+ }));
1582
+ };
1583
+ const onChange = (event, key) => {
1584
+ if (!context.watching) {
1585
+ return;
1586
+ }
1587
+ key = normalizeKey(key);
1588
+ for (const listener of context.watchListeners) {
1589
+ listener(event, key);
1590
+ }
1591
+ };
1592
+ const startWatch = async () => {
1593
+ if (context.watching) {
1594
+ return;
1595
+ }
1596
+ context.watching = true;
1597
+ for (const mountpoint in context.mounts) {
1598
+ context.unwatch[mountpoint] = await watch(
1599
+ context.mounts[mountpoint],
1600
+ onChange,
1601
+ mountpoint
1602
+ );
1603
+ }
1604
+ };
1605
+ const stopWatch = async () => {
1606
+ if (!context.watching) {
1607
+ return;
1608
+ }
1609
+ for (const mountpoint in context.unwatch) {
1610
+ await context.unwatch[mountpoint]();
1611
+ }
1612
+ context.unwatch = {};
1613
+ context.watching = false;
1614
+ };
1615
+ const runBatch = (items, commonOptions, cb) => {
1616
+ const batches = /* @__PURE__ */ new Map();
1617
+ const getBatch = (mount) => {
1618
+ let batch = batches.get(mount.base);
1619
+ if (!batch) {
1620
+ batch = {
1621
+ driver: mount.driver,
1622
+ base: mount.base,
1623
+ items: []
1624
+ };
1625
+ batches.set(mount.base, batch);
1626
+ }
1627
+ return batch;
1628
+ };
1629
+ for (const item of items) {
1630
+ const isStringItem = typeof item === "string";
1631
+ const key = normalizeKey(isStringItem ? item : item.key);
1632
+ const value = isStringItem ? void 0 : item.value;
1633
+ const options2 = isStringItem || !item.options ? commonOptions : { ...commonOptions, ...item.options };
1634
+ const mount = getMount(key);
1635
+ getBatch(mount).items.push({
1636
+ key,
1637
+ value,
1638
+ relativeKey: mount.relativeKey,
1639
+ options: options2
1640
+ });
1641
+ }
1642
+ return Promise.all([...batches.values()].map((batch) => cb(batch))).then(
1643
+ (r) => r.flat()
1644
+ );
1645
+ };
1646
+ const storage = {
1647
+ // Item
1648
+ hasItem(key, opts = {}) {
1649
+ key = normalizeKey(key);
1650
+ const { relativeKey, driver } = getMount(key);
1651
+ return asyncCall(driver.hasItem, relativeKey, opts);
1652
+ },
1653
+ getItem(key, opts = {}) {
1654
+ key = normalizeKey(key);
1655
+ const { relativeKey, driver } = getMount(key);
1656
+ return asyncCall(driver.getItem, relativeKey, opts).then(
1657
+ (value) => destr(value)
1658
+ );
1659
+ },
1660
+ getItems(items, commonOptions = {}) {
1661
+ return runBatch(items, commonOptions, (batch) => {
1662
+ if (batch.driver.getItems) {
1663
+ return asyncCall(
1664
+ batch.driver.getItems,
1665
+ batch.items.map((item) => ({
1666
+ key: item.relativeKey,
1667
+ options: item.options
1668
+ })),
1669
+ commonOptions
1670
+ ).then(
1671
+ (r) => r.map((item) => ({
1672
+ key: joinKeys(batch.base, item.key),
1673
+ value: destr(item.value)
1674
+ }))
1675
+ );
1676
+ }
1677
+ return Promise.all(
1678
+ batch.items.map((item) => {
1679
+ return asyncCall(
1680
+ batch.driver.getItem,
1681
+ item.relativeKey,
1682
+ item.options
1683
+ ).then((value) => ({
1684
+ key: item.key,
1685
+ value: destr(value)
1686
+ }));
1687
+ })
1688
+ );
1689
+ });
1690
+ },
1691
+ getItemRaw(key, opts = {}) {
1692
+ key = normalizeKey(key);
1693
+ const { relativeKey, driver } = getMount(key);
1694
+ if (driver.getItemRaw) {
1695
+ return asyncCall(driver.getItemRaw, relativeKey, opts);
1696
+ }
1697
+ return asyncCall(driver.getItem, relativeKey, opts).then(
1698
+ (value) => deserializeRaw(value)
1699
+ );
1700
+ },
1701
+ async setItem(key, value, opts = {}) {
1702
+ if (value === void 0) {
1703
+ return storage.removeItem(key);
1704
+ }
1705
+ key = normalizeKey(key);
1706
+ const { relativeKey, driver } = getMount(key);
1707
+ if (!driver.setItem) {
1708
+ return;
1709
+ }
1710
+ await asyncCall(driver.setItem, relativeKey, stringify$1(value), opts);
1711
+ if (!driver.watch) {
1712
+ onChange("update", key);
1713
+ }
1714
+ },
1715
+ async setItems(items, commonOptions) {
1716
+ await runBatch(items, commonOptions, async (batch) => {
1717
+ if (batch.driver.setItems) {
1718
+ return asyncCall(
1719
+ batch.driver.setItems,
1720
+ batch.items.map((item) => ({
1721
+ key: item.relativeKey,
1722
+ value: stringify$1(item.value),
1723
+ options: item.options
1724
+ })),
1725
+ commonOptions
1726
+ );
1727
+ }
1728
+ if (!batch.driver.setItem) {
1729
+ return;
1730
+ }
1731
+ await Promise.all(
1732
+ batch.items.map((item) => {
1733
+ return asyncCall(
1734
+ batch.driver.setItem,
1735
+ item.relativeKey,
1736
+ stringify$1(item.value),
1737
+ item.options
1738
+ );
1739
+ })
1740
+ );
1741
+ });
1742
+ },
1743
+ async setItemRaw(key, value, opts = {}) {
1744
+ if (value === void 0) {
1745
+ return storage.removeItem(key, opts);
1746
+ }
1747
+ key = normalizeKey(key);
1748
+ const { relativeKey, driver } = getMount(key);
1749
+ if (driver.setItemRaw) {
1750
+ await asyncCall(driver.setItemRaw, relativeKey, value, opts);
1751
+ } else if (driver.setItem) {
1752
+ await asyncCall(driver.setItem, relativeKey, serializeRaw(value), opts);
1753
+ } else {
1754
+ return;
1755
+ }
1756
+ if (!driver.watch) {
1757
+ onChange("update", key);
1758
+ }
1759
+ },
1760
+ async removeItem(key, opts = {}) {
1761
+ if (typeof opts === "boolean") {
1762
+ opts = { removeMeta: opts };
1763
+ }
1764
+ key = normalizeKey(key);
1765
+ const { relativeKey, driver } = getMount(key);
1766
+ if (!driver.removeItem) {
1767
+ return;
1768
+ }
1769
+ await asyncCall(driver.removeItem, relativeKey, opts);
1770
+ if (opts.removeMeta || opts.removeMata) {
1771
+ await asyncCall(driver.removeItem, relativeKey + "$", opts);
1772
+ }
1773
+ if (!driver.watch) {
1774
+ onChange("remove", key);
1775
+ }
1776
+ },
1777
+ // Meta
1778
+ async getMeta(key, opts = {}) {
1779
+ if (typeof opts === "boolean") {
1780
+ opts = { nativeOnly: opts };
1781
+ }
1782
+ key = normalizeKey(key);
1783
+ const { relativeKey, driver } = getMount(key);
1784
+ const meta = /* @__PURE__ */ Object.create(null);
1785
+ if (driver.getMeta) {
1786
+ Object.assign(meta, await asyncCall(driver.getMeta, relativeKey, opts));
1787
+ }
1788
+ if (!opts.nativeOnly) {
1789
+ const value = await asyncCall(
1790
+ driver.getItem,
1791
+ relativeKey + "$",
1792
+ opts
1793
+ ).then((value_) => destr(value_));
1794
+ if (value && typeof value === "object") {
1795
+ if (typeof value.atime === "string") {
1796
+ value.atime = new Date(value.atime);
1797
+ }
1798
+ if (typeof value.mtime === "string") {
1799
+ value.mtime = new Date(value.mtime);
1800
+ }
1801
+ Object.assign(meta, value);
1802
+ }
1803
+ }
1804
+ return meta;
1805
+ },
1806
+ setMeta(key, value, opts = {}) {
1807
+ return this.setItem(key + "$", value, opts);
1808
+ },
1809
+ removeMeta(key, opts = {}) {
1810
+ return this.removeItem(key + "$", opts);
1811
+ },
1812
+ // Keys
1813
+ async getKeys(base, opts = {}) {
1814
+ base = normalizeBaseKey(base);
1815
+ const mounts = getMounts(base, true);
1816
+ let maskedMounts = [];
1817
+ const allKeys = [];
1818
+ let allMountsSupportMaxDepth = true;
1819
+ for (const mount of mounts) {
1820
+ if (!mount.driver.flags?.maxDepth) {
1821
+ allMountsSupportMaxDepth = false;
1822
+ }
1823
+ const rawKeys = await asyncCall(
1824
+ mount.driver.getKeys,
1825
+ mount.relativeBase,
1826
+ opts
1827
+ );
1828
+ for (const key of rawKeys) {
1829
+ const fullKey = mount.mountpoint + normalizeKey(key);
1830
+ if (!maskedMounts.some((p) => fullKey.startsWith(p))) {
1831
+ allKeys.push(fullKey);
1832
+ }
1833
+ }
1834
+ maskedMounts = [
1835
+ mount.mountpoint,
1836
+ ...maskedMounts.filter((p) => !p.startsWith(mount.mountpoint))
1837
+ ];
1838
+ }
1839
+ const shouldFilterByDepth = opts.maxDepth !== void 0 && !allMountsSupportMaxDepth;
1840
+ return allKeys.filter(
1841
+ (key) => (!shouldFilterByDepth || filterKeyByDepth(key, opts.maxDepth)) && filterKeyByBase(key, base)
1842
+ );
1843
+ },
1844
+ // Utils
1845
+ async clear(base, opts = {}) {
1846
+ base = normalizeBaseKey(base);
1847
+ await Promise.all(
1848
+ getMounts(base, false).map(async (m) => {
1849
+ if (m.driver.clear) {
1850
+ return asyncCall(m.driver.clear, m.relativeBase, opts);
1851
+ }
1852
+ if (m.driver.removeItem) {
1853
+ const keys = await m.driver.getKeys(m.relativeBase || "", opts);
1854
+ return Promise.all(
1855
+ keys.map((key) => m.driver.removeItem(key, opts))
1856
+ );
1857
+ }
1858
+ })
1859
+ );
1860
+ },
1861
+ async dispose() {
1862
+ await Promise.all(
1863
+ Object.values(context.mounts).map((driver) => dispose(driver))
1864
+ );
1865
+ },
1866
+ async watch(callback) {
1867
+ await startWatch();
1868
+ context.watchListeners.push(callback);
1869
+ return async () => {
1870
+ context.watchListeners = context.watchListeners.filter(
1871
+ (listener) => listener !== callback
1872
+ );
1873
+ if (context.watchListeners.length === 0) {
1874
+ await stopWatch();
1875
+ }
1876
+ };
1877
+ },
1878
+ async unwatch() {
1879
+ context.watchListeners = [];
1880
+ await stopWatch();
1881
+ },
1882
+ // Mount
1883
+ mount(base, driver) {
1884
+ base = normalizeBaseKey(base);
1885
+ if (base && context.mounts[base]) {
1886
+ throw new Error(`already mounted at ${base}`);
1887
+ }
1888
+ if (base) {
1889
+ context.mountpoints.push(base);
1890
+ context.mountpoints.sort((a, b) => b.length - a.length);
1891
+ }
1892
+ context.mounts[base] = driver;
1893
+ if (context.watching) {
1894
+ Promise.resolve(watch(driver, onChange, base)).then((unwatcher) => {
1895
+ context.unwatch[base] = unwatcher;
1896
+ }).catch(console.error);
1897
+ }
1898
+ return storage;
1899
+ },
1900
+ async unmount(base, _dispose = true) {
1901
+ base = normalizeBaseKey(base);
1902
+ if (!base || !context.mounts[base]) {
1903
+ return;
1904
+ }
1905
+ if (context.watching && base in context.unwatch) {
1906
+ context.unwatch[base]?.();
1907
+ delete context.unwatch[base];
1908
+ }
1909
+ if (_dispose) {
1910
+ await dispose(context.mounts[base]);
1911
+ }
1912
+ context.mountpoints = context.mountpoints.filter((key) => key !== base);
1913
+ delete context.mounts[base];
1914
+ },
1915
+ getMount(key = "") {
1916
+ key = normalizeKey(key) + ":";
1917
+ const m = getMount(key);
1918
+ return {
1919
+ driver: m.driver,
1920
+ base: m.base
1921
+ };
1922
+ },
1923
+ getMounts(base = "", opts = {}) {
1924
+ base = normalizeKey(base);
1925
+ const mounts = getMounts(base, opts.parents);
1926
+ return mounts.map((m) => ({
1927
+ driver: m.driver,
1928
+ base: m.mountpoint
1929
+ }));
1930
+ },
1931
+ // Aliases
1932
+ keys: (base, opts = {}) => storage.getKeys(base, opts),
1933
+ get: (key, opts = {}) => storage.getItem(key, opts),
1934
+ set: (key, value, opts = {}) => storage.setItem(key, value, opts),
1935
+ has: (key, opts = {}) => storage.hasItem(key, opts),
1936
+ del: (key, opts = {}) => storage.removeItem(key, opts),
1937
+ remove: (key, opts = {}) => storage.removeItem(key, opts)
1938
+ };
1939
+ return storage;
1940
+ }
1941
+ function watch(driver, onChange, base) {
1942
+ return driver.watch ? driver.watch((event, key) => onChange(event, base + key)) : () => {
1943
+ };
1944
+ }
1945
+ async function dispose(driver) {
1946
+ if (typeof driver.dispose === "function") {
1947
+ await asyncCall(driver.dispose);
1948
+ }
1949
+ }
1950
+
1951
+ const builtinDrivers = {
1952
+ "azure-app-configuration": "unstorage/drivers/azure-app-configuration",
1953
+ "azureAppConfiguration": "unstorage/drivers/azure-app-configuration",
1954
+ "azure-cosmos": "unstorage/drivers/azure-cosmos",
1955
+ "azureCosmos": "unstorage/drivers/azure-cosmos",
1956
+ "azure-key-vault": "unstorage/drivers/azure-key-vault",
1957
+ "azureKeyVault": "unstorage/drivers/azure-key-vault",
1958
+ "azure-storage-blob": "unstorage/drivers/azure-storage-blob",
1959
+ "azureStorageBlob": "unstorage/drivers/azure-storage-blob",
1960
+ "azure-storage-table": "unstorage/drivers/azure-storage-table",
1961
+ "azureStorageTable": "unstorage/drivers/azure-storage-table",
1962
+ "capacitor-preferences": "unstorage/drivers/capacitor-preferences",
1963
+ "capacitorPreferences": "unstorage/drivers/capacitor-preferences",
1964
+ "cloudflare-kv-binding": "unstorage/drivers/cloudflare-kv-binding",
1965
+ "cloudflareKVBinding": "unstorage/drivers/cloudflare-kv-binding",
1966
+ "cloudflare-kv-http": "unstorage/drivers/cloudflare-kv-http",
1967
+ "cloudflareKVHttp": "unstorage/drivers/cloudflare-kv-http",
1968
+ "cloudflare-r2-binding": "unstorage/drivers/cloudflare-r2-binding",
1969
+ "cloudflareR2Binding": "unstorage/drivers/cloudflare-r2-binding",
1970
+ "db0": "unstorage/drivers/db0",
1971
+ "deno-kv-node": "unstorage/drivers/deno-kv-node",
1972
+ "denoKVNode": "unstorage/drivers/deno-kv-node",
1973
+ "deno-kv": "unstorage/drivers/deno-kv",
1974
+ "denoKV": "unstorage/drivers/deno-kv",
1975
+ "fs-lite": "unstorage/drivers/fs-lite",
1976
+ "fsLite": "unstorage/drivers/fs-lite",
1977
+ "fs": "unstorage/drivers/fs",
1978
+ "github": "unstorage/drivers/github",
1979
+ "http": "unstorage/drivers/http",
1980
+ "indexedb": "unstorage/drivers/indexedb",
1981
+ "localstorage": "unstorage/drivers/localstorage",
1982
+ "lru-cache": "unstorage/drivers/lru-cache",
1983
+ "lruCache": "unstorage/drivers/lru-cache",
1984
+ "memory": "unstorage/drivers/memory",
1985
+ "mongodb": "unstorage/drivers/mongodb",
1986
+ "netlify-blobs": "unstorage/drivers/netlify-blobs",
1987
+ "netlifyBlobs": "unstorage/drivers/netlify-blobs",
1988
+ "null": "unstorage/drivers/null",
1989
+ "overlay": "unstorage/drivers/overlay",
1990
+ "planetscale": "unstorage/drivers/planetscale",
1991
+ "redis": "unstorage/drivers/redis",
1992
+ "s3": "unstorage/drivers/s3",
1993
+ "session-storage": "unstorage/drivers/session-storage",
1994
+ "sessionStorage": "unstorage/drivers/session-storage",
1995
+ "uploadthing": "unstorage/drivers/uploadthing",
1996
+ "upstash": "unstorage/drivers/upstash",
1997
+ "vercel-blob": "unstorage/drivers/vercel-blob",
1998
+ "vercelBlob": "unstorage/drivers/vercel-blob",
1999
+ "vercel-kv": "unstorage/drivers/vercel-kv",
2000
+ "vercelKV": "unstorage/drivers/vercel-kv"
2001
+ };
2002
+
2003
+ const PERSIST_SYMBOL = Symbol();
2004
+ const DEFAULT_COOKIE_NAME = "astro-session";
2005
+ const VALID_COOKIE_REGEX = /^[\w-]+$/;
2006
+ const unflatten = (parsed, _) => {
2007
+ return unflatten$1(parsed, {
2008
+ URL: (href) => new URL(href)
2009
+ });
1707
2010
  };
1708
2011
  const stringify = (data, _) => {
1709
- return stringify$1(data, {
2012
+ return stringify$2(data, {
1710
2013
  // Support URL objects
1711
2014
  URL: (val) => val instanceof URL && val.href
1712
2015
  });
@@ -1739,10 +2042,11 @@ class AstroSession {
1739
2042
  // When we load the data from storage, we need to merge it with the local partial data,
1740
2043
  // preserving in-memory changes and deletions.
1741
2044
  #partial = true;
2045
+ static #sharedStorage = /* @__PURE__ */ new Map();
1742
2046
  constructor(cookies, {
1743
2047
  cookie: cookieConfig = DEFAULT_COOKIE_NAME,
1744
2048
  ...config
1745
- }) {
2049
+ }, runtimeMode) {
1746
2050
  this.#cookies = cookies;
1747
2051
  let cookieConfigObject;
1748
2052
  if (typeof cookieConfig === "object") {
@@ -1754,7 +2058,7 @@ class AstroSession {
1754
2058
  }
1755
2059
  this.#cookieConfig = {
1756
2060
  sameSite: "lax",
1757
- secure: true,
2061
+ secure: runtimeMode === "production",
1758
2062
  path: "/",
1759
2063
  ...cookieConfigObject,
1760
2064
  httpOnly: true
@@ -1906,6 +2210,19 @@ class AstroSession {
1906
2210
  get sessionID() {
1907
2211
  return this.#sessionID;
1908
2212
  }
2213
+ /**
2214
+ * Loads a session from storage with the given ID, and replaces the current session.
2215
+ * Any changes made to the current session will be lost.
2216
+ * This is not normally needed, as the session is automatically loaded using the cookie.
2217
+ * However it can be used to restore a session where the ID has been recorded somewhere
2218
+ * else (e.g. in a database).
2219
+ */
2220
+ async load(sessionID) {
2221
+ this.#sessionID = sessionID;
2222
+ this.#data = void 0;
2223
+ await this.#setCookie();
2224
+ await this.#ensureData();
2225
+ }
1909
2226
  /**
1910
2227
  * Sets the session cookie.
1911
2228
  */
@@ -2000,6 +2317,10 @@ class AstroSession {
2000
2317
  if (this.#storage) {
2001
2318
  return this.#storage;
2002
2319
  }
2320
+ if (AstroSession.#sharedStorage.has(this.#config.driver)) {
2321
+ this.#storage = AstroSession.#sharedStorage.get(this.#config.driver);
2322
+ return this.#storage;
2323
+ }
2003
2324
  if (this.#config.driver === "test") {
2004
2325
  this.#storage = this.#config.options.mockStorage;
2005
2326
  return this.#storage;
@@ -2018,12 +2339,14 @@ class AstroSession {
2018
2339
  });
2019
2340
  }
2020
2341
  let driver = null;
2021
- const driverPackage = await resolveSessionDriver(this.#config.driver);
2022
2342
  try {
2023
2343
  if (this.#config.driverModule) {
2024
2344
  driver = (await this.#config.driverModule()).default;
2025
- } else if (driverPackage) {
2026
- driver = (await import(driverPackage)).default;
2345
+ } else if (this.#config.driver) {
2346
+ const driverName = resolveSessionDriverName(this.#config.driver);
2347
+ if (driverName) {
2348
+ driver = (await import(driverName)).default;
2349
+ }
2027
2350
  }
2028
2351
  } catch (err) {
2029
2352
  if (err.code === "ERR_MODULE_NOT_FOUND") {
@@ -2031,7 +2354,7 @@ class AstroSession {
2031
2354
  {
2032
2355
  ...SessionStorageInitError,
2033
2356
  message: SessionStorageInitError.message(
2034
- err.message.includes(`Cannot find package '${driverPackage}'`) ? "The driver module could not be found." : err.message,
2357
+ err.message.includes(`Cannot find package`) ? "The driver module could not be found." : err.message,
2035
2358
  this.#config.driver
2036
2359
  )
2037
2360
  },
@@ -2053,6 +2376,7 @@ class AstroSession {
2053
2376
  this.#storage = createStorage({
2054
2377
  driver: driver(this.#config.options)
2055
2378
  });
2379
+ AstroSession.#sharedStorage.set(this.#config.driver, this.#storage);
2056
2380
  return this.#storage;
2057
2381
  } catch (err) {
2058
2382
  throw new AstroError(
@@ -2065,16 +2389,16 @@ class AstroSession {
2065
2389
  }
2066
2390
  }
2067
2391
  }
2068
- async function resolveSessionDriver(driver) {
2392
+ function resolveSessionDriverName(driver) {
2069
2393
  if (!driver) {
2070
2394
  return null;
2071
2395
  }
2072
2396
  try {
2073
2397
  if (driver === "fs") {
2074
- return await import.meta.resolve(builtinDrivers.fsLite);
2398
+ return builtinDrivers.fsLite;
2075
2399
  }
2076
2400
  if (driver in builtinDrivers) {
2077
- return await import.meta.resolve(builtinDrivers[driver]);
2401
+ return builtinDrivers[driver];
2078
2402
  }
2079
2403
  } catch {
2080
2404
  return null;
@@ -2084,10 +2408,11 @@ async function resolveSessionDriver(driver) {
2084
2408
 
2085
2409
  const apiContextRoutesSymbol = Symbol.for("context.routes");
2086
2410
  class RenderContext {
2087
- constructor(pipeline, locals, middleware, pathname, request, routeData, status, clientAddress, cookies = new AstroCookies(request), params = getParams(routeData, pathname), url = new URL(request.url), props = {}, partial = void 0, session = pipeline.manifest.sessionConfig ? new AstroSession(cookies, pipeline.manifest.sessionConfig) : void 0) {
2411
+ constructor(pipeline, locals, middleware, actions, pathname, request, routeData, status, clientAddress, cookies = new AstroCookies(request), params = getParams(routeData, pathname), url = new URL(request.url), props = {}, partial = void 0, session = pipeline.manifest.sessionConfig ? new AstroSession(cookies, pipeline.manifest.sessionConfig, pipeline.runtimeMode) : void 0) {
2088
2412
  this.pipeline = pipeline;
2089
2413
  this.locals = locals;
2090
2414
  this.middleware = middleware;
2415
+ this.actions = actions;
2091
2416
  this.pathname = pathname;
2092
2417
  this.request = request;
2093
2418
  this.routeData = routeData;
@@ -2108,6 +2433,7 @@ class RenderContext {
2108
2433
  * A safety net in case of loops
2109
2434
  */
2110
2435
  counter = 0;
2436
+ result = void 0;
2111
2437
  static async create({
2112
2438
  locals = {},
2113
2439
  middleware,
@@ -2118,14 +2444,17 @@ class RenderContext {
2118
2444
  clientAddress,
2119
2445
  status = 200,
2120
2446
  props,
2121
- partial = void 0
2447
+ partial = void 0,
2448
+ actions
2122
2449
  }) {
2123
2450
  const pipelineMiddleware = await pipeline.getMiddleware();
2451
+ const pipelineActions = actions ?? await pipeline.getActions();
2124
2452
  setOriginPathname(request, pathname);
2125
2453
  return new RenderContext(
2126
2454
  pipeline,
2127
2455
  locals,
2128
2456
  sequence(...pipeline.internalMiddleware, middleware ?? pipelineMiddleware),
2457
+ pipelineActions,
2129
2458
  pathname,
2130
2459
  request,
2131
2460
  routeData,
@@ -2161,7 +2490,8 @@ class RenderContext {
2161
2490
  serverLike,
2162
2491
  base: manifest.base
2163
2492
  });
2164
- const apiContext = this.createAPIContext(props);
2493
+ const actionApiContext = this.createActionAPIContext();
2494
+ const apiContext = this.createAPIContext(props, actionApiContext);
2165
2495
  this.counter++;
2166
2496
  if (this.counter === 4) {
2167
2497
  return new Response("Loop Detected", {
@@ -2172,6 +2502,7 @@ class RenderContext {
2172
2502
  }
2173
2503
  const lastNext = async (ctx, payload) => {
2174
2504
  if (payload) {
2505
+ const oldPathname = this.pathname;
2175
2506
  pipeline.logger.debug("router", "Called rewriting to:", payload);
2176
2507
  const {
2177
2508
  routeData,
@@ -2202,12 +2533,19 @@ class RenderContext {
2202
2533
  }
2203
2534
  this.isRewriting = true;
2204
2535
  this.url = new URL(this.request.url);
2205
- this.cookies = new AstroCookies(this.request);
2206
2536
  this.params = getParams(routeData, pathname);
2207
2537
  this.pathname = pathname;
2208
2538
  this.status = 200;
2539
+ setOriginPathname(this.request, oldPathname);
2209
2540
  }
2210
2541
  let response2;
2542
+ if (!ctx.isPrerendered) {
2543
+ const { action, setActionResult, serializeActionResult } = getActionContext(ctx);
2544
+ if (action?.calledFrom === "form") {
2545
+ const actionResult = await action.handler();
2546
+ setActionResult(action.name, serializeActionResult(actionResult));
2547
+ }
2548
+ }
2211
2549
  switch (this.routeData.type) {
2212
2550
  case "endpoint": {
2213
2551
  response2 = await renderEndpoint(
@@ -2221,10 +2559,10 @@ class RenderContext {
2221
2559
  case "redirect":
2222
2560
  return renderRedirect(this);
2223
2561
  case "page": {
2224
- const result = await this.createResult(componentInstance);
2562
+ this.result = await this.createResult(componentInstance, actionApiContext);
2225
2563
  try {
2226
2564
  response2 = await renderPage(
2227
- result,
2565
+ this.result,
2228
2566
  componentInstance?.default,
2229
2567
  props,
2230
2568
  slots,
@@ -2232,7 +2570,7 @@ class RenderContext {
2232
2570
  this.routeData
2233
2571
  );
2234
2572
  } catch (e) {
2235
- result.cancelled = true;
2573
+ this.result.cancelled = true;
2236
2574
  throw e;
2237
2575
  }
2238
2576
  response2.headers.set(ROUTE_TYPE_HEADER, "page");
@@ -2264,8 +2602,7 @@ class RenderContext {
2264
2602
  attachCookiesToResponse(response, cookies);
2265
2603
  return response;
2266
2604
  }
2267
- createAPIContext(props) {
2268
- const context = this.createActionAPIContext();
2605
+ createAPIContext(props, context) {
2269
2606
  const redirect = (path, status = 302) => new Response(null, { status, headers: { Location: path } });
2270
2607
  Reflect.set(context, apiContextRoutesSymbol, this.pipeline);
2271
2608
  return Object.assign(context, {
@@ -2277,11 +2614,12 @@ class RenderContext {
2277
2614
  }
2278
2615
  async #executeRewrite(reroutePayload) {
2279
2616
  this.pipeline.logger.debug("router", "Calling rewrite: ", reroutePayload);
2617
+ const oldPathname = this.pathname;
2280
2618
  const { routeData, componentInstance, newUrl, pathname } = await this.pipeline.tryRewrite(
2281
2619
  reroutePayload,
2282
2620
  this.request
2283
2621
  );
2284
- if (this.pipeline.serverLike === true && this.routeData.prerender === false && routeData.prerender === true) {
2622
+ if (this.pipeline.serverLike && !this.routeData.prerender && routeData.prerender) {
2285
2623
  throw new AstroError({
2286
2624
  ...ForbiddenRewrite,
2287
2625
  message: ForbiddenRewrite.message(this.pathname, pathname, routeData.component),
@@ -2307,11 +2645,12 @@ class RenderContext {
2307
2645
  this.pathname = pathname;
2308
2646
  this.isRewriting = true;
2309
2647
  this.status = 200;
2648
+ setOriginPathname(this.request, oldPathname);
2310
2649
  return await this.render(componentInstance);
2311
2650
  }
2312
2651
  createActionAPIContext() {
2313
2652
  const renderContext = this;
2314
- const { cookies, params, pipeline, url, session } = this;
2653
+ const { cookies, params, pipeline, url } = this;
2315
2654
  const generator = `Astro v${ASTRO_VERSION}`;
2316
2655
  const rewrite = async (reroutePayload) => {
2317
2656
  return await this.#executeRewrite(reroutePayload);
@@ -2347,10 +2686,56 @@ class RenderContext {
2347
2686
  get originPathname() {
2348
2687
  return getOriginPathname(renderContext.request);
2349
2688
  },
2350
- session
2689
+ get session() {
2690
+ if (this.isPrerendered) {
2691
+ pipeline.logger.warn(
2692
+ "session",
2693
+ `context.session was used when rendering the route ${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/`
2694
+ );
2695
+ return void 0;
2696
+ }
2697
+ if (!renderContext.session) {
2698
+ pipeline.logger.warn(
2699
+ "session",
2700
+ `context.session was used when rendering the route ${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/`
2701
+ );
2702
+ return void 0;
2703
+ }
2704
+ return renderContext.session;
2705
+ },
2706
+ insertDirective(payload) {
2707
+ if (!pipeline.manifest.csp) {
2708
+ throw new AstroError(CspNotEnabled);
2709
+ }
2710
+ renderContext.result?.directives.push(payload);
2711
+ },
2712
+ insertScriptResource(resource) {
2713
+ if (!pipeline.manifest.csp) {
2714
+ throw new AstroError(CspNotEnabled);
2715
+ }
2716
+ renderContext.result?.scriptResources.push(resource);
2717
+ },
2718
+ insertStyleResource(resource) {
2719
+ if (!pipeline.manifest.csp) {
2720
+ throw new AstroError(CspNotEnabled);
2721
+ }
2722
+ renderContext.result?.styleResources.push(resource);
2723
+ },
2724
+ insertStyleHash(hash) {
2725
+ if (!pipeline.manifest.csp) {
2726
+ throw new AstroError(CspNotEnabled);
2727
+ }
2728
+ renderContext.result?.styleHashes.push(hash);
2729
+ },
2730
+ insertScriptHash(hash) {
2731
+ if (!!pipeline.manifest.csp === false) {
2732
+ throw new AstroError(CspNotEnabled);
2733
+ }
2734
+ renderContext.result?.scriptHashes.push(hash);
2735
+ }
2351
2736
  };
2352
2737
  }
2353
- async createResult(mod) {
2738
+ async createResult(mod, ctx) {
2354
2739
  const { cookies, pathname, pipeline, routeData, status } = this;
2355
2740
  const { clientDirectives, inlinedScripts, compressHTML, manifest, renderers, resolve } = pipeline;
2356
2741
  const { links, scripts, styles } = await pipeline.headElements(routeData);
@@ -2379,7 +2764,7 @@ class RenderContext {
2379
2764
  compressHTML,
2380
2765
  cookies,
2381
2766
  /** This function returns the `Astro` faux-global */
2382
- createAstro: (astroGlobal, props, slots) => this.createAstro(result, astroGlobal, props, slots),
2767
+ createAstro: (astroGlobal, props, slots) => this.createAstro(result, astroGlobal, props, slots, ctx),
2383
2768
  links,
2384
2769
  params: this.params,
2385
2770
  partial,
@@ -2400,10 +2785,23 @@ class RenderContext {
2400
2785
  hasRenderedHead: false,
2401
2786
  renderedScripts: /* @__PURE__ */ new Set(),
2402
2787
  hasDirectives: /* @__PURE__ */ new Set(),
2788
+ hasRenderedServerIslandRuntime: false,
2403
2789
  headInTree: false,
2404
2790
  extraHead: [],
2791
+ extraStyleHashes: [],
2792
+ extraScriptHashes: [],
2405
2793
  propagators: /* @__PURE__ */ new Set()
2406
- }
2794
+ },
2795
+ cspDestination: manifest.csp?.cspDestination ?? (routeData.prerender ? "meta" : "header"),
2796
+ shouldInjectCspMetaTags: !!manifest.csp,
2797
+ cspAlgorithm: manifest.csp?.algorithm ?? "SHA-256",
2798
+ // The following arrays must be cloned, otherwise they become mutable across routes.
2799
+ scriptHashes: manifest.csp?.scriptHashes ? [...manifest.csp.scriptHashes] : [],
2800
+ scriptResources: manifest.csp?.scriptResources ? [...manifest.csp.scriptResources] : [],
2801
+ styleHashes: manifest.csp?.styleHashes ? [...manifest.csp.styleHashes] : [],
2802
+ styleResources: manifest.csp?.styleResources ? [...manifest.csp.styleResources] : [],
2803
+ directives: manifest.csp?.directives ? [...manifest.csp.directives] : [],
2804
+ isStrictDynamic: manifest.csp?.isStrictDynamic ?? false
2407
2805
  };
2408
2806
  return result;
2409
2807
  }
@@ -2416,17 +2814,19 @@ class RenderContext {
2416
2814
  *
2417
2815
  * 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.
2418
2816
  */
2419
- createAstro(result, astroStaticPartial, props, slotValues) {
2817
+ createAstro(result, astroStaticPartial, props, slotValues, apiContext) {
2420
2818
  let astroPagePartial;
2421
2819
  if (this.isRewriting) {
2422
2820
  astroPagePartial = this.#astroPagePartial = this.createAstroPagePartial(
2423
2821
  result,
2424
- astroStaticPartial
2822
+ astroStaticPartial,
2823
+ apiContext
2425
2824
  );
2426
2825
  } else {
2427
2826
  astroPagePartial = this.#astroPagePartial ??= this.createAstroPagePartial(
2428
2827
  result,
2429
- astroStaticPartial
2828
+ astroStaticPartial,
2829
+ apiContext
2430
2830
  );
2431
2831
  }
2432
2832
  const astroComponentPartial = { props, self: null };
@@ -2449,9 +2849,9 @@ class RenderContext {
2449
2849
  });
2450
2850
  return Astro;
2451
2851
  }
2452
- createAstroPagePartial(result, astroStaticPartial) {
2852
+ createAstroPagePartial(result, astroStaticPartial, apiContext) {
2453
2853
  const renderContext = this;
2454
- const { cookies, locals, params, pipeline, url, session } = this;
2854
+ const { cookies, locals, params, pipeline, url } = this;
2455
2855
  const { response } = result;
2456
2856
  const redirect = (path, status = 302) => {
2457
2857
  if (this.request[responseSentSymbol$1]) {
@@ -2464,13 +2864,30 @@ class RenderContext {
2464
2864
  const rewrite = async (reroutePayload) => {
2465
2865
  return await this.#executeRewrite(reroutePayload);
2466
2866
  };
2867
+ const callAction = createCallAction(apiContext);
2467
2868
  return {
2468
2869
  generator: astroStaticPartial.generator,
2469
2870
  glob: astroStaticPartial.glob,
2470
2871
  routePattern: this.routeData.route,
2471
2872
  isPrerendered: this.routeData.prerender,
2472
2873
  cookies,
2473
- session,
2874
+ get session() {
2875
+ if (this.isPrerendered) {
2876
+ pipeline.logger.warn(
2877
+ "session",
2878
+ `Astro.session was used when rendering the route ${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/`
2879
+ );
2880
+ return void 0;
2881
+ }
2882
+ if (!renderContext.session) {
2883
+ pipeline.logger.warn(
2884
+ "session",
2885
+ `Astro.session was used when rendering the route ${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/`
2886
+ );
2887
+ return void 0;
2888
+ }
2889
+ return renderContext.session;
2890
+ },
2474
2891
  get clientAddress() {
2475
2892
  return renderContext.getClientAddress();
2476
2893
  },
@@ -2492,18 +2909,51 @@ class RenderContext {
2492
2909
  site: pipeline.site,
2493
2910
  getActionResult: createGetActionResult(locals),
2494
2911
  get callAction() {
2495
- return createCallAction(this);
2912
+ return callAction;
2496
2913
  },
2497
2914
  url,
2498
2915
  get originPathname() {
2499
2916
  return getOriginPathname(renderContext.request);
2917
+ },
2918
+ insertDirective(payload) {
2919
+ if (!pipeline.manifest.csp) {
2920
+ throw new AstroError(CspNotEnabled);
2921
+ }
2922
+ renderContext.result?.directives.push(payload);
2923
+ },
2924
+ insertScriptResource(resource) {
2925
+ if (!pipeline.manifest.csp) {
2926
+ throw new AstroError(CspNotEnabled);
2927
+ }
2928
+ renderContext.result?.scriptResources.push(resource);
2929
+ },
2930
+ insertStyleResource(resource) {
2931
+ if (!pipeline.manifest.csp) {
2932
+ throw new AstroError(CspNotEnabled);
2933
+ }
2934
+ renderContext.result?.styleResources.push(resource);
2935
+ },
2936
+ insertStyleHash(hash) {
2937
+ if (!pipeline.manifest.csp) {
2938
+ throw new AstroError(CspNotEnabled);
2939
+ }
2940
+ renderContext.result?.styleHashes.push(hash);
2941
+ },
2942
+ insertScriptHash(hash) {
2943
+ if (!!pipeline.manifest.csp === false) {
2944
+ throw new AstroError(CspNotEnabled);
2945
+ }
2946
+ renderContext.result?.scriptHashes.push(hash);
2500
2947
  }
2501
2948
  };
2502
2949
  }
2503
2950
  getClientAddress() {
2504
2951
  const { pipeline, request, routeData, clientAddress } = this;
2505
2952
  if (routeData.prerender) {
2506
- throw new AstroError(PrerenderClientAddressNotAvailable);
2953
+ throw new AstroError({
2954
+ ...PrerenderClientAddressNotAvailable,
2955
+ message: PrerenderClientAddressNotAvailable.message(routeData.component)
2956
+ });
2507
2957
  }
2508
2958
  if (clientAddress) {
2509
2959
  return clientAddress;
@@ -2581,1041 +3031,69 @@ class RenderContext {
2581
3031
  }
2582
3032
  }
2583
3033
 
2584
- function getAssetsPrefix(fileExtension, assetsPrefix) {
2585
- if (!assetsPrefix) return "";
2586
- if (typeof assetsPrefix === "string") return assetsPrefix;
2587
- const dotLessFileExtension = fileExtension.slice(1);
2588
- if (assetsPrefix[dotLessFileExtension]) {
2589
- return assetsPrefix[dotLessFileExtension];
3034
+ function sequence(...handlers) {
3035
+ const filtered = handlers.filter((h) => !!h);
3036
+ const length = filtered.length;
3037
+ if (!length) {
3038
+ return defineMiddleware((_context, next) => {
3039
+ return next();
3040
+ });
2590
3041
  }
2591
- return assetsPrefix.fallback;
3042
+ return defineMiddleware((context, next) => {
3043
+ let carriedPayload = void 0;
3044
+ return applyHandle(0, context);
3045
+ function applyHandle(i, handleContext) {
3046
+ const handle = filtered[i];
3047
+ const result = handle(handleContext, async (payload) => {
3048
+ if (i < length - 1) {
3049
+ if (payload) {
3050
+ let newRequest;
3051
+ if (payload instanceof Request) {
3052
+ newRequest = payload;
3053
+ } else if (payload instanceof URL) {
3054
+ newRequest = new Request(payload, handleContext.request.clone());
3055
+ } else {
3056
+ newRequest = new Request(
3057
+ new URL(payload, handleContext.url.origin),
3058
+ handleContext.request.clone()
3059
+ );
3060
+ }
3061
+ const oldPathname = handleContext.url.pathname;
3062
+ const pipeline = Reflect.get(handleContext, apiContextRoutesSymbol);
3063
+ const { routeData, pathname } = await pipeline.tryRewrite(
3064
+ payload,
3065
+ handleContext.request
3066
+ );
3067
+ if (pipeline.serverLike === true && handleContext.isPrerendered === false && routeData.prerender === true) {
3068
+ throw new AstroError({
3069
+ ...ForbiddenRewrite,
3070
+ message: ForbiddenRewrite.message(
3071
+ handleContext.url.pathname,
3072
+ pathname,
3073
+ routeData.component
3074
+ ),
3075
+ hint: ForbiddenRewrite.hint(routeData.component)
3076
+ });
3077
+ }
3078
+ carriedPayload = payload;
3079
+ handleContext.request = newRequest;
3080
+ handleContext.url = new URL(newRequest.url);
3081
+ handleContext.cookies = new AstroCookies(newRequest);
3082
+ handleContext.params = getParams(routeData, pathname);
3083
+ setOriginPathname(handleContext.request, oldPathname);
3084
+ }
3085
+ return applyHandle(i + 1, handleContext);
3086
+ } else {
3087
+ return next(payload ?? carriedPayload);
3088
+ }
3089
+ });
3090
+ return result;
3091
+ }
3092
+ });
2592
3093
  }
2593
3094
 
2594
- function createAssetLink(href, base, assetsPrefix) {
2595
- if (assetsPrefix) {
2596
- const pf = getAssetsPrefix(fileExtension(href), assetsPrefix);
2597
- return joinPaths(pf, slash(href));
2598
- } else if (base) {
2599
- return prependForwardSlash$1(joinPaths(base, slash(href)));
2600
- } else {
2601
- return href;
2602
- }
2603
- }
2604
- function createStylesheetElement(stylesheet, base, assetsPrefix) {
2605
- if (stylesheet.type === "inline") {
2606
- return {
2607
- props: {},
2608
- children: stylesheet.content
2609
- };
2610
- } else {
2611
- return {
2612
- props: {
2613
- rel: "stylesheet",
2614
- href: createAssetLink(stylesheet.src, base, assetsPrefix)
2615
- },
2616
- children: ""
2617
- };
2618
- }
2619
- }
2620
- function createStylesheetElementSet(stylesheets, base, assetsPrefix) {
2621
- return new Set(stylesheets.map((s) => createStylesheetElement(s, base, assetsPrefix)));
2622
- }
2623
- function createModuleScriptElement(script, base, assetsPrefix) {
2624
- if (script.type === "external") {
2625
- return createModuleScriptElementWithSrc(script.value, base, assetsPrefix);
2626
- } else {
2627
- return {
2628
- props: {
2629
- type: "module"
2630
- },
2631
- children: script.value
2632
- };
2633
- }
2634
- }
2635
- function createModuleScriptElementWithSrc(src, base, assetsPrefix) {
2636
- return {
2637
- props: {
2638
- type: "module",
2639
- src: createAssetLink(src, base, assetsPrefix)
2640
- },
2641
- children: ""
2642
- };
2643
- }
2644
-
2645
- function redirectTemplate({ status, location, from }) {
2646
- const delay = status === 302 ? 2 : 0;
2647
- return `<!doctype html>
2648
- <title>Redirecting to: ${location}</title>
2649
- <meta http-equiv="refresh" content="${delay};url=${location}">
2650
- <meta name="robots" content="noindex">
2651
- <link rel="canonical" href="${location}">
2652
- <body>
2653
- <a href="${location}">Redirecting ${from ? `from <code>${from}</code> ` : ""}to <code>${location}</code></a>
2654
- </body>`;
2655
- }
2656
-
2657
- class AppPipeline extends Pipeline {
2658
- #manifestData;
2659
- static create(manifestData, {
2660
- logger,
2661
- manifest,
2662
- runtimeMode,
2663
- renderers,
2664
- resolve,
2665
- serverLike,
2666
- streaming,
2667
- defaultRoutes
2668
- }) {
2669
- const pipeline = new AppPipeline(
2670
- logger,
2671
- manifest,
2672
- runtimeMode,
2673
- renderers,
2674
- resolve,
2675
- serverLike,
2676
- streaming,
2677
- void 0,
2678
- void 0,
2679
- void 0,
2680
- void 0,
2681
- void 0,
2682
- void 0,
2683
- void 0,
2684
- void 0,
2685
- defaultRoutes
2686
- );
2687
- pipeline.#manifestData = manifestData;
2688
- return pipeline;
2689
- }
2690
- headElements(routeData) {
2691
- const routeInfo = this.manifest.routes.find((route) => route.routeData === routeData);
2692
- const links = /* @__PURE__ */ new Set();
2693
- const scripts = /* @__PURE__ */ new Set();
2694
- const styles = createStylesheetElementSet(routeInfo?.styles ?? []);
2695
- for (const script of routeInfo?.scripts ?? []) {
2696
- if ("stage" in script) {
2697
- if (script.stage === "head-inline") {
2698
- scripts.add({
2699
- props: {},
2700
- children: script.children
2701
- });
2702
- }
2703
- } else {
2704
- scripts.add(createModuleScriptElement(script));
2705
- }
2706
- }
2707
- return { links, styles, scripts };
2708
- }
2709
- componentMetadata() {
2710
- }
2711
- async getComponentByRoute(routeData) {
2712
- const module = await this.getModuleForRoute(routeData);
2713
- return module.page();
2714
- }
2715
- async tryRewrite(payload, request) {
2716
- const { newUrl, pathname, routeData } = findRouteToRewrite({
2717
- payload,
2718
- request,
2719
- routes: this.manifest?.routes.map((r) => r.routeData),
2720
- trailingSlash: this.manifest.trailingSlash,
2721
- buildFormat: this.manifest.buildFormat,
2722
- base: this.manifest.base
2723
- });
2724
- const componentInstance = await this.getComponentByRoute(routeData);
2725
- return { newUrl, pathname, componentInstance, routeData };
2726
- }
2727
- async getModuleForRoute(route) {
2728
- for (const defaultRoute of this.defaultRoutes) {
2729
- if (route.component === defaultRoute.component) {
2730
- return {
2731
- page: () => Promise.resolve(defaultRoute.instance),
2732
- renderers: []
2733
- };
2734
- }
2735
- }
2736
- if (route.type === "redirect") {
2737
- return RedirectSinglePageBuiltModule;
2738
- } else {
2739
- if (this.manifest.pageMap) {
2740
- const importComponentInstance = this.manifest.pageMap.get(route.component);
2741
- if (!importComponentInstance) {
2742
- throw new Error(
2743
- `Unexpectedly unable to find a component instance for route ${route.route}`
2744
- );
2745
- }
2746
- return await importComponentInstance();
2747
- } else if (this.manifest.pageModule) {
2748
- return this.manifest.pageModule;
2749
- }
2750
- throw new Error(
2751
- "Astro couldn't find the correct page to render, probably because it wasn't correctly mapped for SSR usage. This is an internal error, please file an issue."
2752
- );
2753
- }
2754
- }
2755
- }
2756
-
2757
- class App {
2758
- #manifest;
2759
- #manifestData;
2760
- #logger = new Logger({
2761
- dest: consoleLogDestination,
2762
- level: "info"
2763
- });
2764
- #baseWithoutTrailingSlash;
2765
- #pipeline;
2766
- #adapterLogger;
2767
- #renderOptionsDeprecationWarningShown = false;
2768
- constructor(manifest, streaming = true) {
2769
- this.#manifest = manifest;
2770
- this.#manifestData = {
2771
- routes: manifest.routes.map((route) => route.routeData)
2772
- };
2773
- ensure404Route(this.#manifestData);
2774
- this.#baseWithoutTrailingSlash = removeTrailingForwardSlash(this.#manifest.base);
2775
- this.#pipeline = this.#createPipeline(this.#manifestData, streaming);
2776
- this.#adapterLogger = new AstroIntegrationLogger(
2777
- this.#logger.options,
2778
- this.#manifest.adapterName
2779
- );
2780
- }
2781
- getAdapterLogger() {
2782
- return this.#adapterLogger;
2783
- }
2784
- /**
2785
- * Creates a pipeline by reading the stored manifest
2786
- *
2787
- * @param manifestData
2788
- * @param streaming
2789
- * @private
2790
- */
2791
- #createPipeline(manifestData, streaming = false) {
2792
- return AppPipeline.create(manifestData, {
2793
- logger: this.#logger,
2794
- manifest: this.#manifest,
2795
- runtimeMode: "production",
2796
- renderers: this.#manifest.renderers,
2797
- defaultRoutes: createDefaultRoutes(this.#manifest),
2798
- resolve: async (specifier) => {
2799
- if (!(specifier in this.#manifest.entryModules)) {
2800
- throw new Error(`Unable to resolve [${specifier}]`);
2801
- }
2802
- const bundlePath = this.#manifest.entryModules[specifier];
2803
- if (bundlePath.startsWith("data:") || bundlePath.length === 0) {
2804
- return bundlePath;
2805
- } else {
2806
- return createAssetLink(bundlePath, this.#manifest.base, this.#manifest.assetsPrefix);
2807
- }
2808
- },
2809
- serverLike: true,
2810
- streaming
2811
- });
2812
- }
2813
- set setManifestData(newManifestData) {
2814
- this.#manifestData = newManifestData;
2815
- }
2816
- removeBase(pathname) {
2817
- if (pathname.startsWith(this.#manifest.base)) {
2818
- return pathname.slice(this.#baseWithoutTrailingSlash.length + 1);
2819
- }
2820
- return pathname;
2821
- }
2822
- /**
2823
- * It removes the base from the request URL, prepends it with a forward slash and attempts to decoded it.
2824
- *
2825
- * If the decoding fails, it logs the error and return the pathname as is.
2826
- * @param request
2827
- * @private
2828
- */
2829
- #getPathnameFromRequest(request) {
2830
- const url = new URL(request.url);
2831
- const pathname = prependForwardSlash$1(this.removeBase(url.pathname));
2832
- try {
2833
- return decodeURI(pathname);
2834
- } catch (e) {
2835
- this.getAdapterLogger().error(e.toString());
2836
- return pathname;
2837
- }
2838
- }
2839
- match(request) {
2840
- const url = new URL(request.url);
2841
- if (this.#manifest.assets.has(url.pathname)) return void 0;
2842
- let pathname = this.#computePathnameFromDomain(request);
2843
- if (!pathname) {
2844
- pathname = prependForwardSlash$1(this.removeBase(url.pathname));
2845
- }
2846
- let routeData = matchRoute(decodeURI(pathname), this.#manifestData);
2847
- if (!routeData || routeData.prerender) return void 0;
2848
- return routeData;
2849
- }
2850
- #computePathnameFromDomain(request) {
2851
- let pathname = void 0;
2852
- const url = new URL(request.url);
2853
- if (this.#manifest.i18n && (this.#manifest.i18n.strategy === "domains-prefix-always" || this.#manifest.i18n.strategy === "domains-prefix-other-locales" || this.#manifest.i18n.strategy === "domains-prefix-always-no-redirect")) {
2854
- let host = request.headers.get("X-Forwarded-Host");
2855
- let protocol = request.headers.get("X-Forwarded-Proto");
2856
- if (protocol) {
2857
- protocol = protocol + ":";
2858
- } else {
2859
- protocol = url.protocol;
2860
- }
2861
- if (!host) {
2862
- host = request.headers.get("Host");
2863
- }
2864
- if (host && protocol) {
2865
- host = host.split(":")[0];
2866
- try {
2867
- let locale;
2868
- const hostAsUrl = new URL(`${protocol}//${host}`);
2869
- for (const [domainKey, localeValue] of Object.entries(
2870
- this.#manifest.i18n.domainLookupTable
2871
- )) {
2872
- const domainKeyAsUrl = new URL(domainKey);
2873
- if (hostAsUrl.host === domainKeyAsUrl.host && hostAsUrl.protocol === domainKeyAsUrl.protocol) {
2874
- locale = localeValue;
2875
- break;
2876
- }
2877
- }
2878
- if (locale) {
2879
- pathname = prependForwardSlash$1(
2880
- joinPaths(normalizeTheLocale(locale), this.removeBase(url.pathname))
2881
- );
2882
- if (url.pathname.endsWith("/")) {
2883
- pathname = appendForwardSlash$1(pathname);
2884
- }
2885
- }
2886
- } catch (e) {
2887
- this.#logger.error(
2888
- "router",
2889
- `Astro tried to parse ${protocol}//${host} as an URL, but it threw a parsing error. Check the X-Forwarded-Host and X-Forwarded-Proto headers.`
2890
- );
2891
- this.#logger.error("router", `Error: ${e}`);
2892
- }
2893
- }
2894
- }
2895
- return pathname;
2896
- }
2897
- #redirectTrailingSlash(pathname) {
2898
- const { trailingSlash } = this.#manifest;
2899
- if (pathname === "/" || pathname.startsWith("/_")) {
2900
- return pathname;
2901
- }
2902
- const path = collapseDuplicateTrailingSlashes(pathname, trailingSlash !== "never");
2903
- if (path !== pathname) {
2904
- return path;
2905
- }
2906
- if (trailingSlash === "ignore") {
2907
- return pathname;
2908
- }
2909
- if (trailingSlash === "always" && !hasFileExtension$1(pathname)) {
2910
- return appendForwardSlash$1(pathname);
2911
- }
2912
- if (trailingSlash === "never") {
2913
- return removeTrailingForwardSlash(pathname);
2914
- }
2915
- return pathname;
2916
- }
2917
- async render(request, renderOptions) {
2918
- let routeData;
2919
- let locals;
2920
- let clientAddress;
2921
- let addCookieHeader;
2922
- const url = new URL(request.url);
2923
- const redirect = this.#redirectTrailingSlash(url.pathname);
2924
- if (redirect !== url.pathname) {
2925
- const status = request.method === "GET" ? 301 : 308;
2926
- return new Response(redirectTemplate({ status, location: redirect, from: request.url }), {
2927
- status,
2928
- headers: {
2929
- location: redirect + url.search
2930
- }
2931
- });
2932
- }
2933
- addCookieHeader = renderOptions?.addCookieHeader;
2934
- clientAddress = renderOptions?.clientAddress ?? Reflect.get(request, clientAddressSymbol);
2935
- routeData = renderOptions?.routeData;
2936
- locals = renderOptions?.locals;
2937
- if (routeData) {
2938
- this.#logger.debug(
2939
- "router",
2940
- "The adapter " + this.#manifest.adapterName + " provided a custom RouteData for ",
2941
- request.url
2942
- );
2943
- this.#logger.debug("router", "RouteData:\n" + routeData);
2944
- }
2945
- if (locals) {
2946
- if (typeof locals !== "object") {
2947
- const error = new AstroError(LocalsNotAnObject);
2948
- this.#logger.error(null, error.stack);
2949
- return this.#renderError(request, { status: 500, error, clientAddress });
2950
- }
2951
- }
2952
- if (!routeData) {
2953
- routeData = this.match(request);
2954
- this.#logger.debug("router", "Astro matched the following route for " + request.url);
2955
- this.#logger.debug("router", "RouteData:\n" + routeData);
2956
- }
2957
- if (!routeData) {
2958
- this.#logger.debug("router", "Astro hasn't found routes that match " + request.url);
2959
- this.#logger.debug("router", "Here's the available routes:\n", this.#manifestData);
2960
- return this.#renderError(request, { locals, status: 404, clientAddress });
2961
- }
2962
- const pathname = this.#getPathnameFromRequest(request);
2963
- const defaultStatus = this.#getDefaultStatusCode(routeData, pathname);
2964
- let response;
2965
- let session;
2966
- try {
2967
- const mod = await this.#pipeline.getModuleForRoute(routeData);
2968
- const renderContext = await RenderContext.create({
2969
- pipeline: this.#pipeline,
2970
- locals,
2971
- pathname,
2972
- request,
2973
- routeData,
2974
- status: defaultStatus,
2975
- clientAddress
2976
- });
2977
- session = renderContext.session;
2978
- response = await renderContext.render(await mod.page());
2979
- } catch (err) {
2980
- this.#logger.error(null, err.stack || err.message || String(err));
2981
- return this.#renderError(request, { locals, status: 500, error: err, clientAddress });
2982
- } finally {
2983
- await session?.[PERSIST_SYMBOL]();
2984
- }
2985
- if (REROUTABLE_STATUS_CODES.includes(response.status) && response.headers.get(REROUTE_DIRECTIVE_HEADER) !== "no") {
2986
- return this.#renderError(request, {
2987
- locals,
2988
- response,
2989
- status: response.status,
2990
- // We don't have an error to report here. Passing null means we pass nothing intentionally
2991
- // while undefined means there's no error
2992
- error: response.status === 500 ? null : void 0,
2993
- clientAddress
2994
- });
2995
- }
2996
- if (response.headers.has(REROUTE_DIRECTIVE_HEADER)) {
2997
- response.headers.delete(REROUTE_DIRECTIVE_HEADER);
2998
- }
2999
- if (addCookieHeader) {
3000
- for (const setCookieHeaderValue of App.getSetCookieFromResponse(response)) {
3001
- response.headers.append("set-cookie", setCookieHeaderValue);
3002
- }
3003
- }
3004
- Reflect.set(response, responseSentSymbol$1, true);
3005
- return response;
3006
- }
3007
- setCookieHeaders(response) {
3008
- return getSetCookiesFromResponse(response);
3009
- }
3010
- /**
3011
- * Reads all the cookies written by `Astro.cookie.set()` onto the passed response.
3012
- * For example,
3013
- * ```ts
3014
- * for (const cookie_ of App.getSetCookieFromResponse(response)) {
3015
- * const cookie: string = cookie_
3016
- * }
3017
- * ```
3018
- * @param response The response to read cookies from.
3019
- * @returns An iterator that yields key-value pairs as equal-sign-separated strings.
3020
- */
3021
- static getSetCookieFromResponse = getSetCookiesFromResponse;
3022
- /**
3023
- * If it is a known error code, try sending the according page (e.g. 404.astro / 500.astro).
3024
- * This also handles pre-rendered /404 or /500 routes
3025
- */
3026
- async #renderError(request, {
3027
- locals,
3028
- status,
3029
- response: originalResponse,
3030
- skipMiddleware = false,
3031
- error,
3032
- clientAddress
3033
- }) {
3034
- const errorRoutePath = `/${status}${this.#manifest.trailingSlash === "always" ? "/" : ""}`;
3035
- const errorRouteData = matchRoute(errorRoutePath, this.#manifestData);
3036
- const url = new URL(request.url);
3037
- if (errorRouteData) {
3038
- if (errorRouteData.prerender) {
3039
- const maybeDotHtml = errorRouteData.route.endsWith(`/${status}`) ? ".html" : "";
3040
- const statusURL = new URL(
3041
- `${this.#baseWithoutTrailingSlash}/${status}${maybeDotHtml}`,
3042
- url
3043
- );
3044
- if (statusURL.toString() !== request.url) {
3045
- const response2 = await fetch(statusURL.toString());
3046
- const override = { status };
3047
- return this.#mergeResponses(response2, originalResponse, override);
3048
- }
3049
- }
3050
- const mod = await this.#pipeline.getModuleForRoute(errorRouteData);
3051
- let session;
3052
- try {
3053
- const renderContext = await RenderContext.create({
3054
- locals,
3055
- pipeline: this.#pipeline,
3056
- middleware: skipMiddleware ? NOOP_MIDDLEWARE_FN : void 0,
3057
- pathname: this.#getPathnameFromRequest(request),
3058
- request,
3059
- routeData: errorRouteData,
3060
- status,
3061
- props: { error },
3062
- clientAddress
3063
- });
3064
- session = renderContext.session;
3065
- const response2 = await renderContext.render(await mod.page());
3066
- return this.#mergeResponses(response2, originalResponse);
3067
- } catch {
3068
- if (skipMiddleware === false) {
3069
- return this.#renderError(request, {
3070
- locals,
3071
- status,
3072
- response: originalResponse,
3073
- skipMiddleware: true,
3074
- clientAddress
3075
- });
3076
- }
3077
- } finally {
3078
- await session?.[PERSIST_SYMBOL]();
3079
- }
3080
- }
3081
- const response = this.#mergeResponses(new Response(null, { status }), originalResponse);
3082
- Reflect.set(response, responseSentSymbol$1, true);
3083
- return response;
3084
- }
3085
- #mergeResponses(newResponse, originalResponse, override) {
3086
- if (!originalResponse) {
3087
- if (override !== void 0) {
3088
- return new Response(newResponse.body, {
3089
- status: override.status,
3090
- statusText: newResponse.statusText,
3091
- headers: newResponse.headers
3092
- });
3093
- }
3094
- return newResponse;
3095
- }
3096
- const status = override?.status ? override.status : originalResponse.status === 200 ? newResponse.status : originalResponse.status;
3097
- try {
3098
- originalResponse.headers.delete("Content-type");
3099
- } catch {
3100
- }
3101
- const mergedHeaders = new Map([
3102
- ...Array.from(newResponse.headers),
3103
- ...Array.from(originalResponse.headers)
3104
- ]);
3105
- const newHeaders = new Headers();
3106
- for (const [name, value] of mergedHeaders) {
3107
- newHeaders.set(name, value);
3108
- }
3109
- return new Response(newResponse.body, {
3110
- status,
3111
- statusText: status === 200 ? newResponse.statusText : originalResponse.statusText,
3112
- // If you're looking at here for possible bugs, it means that it's not a bug.
3113
- // With the middleware, users can meddle with headers, and we should pass to the 404/500.
3114
- // If users see something weird, it's because they are setting some headers they should not.
3115
- //
3116
- // Although, we don't want it to replace the content-type, because the error page must return `text/html`
3117
- headers: newHeaders
3118
- });
3119
- }
3120
- #getDefaultStatusCode(routeData, pathname) {
3121
- if (!routeData.pattern.test(pathname)) {
3122
- for (const fallbackRoute of routeData.fallbackRoutes) {
3123
- if (fallbackRoute.pattern.test(pathname)) {
3124
- return 302;
3125
- }
3126
- }
3127
- }
3128
- const route = removeTrailingForwardSlash(routeData.route);
3129
- if (route.endsWith("/404")) return 404;
3130
- if (route.endsWith("/500")) return 500;
3131
- return 200;
3132
- }
3133
- }
3134
-
3135
- const createOutgoingHttpHeaders = (headers) => {
3136
- if (!headers) {
3137
- return void 0;
3138
- }
3139
- const nodeHeaders = Object.fromEntries(headers.entries());
3140
- if (Object.keys(nodeHeaders).length === 0) {
3141
- return void 0;
3142
- }
3143
- if (headers.has("set-cookie")) {
3144
- const cookieHeaders = headers.getSetCookie();
3145
- if (cookieHeaders.length > 1) {
3146
- nodeHeaders["set-cookie"] = cookieHeaders;
3147
- }
3148
- }
3149
- return nodeHeaders;
3150
- };
3151
-
3152
- function apply() {
3153
- if (!globalThis.crypto) {
3154
- Object.defineProperty(globalThis, "crypto", {
3155
- value: crypto$1.webcrypto
3156
- });
3157
- }
3158
- if (!globalThis.File) {
3159
- Object.defineProperty(globalThis, "File", {
3160
- value: buffer.File
3161
- });
3162
- }
3163
- }
3164
-
3165
- class NodeApp extends App {
3166
- match(req) {
3167
- if (!(req instanceof Request)) {
3168
- req = NodeApp.createRequest(req, {
3169
- skipBody: true
3170
- });
3171
- }
3172
- return super.match(req);
3173
- }
3174
- render(req, routeDataOrOptions, maybeLocals) {
3175
- if (!(req instanceof Request)) {
3176
- req = NodeApp.createRequest(req);
3177
- }
3178
- return super.render(req, routeDataOrOptions, maybeLocals);
3179
- }
3180
- /**
3181
- * Converts a NodeJS IncomingMessage into a web standard Request.
3182
- * ```js
3183
- * import { NodeApp } from 'astro/app/node';
3184
- * import { createServer } from 'node:http';
3185
- *
3186
- * const server = createServer(async (req, res) => {
3187
- * const request = NodeApp.createRequest(req);
3188
- * const response = await app.render(request);
3189
- * await NodeApp.writeResponse(response, res);
3190
- * })
3191
- * ```
3192
- */
3193
- static createRequest(req, { skipBody = false } = {}) {
3194
- const isEncrypted = "encrypted" in req.socket && req.socket.encrypted;
3195
- const getFirstForwardedValue = (multiValueHeader) => {
3196
- return multiValueHeader?.toString()?.split(",").map((e) => e.trim())?.[0];
3197
- };
3198
- const forwardedProtocol = getFirstForwardedValue(req.headers["x-forwarded-proto"]);
3199
- const protocol = forwardedProtocol ?? (isEncrypted ? "https" : "http");
3200
- const forwardedHostname = getFirstForwardedValue(req.headers["x-forwarded-host"]);
3201
- const hostname = forwardedHostname ?? req.headers.host ?? req.headers[":authority"];
3202
- const port = getFirstForwardedValue(req.headers["x-forwarded-port"]);
3203
- const portInHostname = typeof hostname === "string" && /:\d+$/.test(hostname);
3204
- const hostnamePort = portInHostname ? hostname : `${hostname}${port ? `:${port}` : ""}`;
3205
- const url = `${protocol}://${hostnamePort}${req.url}`;
3206
- const options = {
3207
- method: req.method || "GET",
3208
- headers: makeRequestHeaders(req)
3209
- };
3210
- const bodyAllowed = options.method !== "HEAD" && options.method !== "GET" && skipBody === false;
3211
- if (bodyAllowed) {
3212
- Object.assign(options, makeRequestBody(req));
3213
- }
3214
- const request = new Request(url, options);
3215
- const forwardedClientIp = getFirstForwardedValue(req.headers["x-forwarded-for"]);
3216
- const clientIp = forwardedClientIp || req.socket?.remoteAddress;
3217
- if (clientIp) {
3218
- Reflect.set(request, clientAddressSymbol, clientIp);
3219
- }
3220
- return request;
3221
- }
3222
- /**
3223
- * Streams a web-standard Response into a NodeJS Server Response.
3224
- * ```js
3225
- * import { NodeApp } from 'astro/app/node';
3226
- * import { createServer } from 'node:http';
3227
- *
3228
- * const server = createServer(async (req, res) => {
3229
- * const request = NodeApp.createRequest(req);
3230
- * const response = await app.render(request);
3231
- * await NodeApp.writeResponse(response, res);
3232
- * })
3233
- * ```
3234
- * @param source WhatWG Response
3235
- * @param destination NodeJS ServerResponse
3236
- */
3237
- static async writeResponse(source, destination) {
3238
- const { status, headers, body, statusText } = source;
3239
- if (!(destination instanceof Http2ServerResponse)) {
3240
- destination.statusMessage = statusText;
3241
- }
3242
- destination.writeHead(status, createOutgoingHttpHeaders(headers));
3243
- if (!body) return destination.end();
3244
- try {
3245
- const reader = body.getReader();
3246
- destination.on("close", () => {
3247
- reader.cancel().catch((err) => {
3248
- console.error(
3249
- `There was an uncaught error in the middle of the stream while rendering ${destination.req.url}.`,
3250
- err
3251
- );
3252
- });
3253
- });
3254
- let result = await reader.read();
3255
- while (!result.done) {
3256
- destination.write(result.value);
3257
- result = await reader.read();
3258
- }
3259
- destination.end();
3260
- } catch (err) {
3261
- destination.write("Internal server error", () => {
3262
- err instanceof Error ? destination.destroy(err) : destination.destroy();
3263
- });
3264
- }
3265
- }
3266
- }
3267
- function makeRequestHeaders(req) {
3268
- const headers = new Headers();
3269
- for (const [name, value] of Object.entries(req.headers)) {
3270
- if (value === void 0) {
3271
- continue;
3272
- }
3273
- if (Array.isArray(value)) {
3274
- for (const item of value) {
3275
- headers.append(name, item);
3276
- }
3277
- } else {
3278
- headers.append(name, value);
3279
- }
3280
- }
3281
- return headers;
3282
- }
3283
- function makeRequestBody(req) {
3284
- if (req.body !== void 0) {
3285
- if (typeof req.body === "string" && req.body.length > 0) {
3286
- return { body: Buffer.from(req.body) };
3287
- }
3288
- if (typeof req.body === "object" && req.body !== null && Object.keys(req.body).length > 0) {
3289
- return { body: Buffer.from(JSON.stringify(req.body)) };
3290
- }
3291
- if (typeof req.body === "object" && req.body !== null && typeof req.body[Symbol.asyncIterator] !== "undefined") {
3292
- return asyncIterableToBodyProps(req.body);
3293
- }
3294
- }
3295
- return asyncIterableToBodyProps(req);
3296
- }
3297
- function asyncIterableToBodyProps(iterable) {
3298
- return {
3299
- // Node uses undici for the Request implementation. Undici accepts
3300
- // a non-standard async iterable for the body.
3301
- // @ts-expect-error
3302
- body: iterable,
3303
- // The duplex property is required when using a ReadableStream or async
3304
- // iterable for the body. The type definitions do not include the duplex
3305
- // property because they are not up-to-date.
3306
- duplex: "half"
3307
- };
3308
- }
3309
-
3310
- apply();
3311
-
3312
- function createAppHandler(app) {
3313
- const als = new AsyncLocalStorage();
3314
- const logger = app.getAdapterLogger();
3315
- process.on("unhandledRejection", (reason) => {
3316
- const requestUrl = als.getStore();
3317
- logger.error(`Unhandled rejection while rendering ${requestUrl}`);
3318
- console.error(reason);
3319
- });
3320
- return async (req, res, next, locals) => {
3321
- let request;
3322
- try {
3323
- request = NodeApp.createRequest(req);
3324
- } catch (err) {
3325
- logger.error(`Could not render ${req.url}`);
3326
- console.error(err);
3327
- res.statusCode = 500;
3328
- res.end("Internal Server Error");
3329
- return;
3330
- }
3331
- const routeData = app.match(request);
3332
- if (routeData) {
3333
- const response = await als.run(
3334
- request.url,
3335
- () => app.render(request, {
3336
- addCookieHeader: true,
3337
- locals,
3338
- routeData
3339
- })
3340
- );
3341
- await NodeApp.writeResponse(response, res);
3342
- } else if (next) {
3343
- return next();
3344
- } else {
3345
- const response = await app.render(req);
3346
- await NodeApp.writeResponse(response, res);
3347
- }
3348
- };
3349
- }
3350
-
3351
- function createMiddleware(app) {
3352
- const handler = createAppHandler(app);
3353
- const logger = app.getAdapterLogger();
3354
- return async (...args) => {
3355
- const [req, res, next, locals] = args;
3356
- if (req instanceof Error) {
3357
- const error = req;
3358
- if (next) {
3359
- return next(error);
3360
- } else {
3361
- throw error;
3362
- }
3363
- }
3364
- try {
3365
- await handler(req, res, next, locals);
3366
- } catch (err) {
3367
- logger.error(`Could not render ${req.url}`);
3368
- console.error(err);
3369
- if (!res.headersSent) {
3370
- res.writeHead(500, `Server error`);
3371
- res.end();
3372
- }
3373
- }
3374
- };
3375
- }
3376
-
3377
- const wildcardHosts = /* @__PURE__ */ new Set(["0.0.0.0", "::", "0000:0000:0000:0000:0000:0000:0000:0000"]);
3378
- async function logListeningOn(logger, server, configuredHost) {
3379
- await new Promise((resolve) => server.once("listening", resolve));
3380
- const protocol = server instanceof https.Server ? "https" : "http";
3381
- const host = getResolvedHostForHttpServer(configuredHost);
3382
- const { port } = server.address();
3383
- const address = getNetworkAddress(protocol, host, port);
3384
- if (host === void 0 || wildcardHosts.has(host)) {
3385
- logger.info(
3386
- `Server listening on
3387
- local: ${address.local[0]}
3388
- network: ${address.network[0]}
3389
- `
3390
- );
3391
- } else {
3392
- logger.info(`Server listening on ${address.local[0]}`);
3393
- }
3394
- }
3395
- function getResolvedHostForHttpServer(host) {
3396
- if (host === false) {
3397
- return "localhost";
3398
- } else if (host === true) {
3399
- return void 0;
3400
- } else {
3401
- return host;
3402
- }
3403
- }
3404
- function getNetworkAddress(protocol = "http", hostname, port, base) {
3405
- const NetworkAddress = {
3406
- local: [],
3407
- network: []
3408
- };
3409
- Object.values(os.networkInterfaces()).flatMap((nInterface) => nInterface ?? []).filter(
3410
- (detail) => detail && detail.address && (detail.family === "IPv4" || // @ts-expect-error Node 18.0 - 18.3 returns number
3411
- detail.family === 4)
3412
- ).forEach((detail) => {
3413
- let host = detail.address.replace(
3414
- "127.0.0.1",
3415
- hostname === void 0 || wildcardHosts.has(hostname) ? "localhost" : hostname
3416
- );
3417
- if (host.includes(":")) {
3418
- host = `[${host}]`;
3419
- }
3420
- const url = `${protocol}://${host}:${port}${""}`;
3421
- if (detail.address.includes("127.0.0.1")) {
3422
- NetworkAddress.local.push(url);
3423
- } else {
3424
- NetworkAddress.network.push(url);
3425
- }
3426
- });
3427
- return NetworkAddress;
3428
- }
3429
-
3430
- const WITH_FILE_EXT = /\/[^/]+\.\w+$/;
3431
- function hasFileExtension(path) {
3432
- return WITH_FILE_EXT.test(path);
3433
- }
3434
-
3435
- function createStaticHandler(app, options) {
3436
- const client = resolveClientDir(options);
3437
- return (req, res, ssr) => {
3438
- if (req.url) {
3439
- const [urlPath, urlQuery] = req.url.split("?");
3440
- const filePath = path.join(client, app.removeBase(urlPath));
3441
- let isDirectory = false;
3442
- try {
3443
- isDirectory = fs.lstatSync(filePath).isDirectory();
3444
- } catch {
3445
- }
3446
- const { trailingSlash = "ignore" } = options;
3447
- const hasSlash = urlPath.endsWith("/");
3448
- let pathname = urlPath;
3449
- switch (trailingSlash) {
3450
- case "never": {
3451
- if (isDirectory && urlPath !== "/" && hasSlash) {
3452
- pathname = urlPath.slice(0, -1) + (urlQuery ? "?" + urlQuery : "");
3453
- res.statusCode = 301;
3454
- res.setHeader("Location", pathname);
3455
- return res.end();
3456
- }
3457
- if (isDirectory && !hasSlash) {
3458
- pathname = `${urlPath}/index.html`;
3459
- }
3460
- break;
3461
- }
3462
- case "ignore": {
3463
- if (isDirectory && !hasSlash) {
3464
- pathname = `${urlPath}/index.html`;
3465
- }
3466
- break;
3467
- }
3468
- case "always": {
3469
- if (!hasSlash && !hasFileExtension(urlPath)) {
3470
- pathname = urlPath + "/" + (urlQuery ? "?" + urlQuery : "");
3471
- res.statusCode = 301;
3472
- res.setHeader("Location", pathname);
3473
- return res.end();
3474
- }
3475
- break;
3476
- }
3477
- }
3478
- pathname = prependForwardSlash(app.removeBase(pathname));
3479
- const stream = send(req, pathname, {
3480
- root: client,
3481
- dotfiles: pathname.startsWith("/.well-known/") ? "allow" : "deny"
3482
- });
3483
- let forwardError = false;
3484
- stream.on("error", (err) => {
3485
- if (forwardError) {
3486
- console.error(err.toString());
3487
- res.writeHead(500);
3488
- res.end("Internal server error");
3489
- return;
3490
- }
3491
- ssr();
3492
- });
3493
- stream.on("headers", (_res) => {
3494
- if (pathname.startsWith(`/${options.assets}/`)) {
3495
- _res.setHeader("Cache-Control", "public, max-age=31536000, immutable");
3496
- }
3497
- });
3498
- stream.on("file", () => {
3499
- forwardError = true;
3500
- });
3501
- stream.pipe(res);
3502
- } else {
3503
- ssr();
3504
- }
3505
- };
3506
- }
3507
- function resolveClientDir(options) {
3508
- const clientURLRaw = new URL(options.client);
3509
- const serverURLRaw = new URL(options.server);
3510
- const rel = path.relative(url.fileURLToPath(serverURLRaw), url.fileURLToPath(clientURLRaw));
3511
- const serverFolder = path.basename(options.server);
3512
- let serverEntryFolderURL = path.dirname(import.meta.url);
3513
- while (!serverEntryFolderURL.endsWith(serverFolder)) {
3514
- serverEntryFolderURL = path.dirname(serverEntryFolderURL);
3515
- }
3516
- const serverEntryURL = serverEntryFolderURL + "/entry.mjs";
3517
- const clientURL = new URL(appendForwardSlash(rel), serverEntryURL);
3518
- const client = url.fileURLToPath(clientURL);
3519
- return client;
3520
- }
3521
- function prependForwardSlash(pth) {
3522
- return pth.startsWith("/") ? pth : "/" + pth;
3523
- }
3524
- function appendForwardSlash(pth) {
3525
- return pth.endsWith("/") ? pth : pth + "/";
3526
- }
3527
-
3528
- const hostOptions = (host) => {
3529
- if (typeof host === "boolean") {
3530
- return host ? "0.0.0.0" : "localhost";
3531
- }
3532
- return host;
3533
- };
3534
- function standalone(app, options) {
3535
- const port = process.env.PORT ? Number(process.env.PORT) : options.port ?? 8080;
3536
- const host = process.env.HOST ?? hostOptions(options.host);
3537
- const handler = createStandaloneHandler(app, options);
3538
- const server = createServer(handler, host, port);
3539
- server.server.listen(port, host);
3540
- if (process.env.ASTRO_NODE_LOGGING !== "disabled") {
3541
- logListeningOn(app.getAdapterLogger(), server.server, host);
3542
- }
3543
- return {
3544
- server,
3545
- done: server.closed()
3546
- };
3547
- }
3548
- function createStandaloneHandler(app, options) {
3549
- const appHandler = createAppHandler(app);
3550
- const staticHandler = createStaticHandler(app, options);
3551
- return (req, res) => {
3552
- try {
3553
- decodeURI(req.url);
3554
- } catch {
3555
- res.writeHead(400);
3556
- res.end("Bad request.");
3557
- return;
3558
- }
3559
- staticHandler(req, res, () => appHandler(req, res));
3560
- };
3561
- }
3562
- function createServer(listener, host, port) {
3563
- let httpServer;
3564
- if (process.env.SERVER_CERT_PATH && process.env.SERVER_KEY_PATH) {
3565
- httpServer = https.createServer(
3566
- {
3567
- key: fs.readFileSync(process.env.SERVER_KEY_PATH),
3568
- cert: fs.readFileSync(process.env.SERVER_CERT_PATH)
3569
- },
3570
- listener
3571
- );
3572
- } else {
3573
- httpServer = http.createServer(listener);
3574
- }
3575
- enableDestroy(httpServer);
3576
- const closed = new Promise((resolve, reject) => {
3577
- httpServer.addListener("close", resolve);
3578
- httpServer.addListener("error", reject);
3579
- });
3580
- const previewable = {
3581
- host,
3582
- port,
3583
- closed() {
3584
- return closed;
3585
- },
3586
- async stop() {
3587
- await new Promise((resolve, reject) => {
3588
- httpServer.destroy((err) => err ? reject(err) : resolve(void 0));
3589
- });
3590
- }
3591
- };
3592
- return {
3593
- server: httpServer,
3594
- ...previewable
3595
- };
3596
- }
3597
-
3598
- function createExports(manifest, options) {
3599
- const app = new NodeApp(manifest);
3600
- options.trailingSlash = manifest.trailingSlash;
3601
- return {
3602
- options,
3603
- handler: options.mode === "middleware" ? createMiddleware(app) : createStandaloneHandler(app, options),
3604
- startServer: () => standalone(app, options)
3605
- };
3606
- }
3607
- function start(manifest, options) {
3608
- if (options.mode !== "standalone" || process.env.ASTRO_NODE_AUTOSTART === "disabled") {
3609
- return;
3610
- }
3611
- const app = new NodeApp(manifest);
3612
- standalone(app, options);
3095
+ function defineMiddleware(fn) {
3096
+ return fn;
3613
3097
  }
3614
3098
 
3615
- const serverEntrypointModule = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.defineProperty({
3616
- __proto__: null,
3617
- createExports,
3618
- start
3619
- }, Symbol.toStringTag, { value: 'Module' }));
3620
-
3621
- export { start as a, createExports as c, serverEntrypointModule as s };
3099
+ export { PERSIST_SYMBOL as P, RouteCache as R, SERVER_ISLAND_COMPONENT as S, redirectToFallback as a, redirectToDefaultLocale as b, requestHasLocale as c, normalizeTheLocale as d, defineMiddleware as e, SERVER_ISLAND_ROUTE as f, createEndpoint as g, findRouteToRewrite as h, isRequestServerIsland as i, RenderContext as j, getSetCookiesFromResponse as k, matchRoute as m, notFound as n, requestIs404Or500 as r, sequence as s };