import { removeTrailingForwardSlash, appendForwardSlash, collapseDuplicateSlashes, trimSlashes, prependForwardSlash, joinPaths, collapseDuplicateLeadingSlashes, removeLeadingForwardSlash, isInternalPath, collapseDuplicateTrailingSlashes, hasFileExtension, fileExtension, slash } from '@astrojs/internal-helpers/path'; import { matchPattern } from '@astrojs/internal-helpers/remote'; import colors from 'piccolore'; import { parse as parse$1, stringify as stringify$1, unflatten as unflatten$1 } from 'devalue'; import 'es-module-lexer'; import { escape } from 'html-escaper'; import { clsx } from 'clsx'; import { encodeBase64, encodeHexUpperCase, decodeBase64, decodeHex } from '@oslojs/encoding'; import * as z from 'zod/v4'; import { FORBIDDEN_PATH_KEYS } from '@astrojs/internal-helpers/object'; import { serialize, parse } from 'cookie'; import { createStorage } from 'unstorage'; function shouldAppendForwardSlash(trailingSlash, buildFormat) { switch (trailingSlash) { case "always": return true; case "never": return false; case "ignore": { switch (buildFormat) { case "directory": return true; case "preserve": case "file": return false; } } } } const ASTRO_VERSION = "6.2.1"; const ASTRO_GENERATOR = `Astro v${ASTRO_VERSION}`; const REROUTE_DIRECTIVE_HEADER = "X-Astro-Reroute"; const REWRITE_DIRECTIVE_HEADER_KEY = "X-Astro-Rewrite"; const REWRITE_DIRECTIVE_HEADER_VALUE = "yes"; const NOOP_MIDDLEWARE_HEADER = "X-Astro-Noop"; const ROUTE_TYPE_HEADER = "X-Astro-Route-Type"; const DEFAULT_404_COMPONENT = "astro-default-404.astro"; const REDIRECT_STATUS_CODES = [301, 302, 303, 307, 308, 300, 304]; const REROUTABLE_STATUS_CODES = [404, 500]; const clientAddressSymbol = /* @__PURE__ */ Symbol.for("astro.clientAddress"); const originPathnameSymbol = /* @__PURE__ */ Symbol.for("astro.originPathname"); const pipelineSymbol = /* @__PURE__ */ Symbol.for("astro.pipeline"); const responseSentSymbol$1 = /* @__PURE__ */ Symbol.for("astro.responseSent"); const ClientAddressNotAvailable = { name: "ClientAddressNotAvailable", title: "`Astro.clientAddress` is not available in current adapter.", message: (adapterName) => `\`Astro.clientAddress\` is not available in the \`${adapterName}\` adapter. File an issue with the adapter to add support.` }; const PrerenderClientAddressNotAvailable = { name: "PrerenderClientAddressNotAvailable", title: "`Astro.clientAddress` cannot be used inside prerendered routes.", message: (name) => `\`Astro.clientAddress\` cannot be used inside prerendered route ${name}` }; const StaticClientAddressNotAvailable = { name: "StaticClientAddressNotAvailable", title: "`Astro.clientAddress` is not available in prerendered pages.", message: "`Astro.clientAddress` is only available on pages that are server-rendered.", hint: "See https://docs.astro.build/en/guides/on-demand-rendering/ for more information on how to enable SSR." }; const NoMatchingStaticPathFound = { name: "NoMatchingStaticPathFound", title: "No static path found for requested path.", message: (pathName) => `A \`getStaticPaths()\` route pattern was matched, but no matching static path was found for requested path \`${pathName}\`.`, hint: (possibleRoutes) => `Possible dynamic routes being matched: ${possibleRoutes.join(", ")}.` }; const OnlyResponseCanBeReturned = { name: "OnlyResponseCanBeReturned", title: "Invalid type returned by Astro page.", message: (route, returnedValue) => `Route \`${route ? route : ""}\` returned a \`${returnedValue}\`. Only a [Response](https://developer.mozilla.org/en-US/docs/Web/API/Response) can be returned from Astro files.`, hint: "See https://docs.astro.build/en/guides/on-demand-rendering/#response for more information." }; const MissingMediaQueryDirective = { name: "MissingMediaQueryDirective", title: "Missing value for `client:media` directive.", message: 'Media query not provided for `client:media` directive. A media query similar to `client:media="(max-width: 600px)"` must be provided' }; const NoMatchingRenderer = { name: "NoMatchingRenderer", title: "No matching renderer found.", message: (componentName, componentExtension, plural, validRenderersCount) => `Unable to render \`${componentName}\`. ${validRenderersCount > 0 ? `There ${plural ? "are" : "is"} ${validRenderersCount} renderer${plural ? "s" : ""} configured in your \`astro.config.mjs\` file, but ${plural ? "none were" : "it was not"} able to server-side render \`${componentName}\`.` : `No valid renderer was found ${componentExtension ? `for the \`.${componentExtension}\` file extension.` : `for this file extension.`}`}`, hint: (probableRenderers) => `Did you mean to enable the ${probableRenderers} integration? See https://docs.astro.build/en/guides/framework-components/ for more information on how to install and configure integrations.` }; const NoClientOnlyHint = { name: "NoClientOnlyHint", title: "Missing hint on client:only directive.", message: (componentName) => `Unable to render \`${componentName}\`. When using the \`client:only\` hydration strategy, Astro needs a hint to use the correct renderer.`, hint: (probableRenderers) => `Did you mean to pass \`client:only="${probableRenderers}"\`? See https://docs.astro.build/en/reference/directives-reference/#clientonly for more information on client:only` }; const InvalidGetStaticPathsEntry = { name: "InvalidGetStaticPathsEntry", title: "Invalid entry inside getStaticPath's return value", message: (entryType) => `Invalid entry returned by getStaticPaths. Expected an object, got \`${entryType}\``, hint: "If you're using a `.map` call, you might be looking for `.flatMap()` instead. See https://docs.astro.build/en/reference/routing-reference/#getstaticpaths for more information on getStaticPaths." }; const InvalidGetStaticPathsReturn = { name: "InvalidGetStaticPathsReturn", title: "Invalid value returned by getStaticPaths.", message: (returnType) => `Invalid type returned by \`getStaticPaths\`. Expected an \`array\`, got \`${returnType}\``, hint: "See https://docs.astro.build/en/reference/routing-reference/#getstaticpaths for more information on getStaticPaths." }; const GetStaticPathsExpectedParams = { name: "GetStaticPathsExpectedParams", title: "Missing params property on `getStaticPaths` route.", message: "Missing or empty required `params` property on `getStaticPaths` route.", hint: "See https://docs.astro.build/en/reference/routing-reference/#getstaticpaths for more information on getStaticPaths." }; const GetStaticPathsInvalidRouteParam = { name: "GetStaticPathsInvalidRouteParam", title: "Invalid route parameter returned by `getStaticPaths()`.", message: (key, value, valueType) => `Invalid \`getStaticPaths()\` route parameter for \`${key}\`. Expected a string or undefined, received \`${valueType}\` (\`${value}\`)`, hint: "See https://docs.astro.build/en/reference/routing-reference/#getstaticpaths for more information on getStaticPaths." }; const GetStaticPathsRequired = { name: "GetStaticPathsRequired", title: "`getStaticPaths()` function required for dynamic routes.", message: "`getStaticPaths()` function is required for dynamic routes. Make sure that you `export` a `getStaticPaths` function from your dynamic route.", hint: `See https://docs.astro.build/en/guides/routing/#dynamic-routes for more information on dynamic routes. If you meant for this route to be server-rendered, set \`export const prerender = false;\` in the page.` }; const ReservedSlotName = { name: "ReservedSlotName", title: "Invalid slot name.", message: (slotName) => `Unable to create a slot named \`${slotName}\`. \`${slotName}\` is a reserved slot name. Please update the name of this slot.` }; const NoMatchingImport = { name: "NoMatchingImport", title: "No import found for component.", message: (componentName) => `Could not render \`${componentName}\`. No matching import has been found for \`${componentName}\`.`, hint: "Please make sure the component is properly imported." }; const InvalidComponentArgs = { name: "InvalidComponentArgs", title: "Invalid component arguments.", message: (name) => `Invalid arguments passed to${name ? ` <${name}>` : ""} component.`, hint: "Astro components cannot be rendered directly via function call, such as `Component()` or `{items.map(Component)}`." }; const PageNumberParamNotFound = { name: "PageNumberParamNotFound", title: "Page number param not found.", message: (paramName) => `[paginate()] page number param \`${paramName}\` not found in your filepath.`, hint: "Rename your file to `[page].astro` or `[...page].astro`." }; const ImageMissingAlt = { name: "ImageMissingAlt", title: 'Image missing required "alt" property.', message: 'Image missing "alt" property. "alt" text is required to describe important images on the page.', hint: 'Use an empty string ("") for decorative images.' }; const InvalidImageService = { name: "InvalidImageService", title: "Error while loading image service.", message: "There was an error loading the configured image service. Please see the stack trace for more information." }; const MissingImageDimension = { name: "MissingImageDimension", title: "Missing image dimensions", message: (missingDimension, imageURL) => `Missing ${missingDimension === "both" ? "width and height attributes" : `${missingDimension} attribute`} for ${imageURL}. When using remote images, both dimensions are required in order to avoid CLS.`, hint: "If your image is inside your `src` folder, you probably meant to import it instead. See [the Imports guide for more information](https://docs.astro.build/en/guides/imports/#other-assets). You can also use `inferSize={true}` for remote images to get the original dimensions." }; const FailedToFetchRemoteImageDimensions = { name: "FailedToFetchRemoteImageDimensions", title: "Failed to retrieve remote image dimensions", message: (imageURL) => `Failed to get the dimensions for ${imageURL}.`, hint: "Verify your remote image URL is accurate, and that you are not using `inferSize` with a file located in your `public/` folder." }; const RemoteImageNotAllowed = { name: "RemoteImageNotAllowed", title: "Remote image is not allowed", message: (imageURL) => `Remote image ${imageURL} is not allowed by your image configuration.`, hint: "Update `image.domains` or `image.remotePatterns`, or remove `inferSize` for this image." }; const UnsupportedImageFormat = { name: "UnsupportedImageFormat", title: "Unsupported image format", message: (format, imagePath, supportedFormats) => `Received unsupported format \`${format}\` from \`${imagePath}\`. Currently only ${supportedFormats.join( ", " )} are supported by our image services.`, hint: "Using an `img` tag directly instead of the `Image` component might be what you're looking for." }; const UnsupportedImageConversion = { name: "UnsupportedImageConversion", title: "Unsupported image conversion", message: "Converting between vector (such as SVGs) and raster (such as PNGs and JPEGs) images is not currently supported." }; const PrerenderDynamicEndpointPathCollide = { name: "PrerenderDynamicEndpointPathCollide", title: "Prerendered dynamic endpoint has path collision.", message: (pathname) => `Could not render \`${pathname}\` with an \`undefined\` param as the generated path will collide during prerendering. Prevent passing \`undefined\` as \`params\` for the endpoint's \`getStaticPaths()\` function, or add an additional extension to the endpoint's filename.`, hint: (filename) => `Rename \`${filename}\` to \`${filename.replace(/\.(?:js|ts)/, (m) => `.json` + m)}\`` }; const ExpectedImage = { name: "ExpectedImage", title: "Expected src to be an image.", message: (src, typeofOptions, fullOptions) => `Expected \`src\` property for \`getImage\` or \`\` to be either an ESM imported image or a string with the path of a remote image. Received \`${src}\` (type: \`${typeofOptions}\`). Full serialized options received: \`${fullOptions}\`.`, hint: "This error can often happen because of a wrong path. Make sure the path to your image is correct. If you're passing an async function, make sure to call and await it." }; const ExpectedImageOptions = { name: "ExpectedImageOptions", title: "Expected image options.", message: (options) => `Expected getImage() parameter to be an object. Received \`${options}\`.` }; const ExpectedNotESMImage = { name: "ExpectedNotESMImage", title: "Expected image options, not an ESM-imported image.", message: "An ESM-imported image cannot be passed directly to `getImage()`. Instead, pass an object with the image in the `src` property.", hint: "Try changing `getImage(myImage)` to `getImage({ src: myImage })`" }; const IncompatibleDescriptorOptions = { name: "IncompatibleDescriptorOptions", title: "Cannot set both `densities` and `widths`", message: "Only one of `densities` or `widths` can be specified. In most cases, you'll probably want to use only `widths` if you require specific widths.", hint: "Those attributes are used to construct a `srcset` attribute, which cannot have both `x` and `w` descriptors." }; const NoImageMetadata = { name: "NoImageMetadata", title: "Could not process image metadata.", message: (imagePath) => `Could not process image metadata${imagePath ? ` for \`${imagePath}\`` : ""}.`, hint: "This is often caused by a corrupted or malformed image. Re-exporting the image from your image editor may fix this issue." }; const ResponseSentError = { name: "ResponseSentError", title: "Unable to set response.", message: "The response has already been sent to the browser and cannot be altered." }; const MiddlewareNoDataOrNextCalled = { name: "MiddlewareNoDataOrNextCalled", title: "The middleware didn't return a `Response`.", message: "Make sure your middleware returns a `Response` object, either directly or by returning the `Response` from calling the `next` function." }; const MiddlewareNotAResponse = { name: "MiddlewareNotAResponse", title: "The middleware returned something that is not a `Response` object.", message: "Any data returned from middleware must be a valid `Response` object." }; const EndpointDidNotReturnAResponse = { name: "EndpointDidNotReturnAResponse", title: "The endpoint did not return a `Response`.", message: "An endpoint must return either a `Response`, or a `Promise` that resolves with a `Response`." }; const LocalsNotAnObject = { name: "LocalsNotAnObject", title: "Value assigned to `locals` is not accepted.", message: "`locals` can only be assigned to an object. Other values like numbers, strings, etc. are not accepted.", hint: "If you tried to remove some information from the `locals` object, try to use `delete` or set the property to `undefined`." }; const LocalsReassigned = { name: "LocalsReassigned", title: "`locals` must not be reassigned.", message: "`locals` cannot be assigned directly.", hint: "Set a `locals` property instead." }; const AstroResponseHeadersReassigned = { name: "AstroResponseHeadersReassigned", title: "`Astro.response.headers` must not be reassigned.", message: "Individual headers can be added to and removed from `Astro.response.headers`, but it must not be replaced with another instance of `Headers` altogether.", hint: "Consider using `Astro.response.headers.add()`, and `Astro.response.headers.delete()`." }; const LocalImageUsedWrongly = { name: "LocalImageUsedWrongly", title: "Local images must be imported.", message: (imageFilePath) => `\`Image\`'s and \`getImage\`'s \`src\` parameter must be an imported image or an URL, it cannot be a string filepath. Received \`${imageFilePath}\`.`, hint: "If you want to use an image from your `src` folder, you need to either import it or if the image is coming from a content collection, use the [image() schema helper](https://docs.astro.build/en/guides/images/#images-in-content-collections). See https://docs.astro.build/en/guides/images/#src-required for more information on the `src` property." }; const MissingSharp = { name: "MissingSharp", title: "Could not find Sharp.", message: "Could not find Sharp. Please install Sharp (`sharp`) manually into your project or migrate to another image service.", hint: "See Sharp's installation instructions for more information: https://sharp.pixelplumbing.com/install. If you are not relying on `astro:assets` to optimize, transform, or process any images, you can configure a passthrough image service instead of installing Sharp. See https://docs.astro.build/en/reference/errors/missing-sharp for more information.\n\nSee https://docs.astro.build/en/guides/images/#default-image-service for more information on how to migrate to another image service." }; const i18nNoLocaleFoundInPath = { name: "i18nNoLocaleFoundInPath", title: "The path doesn't contain any locale", message: "You tried to use an i18n utility on a path that doesn't contain any locale. You can use `pathHasLocale` first to determine if the path has a locale." }; const RewriteWithBodyUsed = { name: "RewriteWithBodyUsed", title: "Cannot use Astro.rewrite after the request body has been read", message: "Astro.rewrite() cannot be used if the request body has already been read. If you need to read the body, first clone the request." }; const ForbiddenRewrite = { name: "ForbiddenRewrite", title: "Forbidden rewrite to a static route.", message: (from, to, component) => `You tried to rewrite the on-demand route '${from}' with the static route '${to}', when using the 'server' output. The static route '${to}' is rendered by the component '${component}', which is marked as prerendered. This is a forbidden operation because during the build, the component '${component}' is compiled to an HTML file, which can't be retrieved at runtime by Astro.`, hint: (component) => `Add \`export const prerender = false\` to the component '${component}', or use a Astro.redirect().` }; const FontFamilyNotFound = { name: "FontFamilyNotFound", title: "Font family not found", message: (family) => `No data was found for the \`"${family}"\` family passed to the \`\` component.`, hint: "This is often caused by a typo. Check that the `` component is using a `cssVariable` specified in your config." }; const UnableToLoadLogger = { name: "UnableToLoadLogger", title: "Unable to load the logger.", message: (path) => `Couldn't load the logger at given path "${path}".` }; const UnknownContentCollectionError = { name: "UnknownContentCollectionError", title: "Unknown Content Collection Error." }; const RenderUndefinedEntryError = { name: "RenderUndefinedEntryError", title: "Attempted to render an undefined content collection entry.", hint: "Check if the entry is undefined before passing it to `render()`" }; const ActionsReturnedInvalidDataError = { name: "ActionsReturnedInvalidDataError", title: "Action handler returned invalid data.", message: (error) => `Action handler returned invalid data. Handlers should return serializable data types like objects, arrays, strings, and numbers. Parse error: ${error}`, hint: "See the devalue library for all supported types: https://github.com/rich-harris/devalue" }; const ActionNotFoundError = { name: "ActionNotFoundError", title: "Action not found.", message: (actionName) => `The server received a request for an action named \`${actionName}\` but could not find a match. If you renamed an action, check that you've updated your \`actions/index\` file and your calling code to match.`, hint: "You can run `astro check` to detect type errors caused by mismatched action names." }; const SessionStorageInitError = { name: "SessionStorageInitError", title: "Session storage could not be initialized.", message: (error, driver) => `Error when initializing session storage${driver ? ` with driver \`${driver}\`` : ""}. \`${error ?? ""}\``, hint: "For more information, see https://docs.astro.build/en/guides/sessions/" }; const SessionStorageSaveError = { name: "SessionStorageSaveError", title: "Session data could not be saved.", message: (error, driver) => `Error when saving session data${driver ? ` with driver \`${driver}\`` : ""}. \`${error ?? ""}\``, hint: "For more information, see https://docs.astro.build/en/guides/sessions/" }; const CacheNotEnabled = { name: "CacheNotEnabled", title: "Cache is not enabled.", message: "`Astro.cache` is not available because the cache feature is not enabled. To use caching, configure a cache provider in your Astro config under `experimental.cache`.", hint: 'Use an adapter that provides a default cache provider, or set one explicitly: `experimental: { cache: { provider: "..." } }`. See https://docs.astro.build/en/reference/experimental-flags/route-caching/.' }; function normalizeLF(code) { return code.replace(/\r\n|\r(?!\n)|\n/g, "\n"); } function codeFrame(src, loc) { if (!loc || loc.line === void 0 || loc.column === void 0) { return ""; } const lines = normalizeLF(src).split("\n").map((ln) => ln.replace(/\t/g, " ")); const visibleLines = []; for (let n = -2; n <= 2; n++) { if (lines[loc.line + n]) visibleLines.push(loc.line + n); } let gutterWidth = 0; for (const lineNo of visibleLines) { let w = `> ${lineNo}`; if (w.length > gutterWidth) gutterWidth = w.length; } let output = ""; for (const lineNo of visibleLines) { const isFocusedLine = lineNo === loc.line - 1; output += isFocusedLine ? "> " : " "; output += `${lineNo + 1} | ${lines[lineNo]} `; if (isFocusedLine) output += `${Array.from({ length: gutterWidth }).join(" ")} | ${Array.from({ length: loc.column }).join(" ")}^ `; } return output; } class AstroError extends Error { loc; title; hint; frame; type = "AstroError"; constructor(props, options) { const { name, title, message, stack, location, hint, frame } = props; super(message, options); this.title = title; this.name = name; if (message) this.message = message; this.stack = stack ? stack : this.stack; this.loc = location; this.hint = hint; this.frame = frame; } setLocation(location) { this.loc = location; } setName(name) { this.name = name; } setMessage(message) { this.message = message; } setHint(hint) { this.hint = hint; } setFrame(source, location) { this.frame = codeFrame(source, location); } static is(err) { return err?.type === "AstroError"; } } class AstroUserError extends Error { type = "AstroUserError"; /** * A message that explains to the user how they can fix the error. */ hint; name = "AstroUserError"; constructor(message, hint) { super(); this.message = message; this.hint = hint; } static is(err) { return err?.type === "AstroUserError"; } } function computeFallbackRoute(options) { const { pathname, responseStatus, fallback, fallbackType, locales, defaultLocale, strategy, base } = options; if (responseStatus !== 404) { return { type: "none" }; } if (!fallback || Object.keys(fallback).length === 0) { return { type: "none" }; } const segments = pathname.split("/"); const urlLocale = segments.find((segment) => { for (const locale of locales) { if (typeof locale === "string") { if (locale === segment) { return true; } } else if (locale.path === segment) { return true; } } return false; }); if (!urlLocale) { return { type: "none" }; } const fallbackKeys = Object.keys(fallback); if (!fallbackKeys.includes(urlLocale)) { return { type: "none" }; } const fallbackLocale = fallback[urlLocale]; const pathFallbackLocale = getPathByLocale(fallbackLocale, locales); let newPathname; if (pathFallbackLocale === defaultLocale && strategy === "pathname-prefix-other-locales") { if (pathname.includes(`${base}`)) { newPathname = pathname.replace(`/${urlLocale}`, ``); } else { newPathname = pathname.replace(`/${urlLocale}`, `/`); } } else { newPathname = pathname.replace(`/${urlLocale}`, `/${pathFallbackLocale}`); } return { type: fallbackType, pathname: newPathname }; } class I18nRouter { #strategy; #defaultLocale; #locales; #base; #domains; constructor(options) { this.#strategy = options.strategy; this.#defaultLocale = options.defaultLocale; this.#locales = options.locales; this.#base = options.base === "/" ? "/" : removeTrailingForwardSlash(options.base || ""); this.#domains = options.domains; } /** * Evaluate routing strategy for a pathname. * Returns decision object (not HTTP Response). */ match(pathname, context) { if (this.shouldSkipProcessing(pathname, context)) { return { type: "continue" }; } switch (this.#strategy) { case "manual": return { type: "continue" }; case "pathname-prefix-always": return this.matchPrefixAlways(pathname, context); case "domains-prefix-always": if (this.localeHasntDomain(context.currentLocale, context.currentDomain)) { return { type: "continue" }; } return this.matchPrefixAlways(pathname, context); case "pathname-prefix-other-locales": return this.matchPrefixOtherLocales(pathname, context); case "domains-prefix-other-locales": if (this.localeHasntDomain(context.currentLocale, context.currentDomain)) { return { type: "continue" }; } return this.matchPrefixOtherLocales(pathname, context); case "pathname-prefix-always-no-redirect": return this.matchPrefixAlwaysNoRedirect(pathname, context); case "domains-prefix-always-no-redirect": if (this.localeHasntDomain(context.currentLocale, context.currentDomain)) { return { type: "continue" }; } return this.matchPrefixAlwaysNoRedirect(pathname, context); default: return { type: "continue" }; } } /** * Check if i18n processing should be skipped for this request */ shouldSkipProcessing(pathname, context) { if (pathname.includes("/404") || pathname.includes("/500")) { return true; } if (pathname.includes("/_server-islands/")) { return true; } if (context.isReroute) { return true; } if (context.routeType && context.routeType !== "page" && context.routeType !== "fallback") { return true; } return false; } /** * Strategy: pathname-prefix-always * All locales must have a prefix, including the default locale. */ matchPrefixAlways(pathname, _context) { const isRoot = pathname === this.#base + "/" || pathname === this.#base; if (isRoot) { const basePrefix = this.#base === "/" ? "" : this.#base; return { type: "redirect", location: `${basePrefix}/${this.#defaultLocale}` }; } if (!pathHasLocale(pathname, this.#locales)) { return { type: "notFound" }; } return { type: "continue" }; } /** * Strategy: pathname-prefix-other-locales * Default locale has no prefix, other locales must have a prefix. */ matchPrefixOtherLocales(pathname, _context) { let pathnameContainsDefaultLocale = false; for (const segment of pathname.split("/")) { if (normalizeTheLocale(segment) === normalizeTheLocale(this.#defaultLocale)) { pathnameContainsDefaultLocale = true; break; } } if (pathnameContainsDefaultLocale) { const newLocation = pathname.replace(`/${this.#defaultLocale}`, ""); return { type: "notFound", location: newLocation }; } return { type: "continue" }; } /** * Strategy: pathname-prefix-always-no-redirect * Like prefix-always but allows root to serve instead of redirecting */ matchPrefixAlwaysNoRedirect(pathname, _context) { const isRoot = pathname === this.#base + "/" || pathname === this.#base; if (isRoot) { return { type: "continue" }; } if (!pathHasLocale(pathname, this.#locales)) { return { type: "notFound" }; } return { type: "continue" }; } /** * Check if the current locale doesn't belong to the configured domain. * Used for domain-based routing strategies. */ localeHasntDomain(currentLocale, currentDomain) { if (!this.#domains || !currentDomain) { return false; } if (!currentLocale) { return false; } const localesForDomain = this.#domains[currentDomain]; if (!localesForDomain) { return true; } return !localesForDomain.includes(currentLocale); } } function createI18nMiddleware(i18n, base, trailingSlash, format) { if (!i18n) return (_, next) => next(); const i18nRouter = new I18nRouter({ strategy: i18n.strategy, defaultLocale: i18n.defaultLocale, locales: i18n.locales, base, domains: i18n.domainLookupTable ? Object.keys(i18n.domainLookupTable).reduce( (acc, domain) => { const locale = i18n.domainLookupTable[domain]; if (!acc[domain]) { acc[domain] = []; } acc[domain].push(locale); return acc; }, {} ) : void 0 }); return async (context, next) => { const response = await next(); const typeHeader = response.headers.get(ROUTE_TYPE_HEADER); const isReroute = response.headers.get(REROUTE_DIRECTIVE_HEADER); if (isReroute === "no" && typeof i18n.fallback === "undefined") { return response; } if (typeHeader !== "page" && typeHeader !== "fallback") { return response; } const routerContext = { currentLocale: context.currentLocale, currentDomain: context.url.hostname, routeType: typeHeader, isReroute: isReroute === "yes" }; const routeDecision = i18nRouter.match(context.url.pathname, routerContext); switch (routeDecision.type) { case "redirect": { let location = routeDecision.location; if (shouldAppendForwardSlash(trailingSlash, format)) { location = appendForwardSlash(location); } return context.redirect(location, routeDecision.status); } case "notFound": { if (context.isPrerendered) { const prerenderedRes = new Response(response.body, { status: 404, headers: response.headers }); prerenderedRes.headers.set(REROUTE_DIRECTIVE_HEADER, "no"); if (routeDecision.location) { prerenderedRes.headers.set("Location", routeDecision.location); } return prerenderedRes; } const headers = new Headers(); if (routeDecision.location) { headers.set("Location", routeDecision.location); } return new Response(null, { status: 404, headers }); } } if (i18n.fallback && i18n.fallbackType) { const fallbackDecision = computeFallbackRoute({ pathname: context.url.pathname, responseStatus: response.status, currentLocale: context.currentLocale, fallback: i18n.fallback, fallbackType: i18n.fallbackType, locales: i18n.locales, defaultLocale: i18n.defaultLocale, strategy: i18n.strategy, base }); switch (fallbackDecision.type) { case "redirect": return context.redirect(fallbackDecision.pathname + context.url.search); case "rewrite": return await context.rewrite(fallbackDecision.pathname + context.url.search); } } return response; }; } function pathHasLocale(path, locales) { const segments = path.split("/").map(normalizeThePath); for (const segment of segments) { for (const locale of locales) { if (typeof locale === "string") { if (normalizeTheLocale(segment) === normalizeTheLocale(locale)) { return true; } } else if (segment === locale.path) { return true; } } } return false; } function getPathByLocale(locale, locales) { for (const loopLocale of locales) { if (typeof loopLocale === "string") { if (loopLocale === locale) { return loopLocale; } } else { for (const code of loopLocale.codes) { if (code === locale) { return loopLocale.path; } } } } throw new AstroError(i18nNoLocaleFoundInPath); } function normalizeTheLocale(locale) { return locale.replaceAll("_", "-").toLowerCase(); } function normalizeThePath(path) { return path.endsWith(".html") ? path.slice(0, -5) : path; } function getAllCodes(locales) { const result = []; for (const loopLocale of locales) { if (typeof loopLocale === "string") { result.push(loopLocale); } else { result.push(...loopLocale.codes); } } return result; } const DELETED_EXPIRATION = /* @__PURE__ */ new Date(0); const DELETED_VALUE = "deleted"; const responseSentSymbol = /* @__PURE__ */ Symbol.for("astro.responseSent"); const identity = (value) => value; class AstroCookie { value; constructor(value) { this.value = value; } json() { if (this.value === void 0) { throw new Error(`Cannot convert undefined to an object.`); } return JSON.parse(this.value); } number() { return Number(this.value); } boolean() { if (this.value === "false") return false; if (this.value === "0") return false; return Boolean(this.value); } } class AstroCookies { #request; #requestValues; #outgoing; #consumed; constructor(request) { this.#request = request; this.#requestValues = null; this.#outgoing = null; this.#consumed = false; } /** * Astro.cookies.delete(key) is used to delete a cookie. Using this method will result * in a Set-Cookie header added to the response. * @param key The cookie to delete * @param options Options related to this deletion, such as the path of the cookie. */ delete(key, options) { const { // @ts-expect-error maxAge: _ignoredMaxAge, // @ts-expect-error expires: _ignoredExpires, ...sanitizedOptions } = options || {}; const serializeOptions = { expires: DELETED_EXPIRATION, ...sanitizedOptions }; this.#ensureOutgoingMap().set(key, [ DELETED_VALUE, serialize(key, DELETED_VALUE, serializeOptions), false ]); } /** * Astro.cookies.get(key) is used to get a cookie value. The cookie value is read from the * request. If you have set a cookie via Astro.cookies.set(key, value), the value will be taken * from that set call, overriding any values already part of the request. * @param key The cookie to get. * @returns An object containing the cookie value as well as convenience methods for converting its value. */ get(key, options = void 0) { if (this.#outgoing?.has(key)) { let [serializedValue, , isSetValue] = this.#outgoing.get(key); if (isSetValue) { return new AstroCookie(serializedValue); } else { return void 0; } } const decode = options?.decode ?? decodeURIComponent; const values = this.#ensureParsed(); if (key in values) { const value = values[key]; if (value) { let decodedValue; try { decodedValue = decode(value); } catch (_error) { decodedValue = value; } return new AstroCookie(decodedValue); } } } /** * Astro.cookies.has(key) returns a boolean indicating whether this cookie is either * part of the initial request or set via Astro.cookies.set(key) * @param key The cookie to check for. * @param _options This parameter is no longer used. * @returns */ has(key, _options) { if (this.#outgoing?.has(key)) { let [, , isSetValue] = this.#outgoing.get(key); return isSetValue; } const values = this.#ensureParsed(); return values[key] !== void 0; } /** * Astro.cookies.set(key, value) is used to set a cookie's value. If provided * an object it will be stringified via JSON.stringify(value). Additionally you * can provide options customizing how this cookie will be set, such as setting httpOnly * in order to prevent the cookie from being read in client-side JavaScript. * @param key The name of the cookie to set. * @param value A value, either a string or other primitive or an object. * @param options Options for the cookie, such as the path and security settings. */ set(key, value, options) { if (this.#consumed) { const warning = new Error( "Astro.cookies.set() was called after the cookies had already been sent to the browser.\nThis may have happened if this method was called in an imported component.\nPlease make sure that Astro.cookies.set() is only called in the frontmatter of the main page." ); warning.name = "Warning"; console.warn(warning); } let serializedValue; if (typeof value === "string") { serializedValue = value; } else { let toStringValue = value.toString(); if (toStringValue === Object.prototype.toString.call(value)) { serializedValue = JSON.stringify(value); } else { serializedValue = toStringValue; } } const serializeOptions = {}; if (options) { Object.assign(serializeOptions, options); } this.#ensureOutgoingMap().set(key, [ serializedValue, serialize(key, serializedValue, serializeOptions), true ]); if (this.#request[responseSentSymbol]) { throw new AstroError({ ...ResponseSentError }); } } /** * Merges a new AstroCookies instance into the current instance. Any new cookies * will be added to the current instance, overwriting any existing cookies with the same name. */ merge(cookies) { const outgoing = cookies.#outgoing; if (outgoing) { for (const [key, value] of outgoing) { this.#ensureOutgoingMap().set(key, value); } } } /** * Astro.cookies.header() returns an iterator for the cookies that have previously * been set by either Astro.cookies.set() or Astro.cookies.delete(). * This method is primarily used by adapters to set the header on outgoing responses. * @returns */ *headers() { if (this.#outgoing == null) return; for (const [, value] of this.#outgoing) { yield value[1]; } } /** * Behaves the same as AstroCookies.prototype.headers(), * but allows a warning when cookies are set after the instance is consumed. */ static consume(cookies) { cookies.#consumed = true; return cookies.headers(); } #ensureParsed() { if (!this.#requestValues) { this.#parse(); } if (!this.#requestValues) { this.#requestValues = /* @__PURE__ */ Object.create(null); } return this.#requestValues; } #ensureOutgoingMap() { if (!this.#outgoing) { this.#outgoing = /* @__PURE__ */ new Map(); } return this.#outgoing; } #parse() { const raw = this.#request.headers.get("cookie"); if (!raw) { return; } this.#requestValues = parse(raw, { decode: identity }); } } const astroCookiesSymbol = /* @__PURE__ */ Symbol.for("astro.cookies"); function attachCookiesToResponse(response, cookies) { Reflect.set(response, astroCookiesSymbol, cookies); } function getCookiesFromResponse(response) { let cookies = Reflect.get(response, astroCookiesSymbol); if (cookies != null) { return cookies; } else { return void 0; } } function* getSetCookiesFromResponse(response) { const cookies = getCookiesFromResponse(response); if (!cookies) { return []; } for (const headerValue of AstroCookies.consume(cookies)) { yield headerValue; } return []; } const dateTimeFormat = new Intl.DateTimeFormat([], { hour: "2-digit", minute: "2-digit", second: "2-digit", hour12: false }); const levels = { debug: 20, info: 30, warn: 40, error: 50, silent: 90 }; function log(opts, level, label, message, newLine = true) { const logLevel = opts.level; const dest = opts.destination; const event = { label, level, message, newLine }; if (!isLogLevelEnabled(logLevel, level)) { return; } dest.write(event); } function isLogLevelEnabled(configuredLogLevel, level) { return levels[configuredLogLevel] <= levels[level]; } function info(opts, label, message, newLine = true) { return log(opts, "info", label, message, newLine); } function warn(opts, label, message, newLine = true) { return log(opts, "warn", label, message, newLine); } function error(opts, label, message, newLine = true) { return log(opts, "error", label, message, newLine); } function debug(...args) { if ("_astroGlobalDebug" in globalThis) { globalThis._astroGlobalDebug(...args); } } function getEventPrefix({ level, label }) { const timestamp = `${dateTimeFormat.format(/* @__PURE__ */ new Date())}`; const prefix = []; if (level === "error" || level === "warn") { prefix.push(colors.bold(timestamp)); prefix.push(`[${level.toUpperCase()}]`); } else { prefix.push(timestamp); } if (label) { prefix.push(`[${label}]`); } if (level === "error") { return colors.red(prefix.join(" ")); } if (level === "warn") { return colors.yellow(prefix.join(" ")); } if (prefix.length === 1) { return colors.dim(prefix[0]); } return colors.dim(prefix[0]) + " " + colors.blue(prefix.splice(1).join(" ")); } class AstroLogger { options; constructor(options) { this.options = options; } info(label, message, newLine = true) { info(this.options, label, message, newLine); } warn(label, message, newLine = true) { warn(this.options, label, message, newLine); } error(label, message, newLine = true) { error(this.options, label, message, newLine); } debug(label, ...messages) { debug(label, ...messages); } level() { return this.options.level; } forkIntegrationLogger(label) { return new AstroIntegrationLogger(this.options, label); } setDestination(destination) { this.options.destination = destination; } /** * It calls the `close` function of the provided destination, if it exists. */ close() { if (this.options.destination.close) { this.options.destination.close(); } } /** * It calls the `flush` function of the provided destinatin, if it exists. */ flush() { if (this.options.destination.flush) { this.options.destination.flush(); } } } class AstroIntegrationLogger { options; label; constructor(logging, label) { this.options = logging; this.label = label; } /** * Creates a new logger instance with a new label, but the same log options. */ fork(label) { return new AstroIntegrationLogger(this.options, label); } info(message) { info(this.options, this.label, message); } warn(message) { warn(this.options, this.label, message); } error(message) { error(this.options, this.label, message); } debug(message) { debug(this.label, message); } } const ACTION_QUERY_PARAMS = { actionName: "_action"}; const ACTION_RPC_ROUTE_PATTERN = "/_actions/[...path]"; const __vite_import_meta_env__$1 = {"ASSETS_PREFIX": undefined, "BASE_URL": "/", "DEV": false, "MODE": "production", "PROD": true, "SITE": undefined, "SSR": true}; const codeToStatusMap = { // Implemented from IANA HTTP Status Code Registry // https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml BAD_REQUEST: 400, UNAUTHORIZED: 401, PAYMENT_REQUIRED: 402, FORBIDDEN: 403, NOT_FOUND: 404, METHOD_NOT_ALLOWED: 405, NOT_ACCEPTABLE: 406, PROXY_AUTHENTICATION_REQUIRED: 407, REQUEST_TIMEOUT: 408, CONFLICT: 409, GONE: 410, LENGTH_REQUIRED: 411, PRECONDITION_FAILED: 412, CONTENT_TOO_LARGE: 413, URI_TOO_LONG: 414, UNSUPPORTED_MEDIA_TYPE: 415, RANGE_NOT_SATISFIABLE: 416, EXPECTATION_FAILED: 417, MISDIRECTED_REQUEST: 421, UNPROCESSABLE_CONTENT: 422, LOCKED: 423, FAILED_DEPENDENCY: 424, TOO_EARLY: 425, UPGRADE_REQUIRED: 426, PRECONDITION_REQUIRED: 428, TOO_MANY_REQUESTS: 429, REQUEST_HEADER_FIELDS_TOO_LARGE: 431, UNAVAILABLE_FOR_LEGAL_REASONS: 451, INTERNAL_SERVER_ERROR: 500, NOT_IMPLEMENTED: 501, BAD_GATEWAY: 502, SERVICE_UNAVAILABLE: 503, GATEWAY_TIMEOUT: 504, HTTP_VERSION_NOT_SUPPORTED: 505, VARIANT_ALSO_NEGOTIATES: 506, INSUFFICIENT_STORAGE: 507, LOOP_DETECTED: 508, NETWORK_AUTHENTICATION_REQUIRED: 511 }; const statusToCodeMap = Object.fromEntries( Object.entries(codeToStatusMap).map(([key, value]) => [value, key]) ); class ActionError extends Error { type = "AstroActionError"; code = "INTERNAL_SERVER_ERROR"; status = 500; constructor(params) { super(params.message); this.code = params.code; this.status = ActionError.codeToStatus(params.code); if (params.stack) { this.stack = params.stack; } } static codeToStatus(code) { return codeToStatusMap[code]; } static statusToCode(status) { return statusToCodeMap[status] ?? "INTERNAL_SERVER_ERROR"; } static fromJson(body) { if (isInputError(body)) { return new ActionInputError(body.issues); } if (isActionError(body)) { return new ActionError(body); } return new ActionError({ code: "INTERNAL_SERVER_ERROR" }); } } function isActionError(error) { return typeof error === "object" && error != null && "type" in error && error.type === "AstroActionError"; } function isInputError(error) { return typeof error === "object" && error != null && "type" in error && error.type === "AstroActionInputError" && "issues" in error && Array.isArray(error.issues); } class ActionInputError extends ActionError { type = "AstroActionInputError"; // We don't expose all ZodError properties. // Not all properties will serialize from server to client, // and we don't want to import the full ZodError object into the client. issues; fields; constructor(issues) { super({ message: `Failed to validate: ${JSON.stringify(issues, null, 2)}`, code: "BAD_REQUEST" }); this.issues = issues; this.fields = {}; for (const issue of issues) { if (issue.path.length > 0) { const key = issue.path[0].toString(); this.fields[key] ??= []; this.fields[key]?.push(issue.message); } } } } function deserializeActionResult(res) { if (res.type === "error") { let json; try { json = JSON.parse(res.body); } catch { return { data: void 0, error: new ActionError({ message: res.body, code: "INTERNAL_SERVER_ERROR" }) }; } if (Object.assign(__vite_import_meta_env__$1, { OS: "Windows_NT", _: "C:/Program Files/nodejs/node.exe" })?.PROD) { return { error: ActionError.fromJson(json), data: void 0 }; } else { const error = ActionError.fromJson(json); error.stack = actionResultErrorStack.get(); return { error, data: void 0 }; } } if (res.type === "empty") { return { data: void 0, error: void 0 }; } return { data: parse$1(res.body, { URL: (href) => new URL(href) }), error: void 0 }; } const actionResultErrorStack = /* @__PURE__ */ (function actionResultErrorStackFn() { let errorStack; return { set(stack) { errorStack = stack; }, get() { return errorStack; } }; })(); function getActionQueryString(name) { const searchParams = new URLSearchParams({ [ACTION_QUERY_PARAMS.actionName]: name }); return `?${searchParams.toString()}`; } async function readBodyWithLimit(request, limit) { const contentLengthHeader = request.headers.get("content-length"); if (contentLengthHeader) { const contentLength = Number.parseInt(contentLengthHeader, 10); if (Number.isFinite(contentLength) && contentLength > limit) { throw new BodySizeLimitError(limit); } } if (!request.body) return new Uint8Array(); const reader = request.body.getReader(); const chunks = []; let received = 0; while (true) { const { done, value } = await reader.read(); if (done) break; if (value) { received += value.byteLength; if (received > limit) { throw new BodySizeLimitError(limit); } chunks.push(value); } } const buffer = new Uint8Array(received); let offset = 0; for (const chunk of chunks) { buffer.set(chunk, offset); offset += chunk.byteLength; } return buffer; } class BodySizeLimitError extends Error { limit; constructor(limit) { super(`Request body exceeds the configured limit of ${limit} bytes`); this.name = "BodySizeLimitError"; this.limit = limit; } } const __vite_import_meta_env__ = {"ASSETS_PREFIX": undefined, "BASE_URL": "/", "DEV": false, "MODE": "production", "PROD": true, "SITE": undefined, "SSR": true}; function getActionContext(context) { const callerInfo = getCallerInfo(context); const actionResultAlreadySet = Boolean(context.locals._actionPayload); let action = void 0; if (callerInfo && context.request.method === "POST" && !actionResultAlreadySet) { action = { calledFrom: callerInfo.from, name: callerInfo.name, handler: async () => { const pipeline = Reflect.get(context, pipelineSymbol); const callerInfoName = shouldAppendForwardSlash( pipeline.manifest.trailingSlash, pipeline.manifest.buildFormat ) ? removeTrailingForwardSlash(callerInfo.name) : callerInfo.name; let baseAction; try { baseAction = await pipeline.getAction(callerInfoName); } catch (error) { if (error instanceof Error && "name" in error && typeof error.name === "string" && error.name === ActionNotFoundError.name) { return { data: void 0, error: new ActionError({ code: "NOT_FOUND" }) }; } throw error; } const bodySizeLimit = pipeline.manifest.actionBodySizeLimit; let input; try { input = await parseRequestBody(context.request, bodySizeLimit); } catch (e) { if (e instanceof ActionError) { return { data: void 0, error: e }; } if (e instanceof TypeError) { return { data: void 0, error: new ActionError({ code: "UNSUPPORTED_MEDIA_TYPE" }) }; } throw e; } const omitKeys = ["props", "getActionResult", "callAction", "redirect"]; const actionAPIContext = Object.create( Object.getPrototypeOf(context), Object.fromEntries( Object.entries(Object.getOwnPropertyDescriptors(context)).filter( ([key]) => !omitKeys.includes(key) ) ) ); Reflect.set(actionAPIContext, ACTION_API_CONTEXT_SYMBOL, true); const handler = baseAction.bind(actionAPIContext); return handler(input); } }; } function setActionResult(actionName, actionResult) { context.locals._actionPayload = { actionResult, actionName }; } return { action, setActionResult, serializeActionResult, deserializeActionResult }; } function getCallerInfo(ctx) { if (ctx.routePattern === ACTION_RPC_ROUTE_PATTERN) { return { from: "rpc", name: ctx.url.pathname.replace(/^.*\/_actions\//, "") }; } const queryParam = ctx.url.searchParams.get(ACTION_QUERY_PARAMS.actionName); if (queryParam) { return { from: "form", name: queryParam }; } return void 0; } async function parseRequestBody(request, bodySizeLimit) { const contentType = request.headers.get("content-type"); const contentLengthHeader = request.headers.get("content-length"); const contentLength = contentLengthHeader ? Number.parseInt(contentLengthHeader, 10) : void 0; const hasContentLength = typeof contentLength === "number" && Number.isFinite(contentLength); if (!contentType) return void 0; if (hasContentLength && contentLength > bodySizeLimit) { throw new ActionError({ code: "CONTENT_TOO_LARGE", message: `Request body exceeds ${bodySizeLimit} bytes` }); } try { if (hasContentType(contentType, formContentTypes)) { if (!hasContentLength) { const body = await readBodyWithLimit(request.clone(), bodySizeLimit); const formRequest = new Request(request.url, { method: request.method, headers: request.headers, body: toArrayBuffer(body) }); return await formRequest.formData(); } return await request.clone().formData(); } if (hasContentType(contentType, ["application/json"])) { if (contentLength === 0) return void 0; if (!hasContentLength) { const body = await readBodyWithLimit(request.clone(), bodySizeLimit); if (body.byteLength === 0) return void 0; return JSON.parse(new TextDecoder().decode(body)); } return await request.clone().json(); } } catch (e) { if (e instanceof BodySizeLimitError) { throw new ActionError({ code: "CONTENT_TOO_LARGE", message: `Request body exceeds ${bodySizeLimit} bytes` }); } throw e; } throw new TypeError("Unsupported content type"); } const ACTION_API_CONTEXT_SYMBOL = /* @__PURE__ */ Symbol.for("astro.actionAPIContext"); const formContentTypes = ["application/x-www-form-urlencoded", "multipart/form-data"]; function hasContentType(contentType, expected) { const type = contentType.split(";")[0].toLowerCase(); return expected.some((t) => type === t); } function serializeActionResult(res) { if (res.error) { if (Object.assign(__vite_import_meta_env__, { OS: "Windows_NT", _: "C:/Program Files/nodejs/node.exe" })?.DEV) { actionResultErrorStack.set(res.error.stack); } let body2; if (res.error instanceof ActionInputError) { body2 = { type: res.error.type, issues: res.error.issues, fields: res.error.fields }; } else { body2 = { ...res.error, message: res.error.message }; } return { type: "error", status: res.error.status, contentType: "application/json", body: JSON.stringify(body2) }; } if (res.data === void 0) { return { type: "empty", status: 204 }; } let body; try { body = stringify$1(res.data, { // Add support for URL objects URL: (value) => value instanceof URL && value.href }); } catch (e) { let hint = ActionsReturnedInvalidDataError.hint; if (res.data instanceof Response) { hint = REDIRECT_STATUS_CODES.includes(res.data.status) ? "If you need to redirect when the action succeeds, trigger a redirect where the action is called. See the Actions guide for server and client redirect examples: https://docs.astro.build/en/guides/actions." : "If you need to return a Response object, try using a server endpoint instead. See https://docs.astro.build/en/guides/endpoints/#server-endpoints-api-routes"; } throw new AstroError({ ...ActionsReturnedInvalidDataError, message: ActionsReturnedInvalidDataError.message(String(e)), hint }); } return { type: "data", status: 200, contentType: "application/json+devalue", body }; } function toArrayBuffer(buffer) { const copy = new Uint8Array(buffer.byteLength); copy.set(buffer); return copy.buffer; } function hasActionPayload(locals) { return "_actionPayload" in locals; } function createGetActionResult(locals) { return (actionFn) => { if (!hasActionPayload(locals) || actionFn.toString() !== getActionQueryString(locals._actionPayload.actionName)) { return void 0; } return deserializeActionResult(locals._actionPayload.actionResult); }; } function createCallAction(context) { return (baseAction, input) => { Reflect.set(context, ACTION_API_CONTEXT_SYMBOL, true); const action = baseAction.bind(context); return action(input); }; } function parseLocale(header) { if (header === "*") { return [{ locale: header, qualityValue: void 0 }]; } const result = []; const localeValues = header.split(",").map((str) => str.trim()); for (const localeValue of localeValues) { const split = localeValue.split(";").map((str) => str.trim()); const localeName = split[0]; const qualityValue = split[1]; if (!split) { continue; } if (qualityValue && qualityValue.startsWith("q=")) { const qualityValueAsFloat = Number.parseFloat(qualityValue.slice("q=".length)); if (Number.isNaN(qualityValueAsFloat) || qualityValueAsFloat > 1) { result.push({ locale: localeName, qualityValue: void 0 }); } else { result.push({ locale: localeName, qualityValue: qualityValueAsFloat }); } } else { result.push({ locale: localeName, qualityValue: void 0 }); } } return result; } function sortAndFilterLocales(browserLocaleList, locales) { const normalizedLocales = getAllCodes(locales).map(normalizeTheLocale); return browserLocaleList.filter((browserLocale) => { if (browserLocale.locale !== "*") { return normalizedLocales.includes(normalizeTheLocale(browserLocale.locale)); } return true; }).sort((a, b) => { if (a.qualityValue && b.qualityValue) { return Math.sign(b.qualityValue - a.qualityValue); } return 0; }); } function computePreferredLocale(request, locales) { const acceptHeader = request.headers.get("Accept-Language"); let result = void 0; if (acceptHeader) { const browserLocaleList = sortAndFilterLocales(parseLocale(acceptHeader), locales); const firstResult = browserLocaleList.at(0); if (firstResult && firstResult.locale !== "*") { for (const currentLocale of locales) { if (typeof currentLocale === "string") { if (normalizeTheLocale(currentLocale) === normalizeTheLocale(firstResult.locale)) { result = currentLocale; break; } } else { for (const currentCode of currentLocale.codes) { if (normalizeTheLocale(currentCode) === normalizeTheLocale(firstResult.locale)) { result = currentCode; break; } } } } } } return result; } function computePreferredLocaleList(request, locales) { const acceptHeader = request.headers.get("Accept-Language"); let result = []; if (acceptHeader) { const browserLocaleList = sortAndFilterLocales(parseLocale(acceptHeader), locales); if (browserLocaleList.length === 1 && browserLocaleList.at(0).locale === "*") { return getAllCodes(locales); } else if (browserLocaleList.length > 0) { for (const browserLocale of browserLocaleList) { for (const loopLocale of locales) { if (typeof loopLocale === "string") { if (normalizeTheLocale(loopLocale) === normalizeTheLocale(browserLocale.locale)) { result.push(loopLocale); } } else { for (const code of loopLocale.codes) { if (code === browserLocale.locale) { result.push(code); } } } } } } } return result; } function computeCurrentLocale(pathname, locales, defaultLocale) { for (const segment of pathname.split("/").map(normalizeThePath)) { for (const locale of locales) { if (typeof locale === "string") { if (!segment.includes(locale)) continue; if (normalizeTheLocale(locale) === normalizeTheLocale(segment)) { return locale; } } else { if (locale.path === segment) { return locale.codes.at(0); } else { for (const code of locale.codes) { if (normalizeTheLocale(code) === normalizeTheLocale(segment)) { return code; } } } } } } for (const locale of locales) { if (typeof locale === "string") { if (locale === defaultLocale) { return locale; } } else { if (locale.path === defaultLocale) { return locale.codes.at(0); } } } } function computeCurrentLocaleFromParams(params, locales) { const byNormalizedCode = /* @__PURE__ */ new Map(); const byPath = /* @__PURE__ */ new Map(); for (const locale of locales) { if (typeof locale === "string") { byNormalizedCode.set(normalizeTheLocale(locale), locale); } else { byPath.set(locale.path, locale.codes[0]); for (const code of locale.codes) { byNormalizedCode.set(normalizeTheLocale(code), code); } } } for (const value of Object.values(params)) { if (!value) continue; const pathMatch = byPath.get(value); if (pathMatch) return pathMatch; const codeMatch = byNormalizedCode.get(normalizeTheLocale(value)); if (codeMatch) return codeMatch; } } async function renderEndpoint(mod, context, isPrerendered, logger) { const { request, url } = context; const method = request.method.toUpperCase(); let handler = mod[method] ?? mod["ALL"]; if (!handler && method === "HEAD" && mod["GET"]) { handler = mod["GET"]; } if (isPrerendered && !["GET", "HEAD"].includes(method)) { logger.warn( "router", `${url.pathname} ${colors.bold( method )} requests are not available in static endpoints. Mark this page as server-rendered (\`export const prerender = false;\`) or update your config to \`output: 'server'\` to make all your pages server-rendered by default.` ); } if (handler === void 0) { logger.warn( "router", `No API Route handler exists for the method "${method}" for the route "${url.pathname}". Found handlers: ${Object.keys(mod).map((exp) => JSON.stringify(exp)).join(", ")} ` + ("all" in mod ? `One of the exported handlers is "all" (lowercase), did you mean to export 'ALL'? ` : "") ); return new Response(null, { status: 404 }); } if (typeof handler !== "function") { logger.error( "router", `The route "${url.pathname}" exports a value for the method "${method}", but it is of the type ${typeof handler} instead of a function.` ); return new Response(null, { status: 500 }); } let response = await handler.call(mod, context); if (!response || response instanceof Response === false) { throw new AstroError(EndpointDidNotReturnAResponse); } if (REROUTABLE_STATUS_CODES.includes(response.status)) { try { response.headers.set(REROUTE_DIRECTIVE_HEADER, "no"); } catch (err) { if (err.message?.includes("immutable")) { response = new Response(response.body, response); response.headers.set(REROUTE_DIRECTIVE_HEADER, "no"); } else { throw err; } } } if (method === "HEAD") { return new Response(null, response); } return response; } function isPromise(value) { return !!value && typeof value === "object" && "then" in value && typeof value.then === "function"; } async function* streamAsyncIterator(stream) { const reader = stream.getReader(); try { while (true) { const { done, value } = await reader.read(); if (done) return; yield value; } } finally { reader.releaseLock(); } } const escapeHTML = escape; function stringifyForScript(value) { return JSON.stringify(value)?.replace(/ { if (isHTMLString(value)) { return value; } if (typeof value === "string") { return new HTMLString(value); } return value; }; function isHTMLString(value) { return !!value?.[htmlStringSymbol]; } function markHTMLBytes(bytes) { return new HTMLBytes(bytes); } function hasGetReader(obj) { return typeof obj.getReader === "function"; } async function* unescapeChunksAsync(iterable) { if (hasGetReader(iterable)) { for await (const chunk of streamAsyncIterator(iterable)) { yield unescapeHTML(chunk); } } else { for await (const chunk of iterable) { yield unescapeHTML(chunk); } } } function* unescapeChunks(iterable) { for (const chunk of iterable) { yield unescapeHTML(chunk); } } function unescapeHTML(str) { if (!!str && typeof str === "object") { if (str instanceof Uint8Array) { return markHTMLBytes(str); } else if (str instanceof Response && str.body) { const body = str.body; return unescapeChunksAsync(body); } else if (typeof str.then === "function") { return Promise.resolve(str).then((value) => { return unescapeHTML(value); }); } else if (str[/* @__PURE__ */ Symbol.for("astro:slot-string")]) { return str; } else if (Symbol.iterator in str) { return unescapeChunks(str); } else if (Symbol.asyncIterator in str || hasGetReader(str)) { return unescapeChunksAsync(str); } } return markHTMLString(str); } const AstroJSX = "astro:jsx"; const Empty = /* @__PURE__ */ Symbol("empty"); const toSlotName = (slotAttr) => slotAttr; function isVNode(vnode) { return vnode && typeof vnode === "object" && vnode[AstroJSX]; } function transformSlots(vnode) { if (typeof vnode.type === "string") return vnode; const slots = {}; if (isVNode(vnode.props.children)) { const child = vnode.props.children; if (!isVNode(child)) return; if (!("slot" in child.props)) return; const name = toSlotName(child.props.slot); slots[name] = [child]; slots[name]["$$slot"] = true; delete child.props.slot; delete vnode.props.children; } else if (Array.isArray(vnode.props.children)) { vnode.props.children = vnode.props.children.map((child) => { if (!isVNode(child)) return child; if (!("slot" in child.props)) return child; const name = toSlotName(child.props.slot); if (Array.isArray(slots[name])) { slots[name].push(child); } else { slots[name] = [child]; slots[name]["$$slot"] = true; } delete child.props.slot; return Empty; }).filter((v) => v !== Empty); } Object.assign(vnode.props, slots); } function markRawChildren(child) { if (typeof child === "string") return markHTMLString(child); if (Array.isArray(child)) return child.map((c) => markRawChildren(c)); return child; } function transformSetDirectives(vnode) { if (!("set:html" in vnode.props || "set:text" in vnode.props)) return; if ("set:html" in vnode.props) { const children = markRawChildren(vnode.props["set:html"]); delete vnode.props["set:html"]; Object.assign(vnode.props, { children }); return; } if ("set:text" in vnode.props) { const children = vnode.props["set:text"]; delete vnode.props["set:text"]; Object.assign(vnode.props, { children }); return; } } function createVNode(type, props = {}, key) { const vnode = { [Renderer]: "astro:jsx", [AstroJSX]: true, type, props }; transformSetDirectives(vnode); transformSlots(vnode); return vnode; } function resolvePropagationHint(input) { const explicitHint = input.factoryHint ?? "none"; if (explicitHint !== "none") { return explicitHint; } if (!input.moduleId) { return "none"; } return input.metadataLookup(input.moduleId) ?? "none"; } function isPropagatingHint(hint) { return hint === "self" || hint === "in-tree"; } function getPropagationHint$1(result, factory) { return resolvePropagationHint({ factoryHint: factory.propagation, moduleId: factory.moduleId, metadataLookup: (moduleId) => result.componentMetadata.get(moduleId)?.propagation }); } function isAstroComponentFactory(obj) { return obj == null ? false : obj.isAstroComponentFactory === true; } function isAPropagatingComponent(result, factory) { return isPropagatingHint(getPropagationHint(result, factory)); } function getPropagationHint(result, factory) { return getPropagationHint$1(result, factory); } const PROP_TYPE = { Value: 0, JSON: 1, // Actually means Array RegExp: 2, Date: 3, Map: 4, Set: 5, BigInt: 6, URL: 7, Uint8Array: 8, Uint16Array: 9, Uint32Array: 10, Infinity: 11 }; function serializeArray(value, metadata = {}, parents = /* @__PURE__ */ new WeakSet()) { if (parents.has(value)) { throw new Error(`Cyclic reference detected while serializing props for <${metadata.displayName} client:${metadata.hydrate}>! Cyclic references cannot be safely serialized for client-side usage. Please remove the cyclic reference.`); } parents.add(value); const serialized = value.map((v) => { return convertToSerializedForm(v, metadata, parents); }); parents.delete(value); return serialized; } function serializeObject(value, metadata = {}, parents = /* @__PURE__ */ new WeakSet()) { if (parents.has(value)) { throw new Error(`Cyclic reference detected while serializing props for <${metadata.displayName} client:${metadata.hydrate}>! Cyclic references cannot be safely serialized for client-side usage. Please remove the cyclic reference.`); } parents.add(value); const serialized = Object.fromEntries( Object.entries(value).map(([k, v]) => { return [k, convertToSerializedForm(v, metadata, parents)]; }) ); parents.delete(value); return serialized; } function convertToSerializedForm(value, metadata = {}, parents = /* @__PURE__ */ new WeakSet()) { const tag = Object.prototype.toString.call(value); switch (tag) { case "[object Date]": { return [PROP_TYPE.Date, value.toISOString()]; } case "[object RegExp]": { return [PROP_TYPE.RegExp, value.source]; } case "[object Map]": { return [PROP_TYPE.Map, serializeArray(Array.from(value), metadata, parents)]; } case "[object Set]": { return [PROP_TYPE.Set, serializeArray(Array.from(value), metadata, parents)]; } case "[object BigInt]": { return [PROP_TYPE.BigInt, value.toString()]; } case "[object URL]": { return [PROP_TYPE.URL, value.toString()]; } case "[object Array]": { return [PROP_TYPE.JSON, serializeArray(value, metadata, parents)]; } case "[object Uint8Array]": { return [PROP_TYPE.Uint8Array, Array.from(value)]; } case "[object Uint16Array]": { return [PROP_TYPE.Uint16Array, Array.from(value)]; } case "[object Uint32Array]": { return [PROP_TYPE.Uint32Array, Array.from(value)]; } default: { if (value !== null && typeof value === "object") { return [PROP_TYPE.Value, serializeObject(value, metadata, parents)]; } if (value === Number.POSITIVE_INFINITY) { return [PROP_TYPE.Infinity, 1]; } if (value === Number.NEGATIVE_INFINITY) { return [PROP_TYPE.Infinity, -1]; } if (value === void 0) { return [PROP_TYPE.Value]; } return [PROP_TYPE.Value, value]; } } } function serializeProps(props, metadata) { const serialized = JSON.stringify(serializeObject(props, metadata)); return serialized; } const transitionDirectivesToCopyOnIsland = Object.freeze([ "data-astro-transition-scope", "data-astro-transition-persist", "data-astro-transition-persist-props" ]); function extractDirectives(inputProps, clientDirectives) { let extracted = { isPage: false, hydration: null, props: {}, propsWithoutTransitionAttributes: {} }; for (const [key, value] of Object.entries(inputProps)) { if (key.startsWith("server:")) { if (key === "server:root") { extracted.isPage = true; } } if (key.startsWith("client:")) { if (!extracted.hydration) { extracted.hydration = { directive: "", value: "", componentUrl: "", componentExport: { value: "" } }; } switch (key) { case "client:component-path": { extracted.hydration.componentUrl = value; break; } case "client:component-export": { extracted.hydration.componentExport.value = value; break; } // This is a special prop added to prove that the client hydration method // was added statically. case "client:component-hydration": { break; } case "client:display-name": { break; } default: { extracted.hydration.directive = key.split(":")[1]; extracted.hydration.value = value; if (!clientDirectives.has(extracted.hydration.directive)) { const hydrationMethods = Array.from(clientDirectives.keys()).map((d) => `client:${d}`).join(", "); throw new Error( `Error: invalid hydration directive "${key}". Supported hydration methods: ${hydrationMethods}` ); } if (extracted.hydration.directive === "media" && typeof extracted.hydration.value !== "string") { throw new AstroError(MissingMediaQueryDirective); } break; } } } else { extracted.props[key] = value; if (!transitionDirectivesToCopyOnIsland.includes(key)) { extracted.propsWithoutTransitionAttributes[key] = value; } } } for (const sym of Object.getOwnPropertySymbols(inputProps)) { extracted.props[sym] = inputProps[sym]; extracted.propsWithoutTransitionAttributes[sym] = inputProps[sym]; } return extracted; } async function generateHydrateScript(scriptOptions, metadata) { const { renderer, result, astroId, props, attrs } = scriptOptions; const { hydrate, componentUrl, componentExport } = metadata; if (!componentExport.value) { throw new AstroError({ ...NoMatchingImport, message: NoMatchingImport.message(metadata.displayName) }); } const island = { children: "", props: { // This is for HMR, probably can avoid it in prod uid: astroId } }; if (attrs) { for (const [key, value] of Object.entries(attrs)) { island.props[key] = escapeHTML(value); } } island.props["component-url"] = await result.resolve(decodeURI(componentUrl)); if (renderer.clientEntrypoint) { island.props["component-export"] = componentExport.value; island.props["renderer-url"] = await result.resolve( decodeURI(renderer.clientEntrypoint.toString()) ); island.props["props"] = escapeHTML(serializeProps(props, metadata)); } island.props["ssr"] = ""; island.props["client"] = hydrate; let beforeHydrationUrl = await result.resolve("astro:scripts/before-hydration.js"); if (beforeHydrationUrl.length) { island.props["before-hydration-url"] = beforeHydrationUrl; } island.props["opts"] = escapeHTML( JSON.stringify({ name: metadata.displayName, value: metadata.hydrateArgs || "" }) ); transitionDirectivesToCopyOnIsland.forEach((name) => { if (typeof props[name] !== "undefined") { island.props[name] = props[name]; } }); return island; } /** * shortdash - https://github.com/bibig/node-shorthash * * @license * * (The MIT License) * * Copyright (c) 2013 Bibig * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. */ const dictionary = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXY"; const binary = dictionary.length; function bitwise(str) { let hash = 0; if (str.length === 0) return hash; for (let i = 0; i < str.length; i++) { const ch = str.charCodeAt(i); hash = (hash << 5) - hash + ch; hash = hash & hash; } return hash; } function shorthash(text) { let num; let result = ""; let integer = bitwise(text); const sign = integer < 0 ? "Z" : ""; integer = Math.abs(integer); while (integer >= binary) { num = integer % binary; integer = Math.floor(integer / binary); result = dictionary[num] + result; } if (integer > 0) { result = dictionary[integer] + result; } return sign + result; } const headAndContentSym = /* @__PURE__ */ Symbol.for("astro.headAndContent"); function isHeadAndContent(obj) { return typeof obj === "object" && obj !== null && !!obj[headAndContentSym]; } function createHeadAndContent(head, content) { return { [headAndContentSym]: true, head, content }; } function createThinHead() { return { [headAndContentSym]: true }; } var astro_island_prebuilt_default = `(()=>{var A=Object.defineProperty;var C=(i,o,a)=>o in i?A(i,o,{enumerable:!0,configurable:!0,writable:!0,value:a}):i[o]=a;var l=(i,o,a)=>C(i,typeof o!="symbol"?o+"":o,a);var E=new Set(["__proto__","constructor","prototype"]);{let i={0:t=>y(t),1:t=>a(t),2:t=>new RegExp(t),3:t=>new Date(t),4:t=>new Map(a(t)),5:t=>new Set(a(t)),6:t=>BigInt(t),7:t=>new URL(t),8:t=>new Uint8Array(t),9:t=>new Uint16Array(t),10:t=>new Uint32Array(t),11:t=>Number.POSITIVE_INFINITY*t},o=t=>{let[h,e]=t;return h in i?i[h](e):void 0},a=t=>t.map(o),y=t=>typeof t!="object"||t===null?t:Object.fromEntries(Object.entries(t).map(([h,e])=>[h,o(e)]));class f extends HTMLElement{constructor(){super(...arguments);l(this,"Component");l(this,"hydrator");l(this,"hydrate",async()=>{var b;if(!this.hydrator||!this.isConnected)return;let e=(b=this.parentElement)==null?void 0:b.closest("astro-island[ssr]");if(e){e.addEventListener("astro:hydrate",this.hydrate,{once:!0});return}let c=this.querySelectorAll("astro-slot"),n={},p=this.querySelectorAll("template[data-astro-template]");for(let r of p){let s=r.closest(this.tagName);s!=null&&s.isSameNode(this)&&(n[r.getAttribute("data-astro-template")||"default"]=r.innerHTML,r.remove())}for(let r of c){let s=r.closest(this.tagName);s!=null&&s.isSameNode(this)&&(n[r.getAttribute("name")||"default"]=r.innerHTML)}let u;try{u=this.hasAttribute("props")?y(JSON.parse(this.getAttribute("props"))):{}}catch(r){let s=this.getAttribute("component-url")||"",v=this.getAttribute("component-export");throw v&&(s+=\` (export \${v})\`),console.error(\`[hydrate] Error parsing props for component \${s}\`,this.getAttribute("props"),r),r}let d;await this.hydrator(this)(this.Component,u,n,{client:this.getAttribute("client")}),this.removeAttribute("ssr"),this.dispatchEvent(new CustomEvent("astro:hydrate"))});l(this,"unmount",()=>{this.isConnected||this.dispatchEvent(new CustomEvent("astro:unmount"))})}disconnectedCallback(){document.removeEventListener("astro:after-swap",this.unmount),document.addEventListener("astro:after-swap",this.unmount,{once:!0})}connectedCallback(){if(!this.hasAttribute("await-children")||document.readyState==="interactive"||document.readyState==="complete")this.childrenConnectedCallback();else{let e=()=>{document.removeEventListener("DOMContentLoaded",e),c.disconnect(),this.childrenConnectedCallback()},c=new MutationObserver(()=>{var n;((n=this.lastChild)==null?void 0:n.nodeType)===Node.COMMENT_NODE&&this.lastChild.nodeValue==="astro:end"&&(this.lastChild.remove(),e())});c.observe(this,{childList:!0}),document.addEventListener("DOMContentLoaded",e)}}async childrenConnectedCallback(){let e=this.getAttribute("before-hydration-url");e&&await import(e),this.start()}async start(){let e=JSON.parse(this.getAttribute("opts")),c=this.getAttribute("client");if(Astro[c]===void 0){window.addEventListener(\`astro:\${c}\`,()=>this.start(),{once:!0});return}try{await Astro[c](async()=>{let n=this.getAttribute("renderer-url"),[p,{default:u}]=await Promise.all([import(this.getAttribute("component-url")),n?import(n):()=>()=>{}]),d=this.getAttribute("component-export")||"default";if(d.includes(".")){this.Component=p;for(let m of d.split(".")){if(E.has(m)||!this.Component||typeof this.Component!="object"&&typeof this.Component!="function"||!Object.hasOwn(this.Component,m))throw new Error(\`Invalid component export path: \${d}\`);this.Component=this.Component[m]}}else{if(E.has(d))throw new Error(\`Invalid component export path: \${d}\`);this.Component=p[d]}return this.hydrator=u,this.hydrate},e,this)}catch(n){console.error("[astro-island] Error hydrating %s",this.getAttribute("component-url"),n)}}attributeChangedCallback(){this.hydrate()}}l(f,"observedAttributes",["props"]),customElements.get("astro-island")||customElements.define("astro-island",f)}})();`; var astro_island_prebuilt_dev_default = `(()=>{var A=Object.defineProperty;var C=(a,r,c)=>r in a?A(a,r,{enumerable:!0,configurable:!0,writable:!0,value:c}):a[r]=c;var l=(a,r,c)=>C(a,typeof r!="symbol"?r+"":r,c);var E=new Set(["__proto__","constructor","prototype"]);{let a={0:t=>y(t),1:t=>c(t),2:t=>new RegExp(t),3:t=>new Date(t),4:t=>new Map(c(t)),5:t=>new Set(c(t)),6:t=>BigInt(t),7:t=>new URL(t),8:t=>new Uint8Array(t),9:t=>new Uint16Array(t),10:t=>new Uint32Array(t),11:t=>Number.POSITIVE_INFINITY*t},r=t=>{let[p,e]=t;return p in a?a[p](e):void 0},c=t=>t.map(r),y=t=>typeof t!="object"||t===null?t:Object.fromEntries(Object.entries(t).map(([p,e])=>[p,r(e)]));class f extends HTMLElement{constructor(){super(...arguments);l(this,"Component");l(this,"hydrator");l(this,"hydrate",async()=>{var b;if(!this.hydrator||!this.isConnected)return;let e=(b=this.parentElement)==null?void 0:b.closest("astro-island[ssr]");if(e){e.addEventListener("astro:hydrate",this.hydrate,{once:!0});return}let d=this.querySelectorAll("astro-slot"),n={},u=this.querySelectorAll("template[data-astro-template]");for(let o of u){let i=o.closest(this.tagName);i!=null&&i.isSameNode(this)&&(n[o.getAttribute("data-astro-template")||"default"]=o.innerHTML,o.remove())}for(let o of d){let i=o.closest(this.tagName);i!=null&&i.isSameNode(this)&&(n[o.getAttribute("name")||"default"]=o.innerHTML)}let m;try{m=this.hasAttribute("props")?y(JSON.parse(this.getAttribute("props"))):{}}catch(o){let i=this.getAttribute("component-url")||"",v=this.getAttribute("component-export");throw v&&(i+=\` (export \${v})\`),console.error(\`[hydrate] Error parsing props for component \${i}\`,this.getAttribute("props"),o),o}let s,h=this.hydrator(this);s=performance.now(),await h(this.Component,m,n,{client:this.getAttribute("client")}),s&&this.setAttribute("client-render-time",(performance.now()-s).toString()),this.removeAttribute("ssr"),this.dispatchEvent(new CustomEvent("astro:hydrate"))});l(this,"unmount",()=>{this.isConnected||this.dispatchEvent(new CustomEvent("astro:unmount"))})}disconnectedCallback(){document.removeEventListener("astro:after-swap",this.unmount),document.addEventListener("astro:after-swap",this.unmount,{once:!0})}connectedCallback(){if(!this.hasAttribute("await-children")||document.readyState==="interactive"||document.readyState==="complete")this.childrenConnectedCallback();else{let e=()=>{document.removeEventListener("DOMContentLoaded",e),d.disconnect(),this.childrenConnectedCallback()},d=new MutationObserver(()=>{var n;((n=this.lastChild)==null?void 0:n.nodeType)===Node.COMMENT_NODE&&this.lastChild.nodeValue==="astro:end"&&(this.lastChild.remove(),e())});d.observe(this,{childList:!0}),document.addEventListener("DOMContentLoaded",e)}}async childrenConnectedCallback(){let e=this.getAttribute("before-hydration-url");e&&await import(e),this.start()}async start(){let e=JSON.parse(this.getAttribute("opts")),d=this.getAttribute("client");if(Astro[d]===void 0){window.addEventListener(\`astro:\${d}\`,()=>this.start(),{once:!0});return}try{await Astro[d](async()=>{let n=this.getAttribute("renderer-url"),[u,{default:m}]=await Promise.all([import(this.getAttribute("component-url")),n?import(n):()=>()=>{}]),s=this.getAttribute("component-export")||"default";if(s.includes(".")){this.Component=u;for(let h of s.split(".")){if(E.has(h)||!this.Component||typeof this.Component!="object"&&typeof this.Component!="function"||!Object.hasOwn(this.Component,h))throw new Error(\`Invalid component export path: \${s}\`);this.Component=this.Component[h]}}else{if(E.has(s))throw new Error(\`Invalid component export path: \${s}\`);this.Component=u[s]}return this.hydrator=m,this.hydrate},e,this)}catch(n){console.error("[astro-island] Error hydrating %s",this.getAttribute("component-url"),n)}}attributeChangedCallback(){this.hydrate()}}l(f,"observedAttributes",["props"]),customElements.get("astro-island")||customElements.define("astro-island",f)}})();`; const ISLAND_STYLES = "astro-island,astro-slot,astro-static-slot{display:contents}"; function determineIfNeedsHydrationScript(result) { if (result._metadata.hasHydrationScript) { return false; } return result._metadata.hasHydrationScript = true; } function determinesIfNeedsDirectiveScript(result, directive) { if (result._metadata.hasDirectives.has(directive)) { return false; } result._metadata.hasDirectives.add(directive); return true; } function getDirectiveScriptText(result, directive) { const clientDirectives = result.clientDirectives; const clientDirective = clientDirectives.get(directive); if (!clientDirective) { throw new Error(`Unknown directive: ${directive}`); } return clientDirective; } function getPrescripts(result, type, directive) { switch (type) { case "both": return ``; case "directive": return ``; } } async function collectPropagatedHeadParts(input) { const collectedHeadParts = []; const iterator = input.propagators.values(); while (true) { const { value, done } = iterator.next(); if (done) { break; } const returnValue = await value.init(input.result); if (input.isHeadAndContent(returnValue) && returnValue.head) { collectedHeadParts.push(returnValue.head); } } return collectedHeadParts; } function shouldRenderHeadInstruction(state) { return !state.hasRenderedHead && !state.partial; } function shouldRenderMaybeHeadInstruction(state) { return !state.hasRenderedHead && !state.headInTree && !state.partial; } function shouldRenderInstruction$1(type, state) { return type === "head" ? shouldRenderHeadInstruction(state) : shouldRenderMaybeHeadInstruction(state); } function registerIfPropagating(result, factory, instance) { if (factory.propagation === "self" || factory.propagation === "in-tree") { result._metadata.propagators.add( instance ); return; } if (factory.moduleId) { const hint = result.componentMetadata.get(factory.moduleId)?.propagation; if (isPropagatingHint(hint ?? "none")) { result._metadata.propagators.add( instance ); } } } async function bufferPropagatedHead(result) { const collected = await collectPropagatedHeadParts({ propagators: result._metadata.propagators, result, isHeadAndContent }); result._metadata.extraHead.push(...collected); } function shouldRenderInstruction(type, state) { return shouldRenderInstruction$1(type, state); } function getInstructionRenderState(result) { return { hasRenderedHead: result._metadata.hasRenderedHead, headInTree: result._metadata.headInTree, partial: result.partial }; } function renderCspContent(result) { const finalScriptHashes = /* @__PURE__ */ new Set(); const finalStyleHashes = /* @__PURE__ */ new Set(); for (const scriptHash of result.scriptHashes) { finalScriptHashes.add(`'${scriptHash}'`); } for (const styleHash of result.styleHashes) { finalStyleHashes.add(`'${styleHash}'`); } for (const styleHash of result._metadata.extraStyleHashes) { finalStyleHashes.add(`'${styleHash}'`); } for (const scriptHash of result._metadata.extraScriptHashes) { finalScriptHashes.add(`'${scriptHash}'`); } let directives; if (result.directives.length > 0) { directives = result.directives.join(";") + ";"; } let scriptResources = "'self'"; if (result.scriptResources.length > 0) { scriptResources = result.scriptResources.map((r) => `${r}`).join(" "); } let styleResources = "'self'"; if (result.styleResources.length > 0) { styleResources = result.styleResources.map((r) => `${r}`).join(" "); } const strictDynamic = result.isStrictDynamic ? ` 'strict-dynamic'` : ""; const scriptSrc = `script-src ${scriptResources} ${Array.from(finalScriptHashes).join(" ")}${strictDynamic};`; const styleSrc = `style-src ${styleResources} ${Array.from(finalStyleHashes).join(" ")};`; return [directives, scriptSrc, styleSrc].filter(Boolean).join(" "); } const RenderInstructionSymbol = /* @__PURE__ */ Symbol.for("astro:render"); function createRenderInstruction(instruction) { return Object.defineProperty(instruction, RenderInstructionSymbol, { value: true }); } function isRenderInstruction(chunk) { return chunk && typeof chunk === "object" && chunk[RenderInstructionSymbol]; } const voidElementNames = /^(area|base|br|col|command|embed|hr|img|input|keygen|link|meta|param|source|track|wbr)$/i; const htmlBooleanAttributes = /^(?:allowfullscreen|async|autofocus|autoplay|checked|controls|default|defer|disabled|disablepictureinpicture|disableremoteplayback|formnovalidate|inert|loop|muted|nomodule|novalidate|open|playsinline|readonly|required|reversed|scoped|seamless|selected|itemscope)$/i; const AMPERSAND_REGEX = /&/g; const DOUBLE_QUOTE_REGEX = /"/g; const STATIC_DIRECTIVES = /* @__PURE__ */ new Set(["set:html", "set:text"]); const toIdent = (k) => k.trim().replace(/(?!^)\b\w|\s+|\W+/g, (match, index) => { if (/\W/.test(match)) return ""; return index === 0 ? match : match.toUpperCase(); }); const toAttributeString = (value, shouldEscape = true) => shouldEscape ? String(value).replace(AMPERSAND_REGEX, "&").replace(DOUBLE_QUOTE_REGEX, """) : value; const kebab = (k) => k.toLowerCase() === k ? k : k.replace(/[A-Z]/g, (match) => `-${match.toLowerCase()}`); const toStyleString = (obj) => Object.entries(obj).filter(([_, v]) => typeof v === "string" && v.trim() || typeof v === "number").map(([k, v]) => { if (k[0] !== "-" && k[1] !== "-") return `${kebab(k)}:${v}`; return `${k}:${v}`; }).join(";"); function defineScriptVars(vars) { let output = ""; for (const [key, value] of Object.entries(vars)) { output += `const ${toIdent(key)} = ${stringifyForScript(value)}; `; } return markHTMLString(output); } function formatList(values) { if (values.length === 1) { return values[0]; } return `${values.slice(0, -1).join(", ")} or ${values[values.length - 1]}`; } function isCustomElement(tagName) { return tagName.includes("-"); } function handleBooleanAttribute(key, value, shouldEscape, tagName) { if (tagName && isCustomElement(tagName)) { return markHTMLString(` ${key}="${toAttributeString(value, shouldEscape)}"`); } return markHTMLString(value ? ` ${key}` : ""); } function addAttribute(value, key, shouldEscape = true, tagName = "") { if (value == null) { return ""; } if (STATIC_DIRECTIVES.has(key)) { console.warn(`[astro] The "${key}" directive cannot be applied dynamically at runtime. It will not be rendered as an attribute. Make sure to use the static attribute syntax (\`${key}={value}\`) instead of the dynamic spread syntax (\`{...{ "${key}": value }}\`).`); return ""; } if (key === "class:list") { const listValue = toAttributeString(clsx(value), shouldEscape); if (listValue === "") { return ""; } return markHTMLString(` ${key.slice(0, -5)}="${listValue}"`); } if (key === "style" && !(value instanceof HTMLString)) { if (Array.isArray(value) && value.length === 2) { return markHTMLString( ` ${key}="${toAttributeString(`${toStyleString(value[0])};${value[1]}`, shouldEscape)}"` ); } if (typeof value === "object") { return markHTMLString(` ${key}="${toAttributeString(toStyleString(value), shouldEscape)}"`); } } if (key === "className") { return markHTMLString(` class="${toAttributeString(value, shouldEscape)}"`); } if (htmlBooleanAttributes.test(key)) { return handleBooleanAttribute(key, value, shouldEscape, tagName); } if (value === "") { return markHTMLString(` ${key}`); } if (key === "popover" && typeof value === "boolean") { return handleBooleanAttribute(key, value, shouldEscape, tagName); } if (key === "download" && typeof value === "boolean") { return handleBooleanAttribute(key, value, shouldEscape, tagName); } if (key === "hidden" && typeof value === "boolean") { return handleBooleanAttribute(key, value, shouldEscape, tagName); } return markHTMLString(` ${key}="${toAttributeString(value, shouldEscape)}"`); } function internalSpreadAttributes(values, shouldEscape = true, tagName) { let output = ""; for (const [key, value] of Object.entries(values)) { output += addAttribute(value, key, shouldEscape, tagName); } return markHTMLString(output); } function renderElement$1(name, { props: _props, children = "" }, shouldEscape = true) { const { lang: _, "data-astro-id": astroId, "define:vars": defineVars, ...props } = _props; if (defineVars) { if (name === "style") { delete props["is:global"]; delete props["is:scoped"]; } if (name === "script") { delete props.hoist; children = defineScriptVars(defineVars) + "\n" + children; } } if ((children == null || children === "") && voidElementNames.test(name)) { return `<${name}${internalSpreadAttributes(props, shouldEscape, name)}>`; } return `<${name}${internalSpreadAttributes(props, shouldEscape, name)}>${children}`; } const noop = () => { }; class BufferedRenderer { chunks = []; renderPromise; destination; /** * Determines whether buffer has been flushed * to the final destination. */ flushed = false; constructor(destination, renderFunction) { this.destination = destination; this.renderPromise = renderFunction(this); if (isPromise(this.renderPromise)) { Promise.resolve(this.renderPromise).catch(noop); } } write(chunk) { if (this.flushed) { this.destination.write(chunk); } else { this.chunks.push(chunk); } } flush() { if (this.flushed) { throw new Error("The render buffer has already been flushed."); } this.flushed = true; for (const chunk of this.chunks) { this.destination.write(chunk); } return this.renderPromise; } } function createBufferedRenderer(destination, renderFunction) { return new BufferedRenderer(destination, renderFunction); } const isNode = typeof process !== "undefined" && Object.prototype.toString.call(process) === "[object process]"; const isDeno = typeof Deno !== "undefined"; function promiseWithResolvers() { let resolve, reject; const promise = new Promise((_resolve, _reject) => { resolve = _resolve; reject = _reject; }); return { promise, resolve, reject }; } function stablePropsKey(props) { const keys = Object.keys(props).sort(); let result = "{"; for (let i = 0; i < keys.length; i++) { if (i > 0) result += ","; result += JSON.stringify(keys[i]) + ":" + JSON.stringify(props[keys[i]]); } result += "}"; return result; } function deduplicateElements(elements) { if (elements.length <= 1) return elements; const seen = /* @__PURE__ */ new Set(); return elements.filter((item) => { const key = stablePropsKey(item.props) + item.children; if (seen.has(key)) return false; seen.add(key); return true; }); } function renderAllHeadContent(result) { result._metadata.hasRenderedHead = true; let content = ""; if (result.shouldInjectCspMetaTags && result.cspDestination === "meta") { content += renderElement$1( "meta", { props: { "http-equiv": "content-security-policy", content: renderCspContent(result) }, children: "" }, false ); } const styles = deduplicateElements(Array.from(result.styles)).map( (style) => style.props.rel === "stylesheet" ? renderElement$1("link", style) : renderElement$1("style", style) ); result.styles.clear(); const scripts = deduplicateElements(Array.from(result.scripts)).map((script) => { if (result.userAssetsBase) { script.props.src = (result.base === "/" ? "" : result.base) + result.userAssetsBase + script.props.src; } return renderElement$1("script", script, false); }); const links = deduplicateElements(Array.from(result.links)).map( (link) => renderElement$1("link", link, false) ); content += styles.join("\n") + links.join("\n") + scripts.join("\n"); if (result._metadata.extraHead.length > 0) { for (const part of result._metadata.extraHead) { content += part; } } return markHTMLString(content); } function renderHead() { return createRenderInstruction({ type: "head" }); } function maybeRenderHead() { return createRenderInstruction({ type: "maybe-head" }); } const ALGORITHMS = { "SHA-256": "sha256-", "SHA-384": "sha384-", "SHA-512": "sha512-" }; const ALGORITHM_VALUES = Object.values(ALGORITHMS); z.enum(Object.keys(ALGORITHMS)).optional().default("SHA-256"); z.custom((value) => { if (typeof value !== "string") { return false; } return ALGORITHM_VALUES.some((allowedValue) => { return value.startsWith(allowedValue); }); }); const ALLOWED_DIRECTIVES = [ "base-uri", "child-src", "connect-src", "default-src", "fenced-frame-src", "font-src", "form-action", "frame-ancestors", "frame-src", "img-src", "manifest-src", "media-src", "object-src", "referrer", "report-to", "report-uri", "require-trusted-types-for", "sandbox", "trusted-types", "upgrade-insecure-requests", "worker-src" ]; z.custom((value) => { if (typeof value !== "string") { return false; } return ALLOWED_DIRECTIVES.some((allowedValue) => { return value.startsWith(allowedValue); }); }); const ALGORITHM = "AES-GCM"; async function decodeKey(encoded) { const bytes = decodeBase64(encoded); return crypto.subtle.importKey("raw", bytes.buffer, ALGORITHM, true, [ "encrypt", "decrypt" ]); } const encoder$1 = new TextEncoder(); const decoder$1 = new TextDecoder(); const IV_LENGTH = 24; async function encryptString(key, raw, additionalData) { const iv = crypto.getRandomValues(new Uint8Array(IV_LENGTH / 2)); const data = encoder$1.encode(raw); const params = { name: ALGORITHM, iv }; if (additionalData) { params.additionalData = encoder$1.encode(additionalData); } const buffer = await crypto.subtle.encrypt(params, key, data); return encodeHexUpperCase(iv) + encodeBase64(new Uint8Array(buffer)); } async function decryptString(key, encoded, additionalData) { const iv = decodeHex(encoded.slice(0, IV_LENGTH)); const dataArray = decodeBase64(encoded.slice(IV_LENGTH)); const params = { name: ALGORITHM, iv }; if (additionalData) { params.additionalData = encoder$1.encode(additionalData); } const decryptedBuffer = await crypto.subtle.decrypt(params, key, dataArray); const decryptedString = decoder$1.decode(decryptedBuffer); return decryptedString; } async function generateCspDigest(data, algorithm) { const hashBuffer = await crypto.subtle.digest(algorithm, encoder$1.encode(data)); const hash = encodeBase64(new Uint8Array(hashBuffer)); return `${ALGORITHMS[algorithm]}${hash}`; } const renderTemplateResultSym = /* @__PURE__ */ Symbol.for("astro.renderTemplateResult"); class RenderTemplateResult { [renderTemplateResultSym] = true; htmlParts; expressions; error; constructor(htmlParts, expressions) { this.htmlParts = htmlParts; this.error = void 0; this.expressions = expressions.map((expression) => { if (isPromise(expression)) { return Promise.resolve(expression).catch((err) => { if (!this.error) { this.error = err; throw err; } }); } return expression; }); } render(destination) { const { htmlParts, expressions } = this; for (let i = 0; i < htmlParts.length; i++) { const html = htmlParts[i]; if (html) { destination.write(markHTMLString(html)); } if (i >= expressions.length) break; const exp = expressions[i]; if (!(exp || exp === 0)) continue; const result = renderChild(destination, exp); if (isPromise(result)) { const startIdx = i + 1; const remaining = expressions.length - startIdx; const flushers = new Array(remaining); for (let j = 0; j < remaining; j++) { const rExp = expressions[startIdx + j]; flushers[j] = createBufferedRenderer(destination, (bufferDestination) => { if (rExp || rExp === 0) { return renderChild(bufferDestination, rExp); } }); } return result.then(() => { let k = 0; const iterate = () => { while (k < flushers.length) { const rHtml = htmlParts[startIdx + k]; if (rHtml) { destination.write(markHTMLString(rHtml)); } const flushResult = flushers[k++].flush(); if (isPromise(flushResult)) { return flushResult.then(iterate); } } const lastHtml = htmlParts[htmlParts.length - 1]; if (lastHtml) { destination.write(markHTMLString(lastHtml)); } }; return iterate(); }); } } } } function isRenderTemplateResult(obj) { return typeof obj === "object" && obj !== null && !!obj[renderTemplateResultSym]; } function renderTemplate(htmlParts, ...expressions) { return new RenderTemplateResult(htmlParts, expressions); } const slotString = /* @__PURE__ */ Symbol.for("astro:slot-string"); class SlotString extends HTMLString { instructions; [slotString]; constructor(content, instructions) { super(content); this.instructions = instructions; this[slotString] = true; } } function isSlotString(str) { return !!str[slotString]; } function mergeSlotInstructions(target, source) { if (source.instructions?.length) { target ??= []; target.push(...source.instructions); } return target; } function renderSlot(result, slotted, fallback) { if (!slotted && fallback) { return renderSlot(result, fallback); } return { async render(destination) { await renderChild(destination, typeof slotted === "function" ? slotted(result) : slotted); } }; } async function renderSlotToString(result, slotted, fallback) { let content = ""; let instructions = null; const temporaryDestination = { write(chunk) { if (chunk instanceof SlotString) { content += chunk; instructions = mergeSlotInstructions(instructions, chunk); } else if (chunk instanceof Response) return; else if (typeof chunk === "object" && "type" in chunk && typeof chunk.type === "string") { if (instructions === null) { instructions = []; } instructions.push(chunk); } else { content += chunkToString(result, chunk); } } }; const renderInstance = renderSlot(result, slotted, fallback); await renderInstance.render(temporaryDestination); return markHTMLString(new SlotString(content, instructions)); } async function renderSlots(result, slots = {}) { let slotInstructions = null; let children = {}; if (slots) { await Promise.all( Object.entries(slots).map( ([key, value]) => renderSlotToString(result, value).then((output) => { if (output.instructions) { if (slotInstructions === null) { slotInstructions = []; } slotInstructions.push(...output.instructions); } children[key] = output; }) ) ); } return { slotInstructions, children }; } function createSlotValueFromString(content) { return function() { return renderTemplate`${unescapeHTML(content)}`; }; } const internalProps = /* @__PURE__ */ new Set([ "server:component-path", "server:component-export", "server:component-directive", "server:defer" ]); function containsServerDirective(props) { return "server:component-directive" in props; } function createSearchParams(encryptedComponentExport, encryptedProps, slots) { const params = new URLSearchParams(); params.set("e", encryptedComponentExport); params.set("p", encryptedProps); params.set("s", slots); return params; } function isWithinURLLimit(pathname, params) { const url = pathname + "?" + params.toString(); const chars = url.length; return chars < 2048; } class ServerIslandComponent { result; props; slots; displayName; hostId; islandContent; componentPath; componentExport; componentId; constructor(result, props, slots, displayName) { this.result = result; this.props = props; this.slots = slots; this.displayName = displayName; } async init() { const content = await this.getIslandContent(); if (this.result.cspDestination) { this.result._metadata.extraScriptHashes.push( await generateCspDigest(SERVER_ISLAND_REPLACER, this.result.cspAlgorithm) ); const contentDigest = await generateCspDigest(content, this.result.cspAlgorithm); this.result._metadata.extraScriptHashes.push(contentDigest); } return createThinHead(); } async render(destination) { const hostId = await this.getHostId(); const islandContent = await this.getIslandContent(); destination.write(createRenderInstruction({ type: "server-island-runtime" })); destination.write(""); for (const name in this.slots) { if (name === "fallback") { await renderChild(destination, this.slots.fallback(this.result)); } } destination.write( `` ); } getComponentPath() { if (this.componentPath) { return this.componentPath; } const componentPath = this.props["server:component-path"]; if (!componentPath) { throw new Error(`Could not find server component path`); } this.componentPath = componentPath; return componentPath; } getComponentExport() { if (this.componentExport) { return this.componentExport; } const componentExport = this.props["server:component-export"]; if (!componentExport) { throw new Error(`Could not find server component export`); } this.componentExport = componentExport; return componentExport; } async getHostId() { if (!this.hostId) { this.hostId = await crypto.randomUUID(); } return this.hostId; } async getIslandContent() { if (this.islandContent) { return this.islandContent; } const componentPath = this.getComponentPath(); const componentExport = this.getComponentExport(); let componentId = this.result.serverIslandNameMap.get(componentPath); if (!componentId) { throw new Error(`Could not find server component name ${componentPath}`); } for (const key2 of Object.keys(this.props)) { if (internalProps.has(key2)) { delete this.props[key2]; } } const renderedSlots = {}; for (const name in this.slots) { if (name !== "fallback") { const content = await renderSlotToString(this.result, this.slots[name]); let slotHtml = content.toString(); const slotContent = content; if (Array.isArray(slotContent.instructions)) { for (const instruction of slotContent.instructions) { if (instruction.type === "script") { slotHtml += instruction.content; } } } renderedSlots[name] = slotHtml; } } const key = await this.result.key; const componentExportEncrypted = await encryptString( key, componentExport, `export:${componentId}` ); const propsEncrypted = Object.keys(this.props).length === 0 ? "" : await encryptString(key, JSON.stringify(this.props), `props:${componentId}`); const slotsEncrypted = Object.keys(renderedSlots).length === 0 ? "" : await encryptString(key, JSON.stringify(renderedSlots), `slots:${componentId}`); const hostId = await this.getHostId(); const slash = this.result.base.endsWith("/") ? "" : "/"; let serverIslandUrl = `${this.result.base}${slash}_server-islands/${componentId}${this.result.trailingSlash === "always" ? "/" : ""}`; const potentialSearchParams = createSearchParams( componentExportEncrypted, propsEncrypted, slotsEncrypted ); const useGETRequest = isWithinURLLimit(serverIslandUrl, potentialSearchParams); if (useGETRequest) { serverIslandUrl += "?" + potentialSearchParams.toString(); this.result._metadata.extraHead.push( markHTMLString( `` ) ); } const adapterHeaders = this.result.internalFetchHeaders || {}; const headersJson = stringifyForScript(adapterHeaders); const method = useGETRequest ? ( // GET request `const headers = new Headers(${headersJson}); let response = await fetch('${serverIslandUrl}', { headers });` ) : ( // POST request `let data = { encryptedComponentExport: ${stringifyForScript(componentExportEncrypted)}, encryptedProps: ${stringifyForScript(propsEncrypted)}, encryptedSlots: ${stringifyForScript(slotsEncrypted)}, }; const headers = new Headers({ 'Content-Type': 'application/json', ...${headersJson} }); let response = await fetch('${serverIslandUrl}', { method: 'POST', body: JSON.stringify(data), headers, });` ); this.islandContent = `${method}replaceServerIsland('${hostId}', response);`; return this.islandContent; } } const renderServerIslandRuntime = () => { return ``; }; const SERVER_ISLAND_REPLACER = markHTMLString( `async function replaceServerIsland(id, r) { let s = document.querySelector(\`script[data-island-id="\${id}"]\`); // If there's no matching script, or the request fails then return if (!s || r.status !== 200 || r.headers.get('content-type')?.split(';')[0].trim() !== 'text/html') return; // Load the HTML before modifying the DOM in case of errors let html = await r.text(); // Remove any placeholder content before the island script while (s.previousSibling && s.previousSibling.nodeType !== 8 && s.previousSibling.data !== '[if astro]>server-island-start line.trim()).filter((line) => line && !line.startsWith("//")).join(" ") ); const Fragment = /* @__PURE__ */ Symbol.for("astro:fragment"); const Renderer = /* @__PURE__ */ Symbol.for("astro:renderer"); const encoder = new TextEncoder(); const decoder = new TextDecoder(); function stringifyChunk(result, chunk) { if (isRenderInstruction(chunk)) { const instruction = chunk; switch (instruction.type) { case "directive": { const { hydration } = instruction; let needsHydrationScript = hydration && determineIfNeedsHydrationScript(result); let needsDirectiveScript = hydration && determinesIfNeedsDirectiveScript(result, hydration.directive); if (needsHydrationScript) { let prescripts = getPrescripts(result, "both", hydration.directive); return markHTMLString(prescripts); } else if (needsDirectiveScript) { let prescripts = getPrescripts(result, "directive", hydration.directive); return markHTMLString(prescripts); } else { return ""; } } case "head": { if (!shouldRenderInstruction("head", getInstructionRenderState(result))) { return ""; } return renderAllHeadContent(result); } case "maybe-head": { if (!shouldRenderInstruction("maybe-head", getInstructionRenderState(result))) { return ""; } return renderAllHeadContent(result); } case "renderer-hydration-script": { const { rendererSpecificHydrationScripts } = result._metadata; const { rendererName } = instruction; if (!rendererSpecificHydrationScripts.has(rendererName)) { rendererSpecificHydrationScripts.add(rendererName); return instruction.render(); } return ""; } case "server-island-runtime": { if (result._metadata.hasRenderedServerIslandRuntime) { return ""; } result._metadata.hasRenderedServerIslandRuntime = true; return renderServerIslandRuntime(); } case "script": { const { id, content } = instruction; if (result._metadata.templateDepth > 0) { return content; } if (result._metadata.renderedScripts.has(id)) { return ""; } result._metadata.renderedScripts.add(id); return content; } case "template-enter": { result._metadata.templateDepth++; return ""; } case "template-exit": { if (result._metadata.templateDepth <= 0) { throw new Error( "Unexpected template-exit instruction without a matching template-enter. This may indicate that the compiler emitted unbalanced template boundaries, or that a component manually injected a template-exit render instruction." ); } result._metadata.templateDepth--; return ""; } default: { throw new Error(`Unknown chunk type: ${chunk.type}`); } } } else if (chunk instanceof Response) { return ""; } else if (isSlotString(chunk)) { let out = ""; const c = chunk; if (c.instructions) { for (const instr of c.instructions) { out += stringifyChunk(result, instr); } } out += chunk.toString(); return out; } return chunk.toString(); } function chunkToString(result, chunk) { if (ArrayBuffer.isView(chunk)) { return decoder.decode(chunk); } else { return stringifyChunk(result, chunk); } } function chunkToByteArray(result, chunk) { if (ArrayBuffer.isView(chunk)) { return chunk; } else { const stringified = stringifyChunk(result, chunk); return encoder.encode(stringified.toString()); } } function chunkToByteArrayOrString(result, chunk) { if (ArrayBuffer.isView(chunk)) { return chunk; } else { return stringifyChunk(result, chunk).toString(); } } function isRenderInstance(obj) { return !!obj && typeof obj === "object" && "render" in obj && typeof obj.render === "function"; } function renderChild(destination, child) { if (typeof child === "string") { destination.write(markHTMLString(escapeHTML(child))); return; } if (isPromise(child)) { return child.then((x) => renderChild(destination, x)); } if (child instanceof SlotString) { destination.write(child); return; } if (isHTMLString(child)) { destination.write(child); return; } if (!child && child !== 0) { return; } if (Array.isArray(child)) { return renderArray(destination, child); } if (typeof child === "function") { return renderChild(destination, child()); } if (isRenderInstance(child)) { return child.render(destination); } if (isRenderTemplateResult(child)) { return child.render(destination); } if (isAstroComponentInstance(child)) { return child.render(destination); } if (ArrayBuffer.isView(child)) { destination.write(child); return; } if (typeof child === "object" && (Symbol.asyncIterator in child || Symbol.iterator in child)) { if (Symbol.asyncIterator in child) { return renderAsyncIterable(destination, child); } return renderIterable(destination, child); } destination.write(child); } function renderArray(destination, children) { for (let i = 0; i < children.length; i++) { const result = renderChild(destination, children[i]); if (isPromise(result)) { if (i + 1 >= children.length) { return result; } const remaining = children.length - i - 1; const flushers = new Array(remaining); for (let j = 0; j < remaining; j++) { flushers[j] = createBufferedRenderer(destination, (bufferDestination) => { return renderChild(bufferDestination, children[i + 1 + j]); }); } return result.then(() => { let k = 0; const iterate = () => { while (k < flushers.length) { const flushResult = flushers[k++].flush(); if (isPromise(flushResult)) { return flushResult.then(iterate); } } }; return iterate(); }); } } } function renderIterable(destination, children) { const iterator = children[Symbol.iterator](); const iterate = () => { for (; ; ) { const { value, done } = iterator.next(); if (done) { break; } const result = renderChild(destination, value); if (isPromise(result)) { return result.then(iterate); } } }; return iterate(); } async function renderAsyncIterable(destination, children) { for await (const value of children) { await renderChild(destination, value); } } const astroComponentInstanceSym = /* @__PURE__ */ Symbol.for("astro.componentInstance"); class AstroComponentInstance { [astroComponentInstanceSym] = true; result; props; slotValues; factory; returnValue; constructor(result, props, slots, factory) { this.result = result; this.props = props; this.factory = factory; this.slotValues = {}; for (const name in slots) { let didRender = false; let value = slots[name](result); this.slotValues[name] = () => { if (!didRender) { didRender = true; return value; } return slots[name](result); }; } } init(result) { if (this.returnValue !== void 0) { return this.returnValue; } this.returnValue = this.factory(result, this.props, this.slotValues); if (isPromise(this.returnValue)) { this.returnValue.then((resolved) => { this.returnValue = resolved; }).catch(() => { }); } return this.returnValue; } render(destination) { const returnValue = this.init(this.result); if (isPromise(returnValue)) { return returnValue.then((x) => this.renderImpl(destination, x)); } return this.renderImpl(destination, returnValue); } renderImpl(destination, returnValue) { if (isHeadAndContent(returnValue)) { return returnValue.content.render(destination); } else { return renderChild(destination, returnValue); } } } function validateComponentProps(props, clientDirectives, displayName) { if (props != null) { const directives = [...clientDirectives.keys()].map((directive) => `client:${directive}`); for (const prop of Object.keys(props)) { if (directives.includes(prop)) { console.warn( `You are attempting to render <${displayName} ${prop} />, but ${displayName} is an Astro component. Astro components do not render in the client and should not have a hydration directive. Please use a framework component for client rendering.` ); } } } } function createAstroComponentInstance(result, displayName, factory, props, slots = {}) { validateComponentProps(props, result.clientDirectives, displayName); const instance = new AstroComponentInstance(result, props, slots, factory); registerIfPropagating(result, factory, instance); return instance; } function isAstroComponentInstance(obj) { return typeof obj === "object" && obj !== null && !!obj[astroComponentInstanceSym]; } const DOCTYPE_EXP = /" : "\n"; str += doctype; } } if (chunk instanceof Response) return; str += chunkToString(result, chunk); } }; await templateResult.render(destination); return str; } async function renderToReadableStream(result, componentFactory, props, children, isPage = false, route) { const templateResult = await callComponentAsTemplateResultOrResponse( result, componentFactory, props, children, route ); if (templateResult instanceof Response) return templateResult; let renderedFirstPageChunk = false; if (isPage) { await bufferHeadContent(result); } return new ReadableStream({ start(controller) { const destination = { write(chunk) { if (isPage && !renderedFirstPageChunk) { renderedFirstPageChunk = true; if (!result.partial && !DOCTYPE_EXP.test(String(chunk))) { const doctype = result.compressHTML ? "" : "\n"; controller.enqueue(encoder.encode(doctype)); } } if (chunk instanceof Response) { throw new AstroError({ ...ResponseSentError }); } const bytes = chunkToByteArray(result, chunk); controller.enqueue(bytes); } }; (async () => { try { await templateResult.render(destination); controller.close(); } catch (e) { if (AstroError.is(e) && !e.loc) { e.setLocation({ file: route?.component }); } setTimeout(() => controller.error(e), 0); } })(); }, cancel() { result.cancelled = true; } }); } async function callComponentAsTemplateResultOrResponse(result, componentFactory, props, children, route) { const factoryResult = await componentFactory(result, props, children); if (factoryResult instanceof Response) { return factoryResult; } else if (isHeadAndContent(factoryResult)) { if (!isRenderTemplateResult(factoryResult.content)) { throw new AstroError({ ...OnlyResponseCanBeReturned, message: OnlyResponseCanBeReturned.message( route?.route, typeof factoryResult ), location: { file: route?.component } }); } return factoryResult.content; } else if (!isRenderTemplateResult(factoryResult)) { throw new AstroError({ ...OnlyResponseCanBeReturned, message: OnlyResponseCanBeReturned.message(route?.route, typeof factoryResult), location: { file: route?.component } }); } return factoryResult; } async function bufferHeadContent(result) { await bufferPropagatedHead(result); } async function renderToAsyncIterable(result, componentFactory, props, children, isPage = false, route) { const templateResult = await callComponentAsTemplateResultOrResponse( result, componentFactory, props, children, route ); if (templateResult instanceof Response) return templateResult; let renderedFirstPageChunk = false; if (isPage) { await bufferHeadContent(result); } let error = null; let next = null; const buffer = []; let renderingComplete = false; const iterator = { async next() { if (result.cancelled) return { done: true, value: void 0 }; if (next !== null) { await next.promise; } else if (!renderingComplete && !buffer.length) { next = promiseWithResolvers(); await next.promise; } if (!renderingComplete) { next = promiseWithResolvers(); } if (error) { throw error; } let length = 0; let stringToEncode = ""; for (let i = 0, len = buffer.length; i < len; i++) { const bufferEntry = buffer[i]; if (typeof bufferEntry === "string") { const nextIsString = i + 1 < len && typeof buffer[i + 1] === "string"; stringToEncode += bufferEntry; if (!nextIsString) { const encoded = encoder.encode(stringToEncode); length += encoded.length; stringToEncode = ""; buffer[i] = encoded; } else { buffer[i] = ""; } } else { length += bufferEntry.length; } } let mergedArray = new Uint8Array(length); let offset = 0; for (let i = 0, len = buffer.length; i < len; i++) { const item = buffer[i]; if (item === "") { continue; } mergedArray.set(item, offset); offset += item.length; } buffer.length = 0; const returnValue = { // The iterator is done when rendering has finished // and there are no more chunks to return. done: length === 0 && renderingComplete, value: mergedArray }; return returnValue; }, async return() { result.cancelled = true; return { done: true, value: void 0 }; } }; const destination = { write(chunk) { if (isPage && !renderedFirstPageChunk) { renderedFirstPageChunk = true; if (!result.partial && !DOCTYPE_EXP.test(String(chunk))) { const doctype = result.compressHTML ? "" : "\n"; buffer.push(encoder.encode(doctype)); } } if (chunk instanceof Response) { throw new AstroError(ResponseSentError); } const bytes = chunkToByteArrayOrString(result, chunk); if (bytes.length > 0) { buffer.push(bytes); next?.resolve(); } else if (buffer.length > 0) { next?.resolve(); } } }; const renderResult = toPromise(() => templateResult.render(destination)); renderResult.catch((err) => { error = err; }).finally(() => { renderingComplete = true; next?.resolve(); }); return { [Symbol.asyncIterator]() { return iterator; } }; } function toPromise(fn) { try { const result = fn(); return isPromise(result) ? result : Promise.resolve(result); } catch (err) { return Promise.reject(err); } } function componentIsHTMLElement(Component) { return typeof HTMLElement !== "undefined" && HTMLElement.isPrototypeOf(Component); } async function renderHTMLElement$1(result, constructor, props, slots) { const name = getHTMLElementName(constructor); let attrHTML = ""; for (const attr in props) { attrHTML += ` ${attr}="${toAttributeString(await props[attr])}"`; } return markHTMLString( `<${name}${attrHTML}>${await renderSlotToString(result, slots?.default)}` ); } function getHTMLElementName(constructor) { const definedName = customElements.getName(constructor); if (definedName) return definedName; const assignedName = constructor.name.replace(/^HTML|Element$/g, "").replace(/[A-Z]/g, "-$&").toLowerCase().replace(/^-/, "html-"); return assignedName; } const needsHeadRenderingSymbol = /* @__PURE__ */ Symbol.for("astro.needsHeadRendering"); const rendererAliases = /* @__PURE__ */ new Map([["solid", "solid-js"]]); const clientOnlyValues = /* @__PURE__ */ new Set(["solid-js", "react", "preact", "vue", "svelte"]); function guessRenderers(componentUrl) { const extname = componentUrl?.split(".").pop(); switch (extname) { case "svelte": return ["@astrojs/svelte"]; case "vue": return ["@astrojs/vue"]; case "jsx": case "tsx": return ["@astrojs/react", "@astrojs/preact", "@astrojs/solid-js", "@astrojs/vue (jsx)"]; case void 0: default: return [ "@astrojs/react", "@astrojs/preact", "@astrojs/solid-js", "@astrojs/vue", "@astrojs/svelte" ]; } } function isFragmentComponent(Component) { return Component === Fragment; } function isHTMLComponent(Component) { return Component && Component["astro:html"] === true; } const ASTRO_SLOT_EXP = /<\/?astro-slot\b[^>]*>/g; const ASTRO_STATIC_SLOT_EXP = /<\/?astro-static-slot\b[^>]*>/g; function removeStaticAstroSlot(html, supportsAstroStaticSlot = true) { const exp = supportsAstroStaticSlot ? ASTRO_STATIC_SLOT_EXP : ASTRO_SLOT_EXP; return html.replace(exp, ""); } async function renderFrameworkComponent(result, displayName, Component, _props, slots = {}) { if (!Component && "client:only" in _props === false) { throw new Error( `Unable to render ${displayName} because it is ${Component}! Did you forget to import the component or is it possible there is a typo?` ); } const { renderers, clientDirectives } = result; const metadata = { astroStaticSlot: true, displayName }; const { hydration, isPage, props, propsWithoutTransitionAttributes } = extractDirectives( _props, clientDirectives ); let html = ""; let attrs = void 0; if (hydration) { metadata.hydrate = hydration.directive; metadata.hydrateArgs = hydration.value; metadata.componentExport = hydration.componentExport; metadata.componentUrl = hydration.componentUrl; } const probableRendererNames = guessRenderers(metadata.componentUrl); const validRenderers = renderers.filter((r) => r.name !== "astro:jsx"); const { children, slotInstructions } = await renderSlots(result, slots); let renderer; if (metadata.hydrate !== "only") { let isTagged = false; try { isTagged = Component && Component[Renderer]; } catch { } if (isTagged) { const rendererName = Component[Renderer]; renderer = renderers.find(({ name }) => name === rendererName); } if (!renderer) { let error; for (const r of renderers) { try { if (await r.ssr.check.call({ result }, Component, props, children, metadata)) { renderer = r; break; } } catch (e) { error ??= e; } } if (!renderer && error) { throw error; } } if (!renderer && typeof HTMLElement === "function" && componentIsHTMLElement(Component)) { const output = await renderHTMLElement$1( result, Component, _props, slots ); return { render(destination) { destination.write(output); } }; } } else { if (metadata.hydrateArgs) { const rendererName = rendererAliases.has(metadata.hydrateArgs) ? rendererAliases.get(metadata.hydrateArgs) : metadata.hydrateArgs; if (clientOnlyValues.has(rendererName)) { renderer = renderers.find( ({ name }) => name === `@astrojs/${rendererName}` || name === rendererName ); } } if (!renderer && validRenderers.length === 1) { renderer = validRenderers[0]; } if (!renderer) { const extname = metadata.componentUrl?.split(".").pop(); renderer = renderers.find(({ name }) => name === `@astrojs/${extname}` || name === extname); } if (!renderer && metadata.hydrateArgs) { const rendererName = metadata.hydrateArgs; if (typeof rendererName === "string") { renderer = renderers.find(({ name }) => name === rendererName); } } } let componentServerRenderEndTime; if (!renderer) { if (metadata.hydrate === "only") { const rendererName = rendererAliases.has(metadata.hydrateArgs) ? rendererAliases.get(metadata.hydrateArgs) : metadata.hydrateArgs; if (clientOnlyValues.has(rendererName)) { const plural = validRenderers.length > 1; throw new AstroError({ ...NoMatchingRenderer, message: NoMatchingRenderer.message( metadata.displayName, metadata?.componentUrl?.split(".").pop(), plural, validRenderers.length ), hint: NoMatchingRenderer.hint( formatList(probableRendererNames.map((r) => "`" + r + "`")) ) }); } else { throw new AstroError({ ...NoClientOnlyHint, message: NoClientOnlyHint.message(metadata.displayName), hint: NoClientOnlyHint.hint( probableRendererNames.map((r) => r.replace("@astrojs/", "")).join("|") ) }); } } else if (typeof Component !== "string") { const matchingRenderers = validRenderers.filter( (r) => probableRendererNames.includes(r.name) ); const plural = validRenderers.length > 1; if (matchingRenderers.length === 0) { throw new AstroError({ ...NoMatchingRenderer, message: NoMatchingRenderer.message( metadata.displayName, metadata?.componentUrl?.split(".").pop(), plural, validRenderers.length ), hint: NoMatchingRenderer.hint( formatList(probableRendererNames.map((r) => "`" + r + "`")) ) }); } else if (matchingRenderers.length === 1) { renderer = matchingRenderers[0]; ({ html, attrs } = await renderer.ssr.renderToStaticMarkup.call( { result }, Component, propsWithoutTransitionAttributes, children, metadata )); } else { throw new Error(`Unable to render ${metadata.displayName}! This component likely uses ${formatList(probableRendererNames)}, but Astro encountered an error during server-side rendering. Please ensure that ${metadata.displayName}: 1. Does not unconditionally access browser-specific globals like \`window\` or \`document\`. If this is unavoidable, use the \`client:only\` hydration directive. 2. Does not conditionally return \`null\` or \`undefined\` when rendered on the server. 3. If using multiple JSX frameworks at the same time (e.g. React + Preact), pass the correct \`include\`/\`exclude\` options to integrations. If you're still stuck, please open an issue on GitHub or join us at https://astro.build/chat.`); } } } else { if (metadata.hydrate === "only") { html = await renderSlotToString(result, slots?.fallback); } else { const componentRenderStartTime = performance.now(); ({ html, attrs } = await renderer.ssr.renderToStaticMarkup.call( { result }, Component, propsWithoutTransitionAttributes, children, metadata )); if (process.env.NODE_ENV === "development") componentServerRenderEndTime = performance.now() - componentRenderStartTime; } } if (!html && typeof Component === "string") { const Tag = sanitizeElementName(Component); const childSlots = Object.values(children).join(""); const renderTemplateResult = renderTemplate`<${Tag}${internalSpreadAttributes( props, true, Tag )}${markHTMLString( childSlots === "" && voidElementNames.test(Tag) ? `/>` : `>${childSlots}` )}`; html = ""; const destination = { write(chunk) { if (chunk instanceof Response) return; html += chunkToString(result, chunk); } }; await renderTemplateResult.render(destination); } if (!hydration) { return { render(destination) { if (slotInstructions) { for (const instruction of slotInstructions) { destination.write(instruction); } } if (isPage || renderer?.name === "astro:jsx") { destination.write(html); } else if (html && html.length > 0) { destination.write( markHTMLString(removeStaticAstroSlot(html, renderer?.ssr?.supportsAstroStaticSlot)) ); } } }; } const astroId = shorthash( ` ${html} ${serializeProps( props, metadata )}` ); const island = await generateHydrateScript( { renderer, result, astroId, props, attrs }, metadata ); if (componentServerRenderEndTime && process.env.NODE_ENV === "development") island.props["server-render-time"] = componentServerRenderEndTime; let unrenderedSlots = []; if (html) { if (Object.keys(children).length > 0) { for (const key of Object.keys(children)) { let tagName = renderer?.ssr?.supportsAstroStaticSlot ? !!metadata.hydrate ? "astro-slot" : "astro-static-slot" : "astro-slot"; let expectedHTML = key === "default" ? `<${tagName}>` : `<${tagName} name="${key}">`; if (!html.includes(expectedHTML)) { unrenderedSlots.push(key); } } } } else { unrenderedSlots = Object.keys(children); } const template = unrenderedSlots.length > 0 ? unrenderedSlots.map( (key) => `` ).join("") : ""; island.children = `${html ?? ""}${template}`; if (island.children) { island.props["await-children"] = ""; island.children += ``; } return { render(destination) { if (slotInstructions) { for (const instruction of slotInstructions) { destination.write(instruction); } } destination.write(createRenderInstruction({ type: "directive", hydration })); if (hydration.directive !== "only" && renderer?.ssr.renderHydrationScript) { destination.write( createRenderInstruction({ type: "renderer-hydration-script", rendererName: renderer.name, render: renderer.ssr.renderHydrationScript }) ); } const renderedElement = renderElement$1("astro-island", island, false); destination.write(markHTMLString(renderedElement)); } }; } function sanitizeElementName(tag) { const unsafe = /[&<>'"\s]+/; if (!unsafe.test(tag)) return tag; return tag.trim().split(unsafe)[0].trim(); } function renderFragmentComponent(result, slots = {}) { const slot = slots?.default; return { render(destination) { if (slot == null) return; return renderSlot(result, slot).render(destination); } }; } async function renderHTMLComponent(result, Component, _props, slots = {}) { const { slotInstructions, children } = await renderSlots(result, slots); const html = Component({ slots: children }); const hydrationHtml = slotInstructions ? slotInstructions.map((instr) => chunkToString(result, instr)).join("") : ""; return { render(destination) { destination.write(markHTMLString(hydrationHtml + html)); } }; } function renderAstroComponent(result, displayName, Component, props, slots = {}) { if (containsServerDirective(props)) { const serverIslandComponent = new ServerIslandComponent(result, props, slots, displayName); result._metadata.propagators.add(serverIslandComponent); return serverIslandComponent; } const instance = createAstroComponentInstance(result, displayName, Component, props, slots); return { render(destination) { return instance.render(destination); } }; } function renderComponent(result, displayName, Component, props, slots = {}) { if (isPromise(Component)) { return Component.catch(handleCancellation).then((x) => { return renderComponent(result, displayName, x, props, slots); }); } if (isFragmentComponent(Component)) { return renderFragmentComponent(result, slots); } props = normalizeProps(props); if (isHTMLComponent(Component)) { return renderHTMLComponent(result, Component, props, slots).catch(handleCancellation); } if (isAstroComponentFactory(Component)) { return renderAstroComponent(result, displayName, Component, props, slots); } return renderFrameworkComponent(result, displayName, Component, props, slots).catch( handleCancellation ); function handleCancellation(e) { if (result.cancelled) return { render() { } }; throw e; } } function normalizeProps(props) { if (props["class:list"] !== void 0) { const value = props["class:list"]; delete props["class:list"]; props["class"] = clsx(props["class"], value); if (props["class"] === "") { delete props["class"]; } } return props; } async function renderComponentToString(result, displayName, Component, props, slots = {}, isPage = false, route) { let str = ""; let renderedFirstPageChunk = false; let head = ""; if (isPage && !result.partial && nonAstroPageNeedsHeadInjection(Component)) { head += chunkToString(result, maybeRenderHead()); } try { const destination = { write(chunk) { if (isPage && !result.partial && !renderedFirstPageChunk) { renderedFirstPageChunk = true; if (!/" : "\n"; str += doctype + head; } } if (chunk instanceof Response) return; str += chunkToString(result, chunk); } }; const renderInstance = await renderComponent(result, displayName, Component, props, slots); if (containsServerDirective(props)) { await bufferHeadContent(result); } await renderInstance.render(destination); } catch (e) { if (AstroError.is(e) && !e.loc) { e.setLocation({ file: route?.component }); } throw e; } return str; } function nonAstroPageNeedsHeadInjection(pageComponent) { return !!pageComponent?.[needsHeadRenderingSymbol]; } const ClientOnlyPlaceholder$1 = "astro-client-only"; const hasTriedRenderComponentSymbol = /* @__PURE__ */ Symbol("hasTriedRenderComponent"); async function renderJSX(result, vnode) { switch (true) { case vnode instanceof HTMLString: if (vnode.toString().trim() === "") { return ""; } return vnode; case typeof vnode === "string": return markHTMLString(escapeHTML(vnode)); case typeof vnode === "function": return vnode; case (!vnode && vnode !== 0): return ""; case Array.isArray(vnode): { const renderedItems = await Promise.all(vnode.map((v) => renderJSX(result, v))); let instructions = null; let content = ""; for (const item of renderedItems) { if (item instanceof SlotString) { content += item; instructions = mergeSlotInstructions(instructions, item); } else { content += item; } } if (instructions) { return markHTMLString(new SlotString(content, instructions)); } return markHTMLString(content); } } return renderJSXVNode(result, vnode); } async function renderJSXVNode(result, vnode) { if (isVNode(vnode)) { switch (true) { case !vnode.type: { throw new Error(`Unable to render ${result.pathname} because it contains an undefined Component! Did you forget to import the component or is it possible there is a typo?`); } case vnode.type === /* @__PURE__ */ Symbol.for("astro:fragment"): return renderJSX(result, vnode.props.children); case isAstroComponentFactory(vnode.type): { let props = {}; let slots = {}; for (const [key, value] of Object.entries(vnode.props ?? {})) { if (key === "children" || value && typeof value === "object" && value["$$slot"]) { slots[key === "children" ? "default" : key] = () => renderJSX(result, value); } else { props[key] = value; } } const str = await renderComponentToString( result, vnode.type.name, vnode.type, props, slots ); const html = markHTMLString(str); return html; } case (!vnode.type && vnode.type !== 0): return ""; case (typeof vnode.type === "string" && vnode.type !== ClientOnlyPlaceholder$1): return markHTMLString(await renderElement(result, vnode.type, vnode.props ?? {})); } if (vnode.type) { let extractSlots2 = function(child) { if (Array.isArray(child)) { return child.map((c) => extractSlots2(c)); } if (!isVNode(child)) { _slots.default.push(child); return; } if ("slot" in child.props) { _slots[child.props.slot] = [..._slots[child.props.slot] ?? [], child]; delete child.props.slot; return; } _slots.default.push(child); }; if (typeof vnode.type === "function" && vnode.props["server:root"]) { const output2 = await vnode.type(vnode.props ?? {}); return await renderJSX(result, output2); } if (typeof vnode.type === "function") { if (vnode.props[hasTriedRenderComponentSymbol]) { delete vnode.props[hasTriedRenderComponentSymbol]; const output2 = await vnode.type(vnode.props ?? {}); if (output2?.[AstroJSX] || !output2) { return await renderJSXVNode(result, output2); } else { return; } } else { vnode.props[hasTriedRenderComponentSymbol] = true; } } const { children = null, ...props } = vnode.props ?? {}; const _slots = { default: [] }; extractSlots2(children); for (const [key, value] of Object.entries(props)) { if (value?.["$$slot"]) { _slots[key] = value; delete props[key]; } } const slotPromises = []; const slots = {}; for (const [key, value] of Object.entries(_slots)) { slotPromises.push( renderJSX(result, value).then((output2) => { if (output2.toString().trim().length === 0) return; slots[key] = () => output2; }) ); } await Promise.all(slotPromises); let output; if (vnode.type === ClientOnlyPlaceholder$1 && vnode.props["client:only"]) { output = await renderComponentToString( result, vnode.props["client:display-name"] ?? "", null, props, slots ); } else { output = await renderComponentToString( result, typeof vnode.type === "function" ? vnode.type.name : vnode.type, vnode.type, props, slots ); } return markHTMLString(output); } } return markHTMLString(`${vnode}`); } async function renderElement(result, tag, { children, ...props }) { return markHTMLString( `<${tag}${spreadAttributes(props)}${markHTMLString( (children == null || children === "") && voidElementNames.test(tag) ? `/>` : `>${children == null ? "" : await renderJSX(result, prerenderElementChildren$1(tag, children))}` )}` ); } function prerenderElementChildren$1(tag, children) { if (typeof children === "string" && (tag === "style" || tag === "script")) { return markHTMLString(children); } else { return children; } } const ClientOnlyPlaceholder = "astro-client-only"; function renderJSXToQueue(vnode, result, queue, pool, stack, parent, metadata) { if (vnode instanceof HTMLString) { const html = vnode.toString(); if (html.trim() === "") return; const node = pool.acquire("html-string", html); node.html = html; queue.nodes.push(node); return; } if (typeof vnode === "string") { const node = pool.acquire("text", vnode); node.content = vnode; queue.nodes.push(node); return; } if (typeof vnode === "number" || typeof vnode === "boolean") { const str = String(vnode); const node = pool.acquire("text", str); node.content = str; queue.nodes.push(node); return; } if (vnode == null || vnode === false) { return; } if (Array.isArray(vnode)) { for (let i = vnode.length - 1; i >= 0; i = i - 1) { stack.push({ node: vnode[i], parent, metadata }); } return; } if (!isVNode(vnode)) { const str = String(vnode); const node = pool.acquire("text", str); node.content = str; queue.nodes.push(node); return; } handleVNode(vnode, result, queue, pool, stack, parent, metadata); } function handleVNode(vnode, result, queue, pool, stack, parent, metadata) { if (!vnode.type) { throw new Error( `Unable to render ${result.pathname} because it contains an undefined Component! Did you forget to import the component or is it possible there is a typo?` ); } if (vnode.type === /* @__PURE__ */ Symbol.for("astro:fragment")) { stack.push({ node: vnode.props?.children, parent, metadata }); return; } if (isAstroComponentFactory(vnode.type)) { const factory = vnode.type; let props = {}; let slots = {}; for (const [key, value] of Object.entries(vnode.props ?? {})) { if (key === "children" || value && typeof value === "object" && value["$$slot"]) { slots[key === "children" ? "default" : key] = () => renderJSX(result, value); } else { props[key] = value; } } const displayName = metadata?.displayName || factory.name || "Anonymous"; const instance = createAstroComponentInstance(result, displayName, factory, props, slots); const queueNode = pool.acquire("component"); queueNode.instance = instance; queue.nodes.push(queueNode); return; } if (typeof vnode.type === "string" && vnode.type !== ClientOnlyPlaceholder) { renderHTMLElement(vnode, result, queue, pool, stack, parent, metadata); return; } if (typeof vnode.type === "function") { if (vnode.props?.["server:root"]) { const output3 = vnode.type(vnode.props ?? {}); stack.push({ node: output3, parent, metadata }); return; } const output2 = vnode.type(vnode.props ?? {}); stack.push({ node: output2, parent, metadata }); return; } const output = renderJSX(result, vnode); stack.push({ node: output, parent, metadata }); } function renderHTMLElement(vnode, _result, queue, pool, stack, parent, metadata) { const tag = vnode.type; const { children, ...props } = vnode.props ?? {}; const attrs = spreadAttributes(props); const isVoidElement = (children == null || children === "") && voidElementNames.test(tag); if (isVoidElement) { const html = `<${tag}${attrs}/>`; const node = pool.acquire("html-string", html); node.html = html; queue.nodes.push(node); return; } const openTag = `<${tag}${attrs}>`; const openTagHtml = queue.htmlStringCache ? queue.htmlStringCache.getOrCreate(openTag) : markHTMLString(openTag); stack.push({ node: openTagHtml, parent, metadata }); if (children != null && children !== "") { const processedChildren = prerenderElementChildren(tag, children, queue.htmlStringCache); stack.push({ node: processedChildren, parent, metadata }); } const closeTag = ``; const closeTagHtml = queue.htmlStringCache ? queue.htmlStringCache.getOrCreate(closeTag) : markHTMLString(closeTag); stack.push({ node: closeTagHtml, parent, metadata }); } function prerenderElementChildren(tag, children, htmlStringCache) { if (typeof children === "string" && (tag === "style" || tag === "script")) { return htmlStringCache ? htmlStringCache.getOrCreate(children) : markHTMLString(children); } return children; } async function buildRenderQueue(root, result, pool) { const queue = { nodes: [], result, pool, htmlStringCache: result._experimentalQueuedRendering?.htmlStringCache }; const stack = [{ node: root, parent: null }]; while (stack.length > 0) { const item = stack.pop(); if (!item) { continue; } let { node, parent } = item; if (isPromise(node)) { try { const resolved = await node; stack.push({ node: resolved, parent, metadata: item.metadata }); } catch (error) { throw error; } continue; } if (node == null || node === false) { continue; } if (typeof node === "string") { const queueNode = pool.acquire("text", node); queueNode.content = node; queue.nodes.push(queueNode); continue; } if (typeof node === "number" || typeof node === "boolean") { const str = String(node); const queueNode = pool.acquire("text", str); queueNode.content = str; queue.nodes.push(queueNode); continue; } if (isHTMLString(node)) { const html = node.toString(); const queueNode = pool.acquire("html-string", html); queueNode.html = html; queue.nodes.push(queueNode); continue; } if (node instanceof SlotString) { const html = node.toString(); const queueNode = pool.acquire("html-string", html); queueNode.html = html; queue.nodes.push(queueNode); continue; } if (isVNode(node)) { renderJSXToQueue(node, result, queue, pool, stack, parent, item.metadata); continue; } if (Array.isArray(node)) { for (const n of node) { stack.push({ node: n, parent, metadata: item.metadata }); } continue; } if (isRenderInstruction(node)) { const queueNode = pool.acquire("instruction"); queueNode.instruction = node; queue.nodes.push(queueNode); continue; } if (isRenderTemplateResult(node)) { const htmlParts = node["htmlParts"]; const expressions = node["expressions"]; if (htmlParts[0]) { const htmlString = queue.htmlStringCache ? queue.htmlStringCache.getOrCreate(htmlParts[0]) : markHTMLString(htmlParts[0]); stack.push({ node: htmlString, parent, metadata: item.metadata }); } for (let i = 0; i < expressions.length; i = i + 1) { stack.push({ node: expressions[i], parent, metadata: item.metadata }); if (htmlParts[i + 1]) { const htmlString = queue.htmlStringCache ? queue.htmlStringCache.getOrCreate(htmlParts[i + 1]) : markHTMLString(htmlParts[i + 1]); stack.push({ node: htmlString, parent, metadata: item.metadata }); } } continue; } if (isAstroComponentInstance(node)) { const queueNode = pool.acquire("component"); queueNode.instance = node; queue.nodes.push(queueNode); continue; } if (isAstroComponentFactory(node)) { const factory = node; const props = item.metadata?.props || {}; const slots = item.metadata?.slots || {}; const displayName = item.metadata?.displayName || factory.name || "Anonymous"; const instance = createAstroComponentInstance(result, displayName, factory, props, slots); const queueNode = pool.acquire("component"); queueNode.instance = instance; if (isAPropagatingComponent(result, factory)) { try { const returnValue = await instance.init(result); if (isHeadAndContent(returnValue) && returnValue.head) { result._metadata.extraHead.push(returnValue.head); } } catch (error) { throw error; } } queue.nodes.push(queueNode); continue; } if (isRenderInstance(node)) { const queueNode = pool.acquire("component"); queueNode.instance = node; queue.nodes.push(queueNode); continue; } if (typeof node === "object" && Symbol.iterator in node) { const items = Array.from(node); for (const iterItem of items) { stack.push({ node: iterItem, parent, metadata: item.metadata }); } continue; } if (typeof node === "object" && Symbol.asyncIterator in node) { try { const items = []; for await (const asyncItem of node) { items.push(asyncItem); } for (const iterItem of items) { stack.push({ node: iterItem, parent, metadata: item.metadata }); } } catch (error) { throw error; } continue; } if (node instanceof Response) { const queueNode = pool.acquire("html-string", ""); queueNode.html = ""; queue.nodes.push(queueNode); continue; } if (isHTMLString(node)) { const html = String(node); const queueNode = pool.acquire("html-string", html); queueNode.html = html; queue.nodes.push(queueNode); } else { const str = String(node); const queueNode = pool.acquire("text", str); queueNode.content = str; queue.nodes.push(queueNode); } } queue.nodes.reverse(); return queue; } async function renderQueue(queue, destination) { const result = queue.result; const pool = queue.pool; const cache = queue.htmlStringCache; let batchBuffer = ""; let i = 0; while (i < queue.nodes.length) { const node = queue.nodes[i]; try { if (canBatch(node)) { const batchStart = i; while (i < queue.nodes.length && canBatch(queue.nodes[i])) { batchBuffer += renderNodeToString(queue.nodes[i]); i = i + 1; } if (batchBuffer) { const htmlString = cache ? cache.getOrCreate(batchBuffer) : markHTMLString(batchBuffer); destination.write(htmlString); batchBuffer = ""; } if (pool) { for (let j = batchStart; j < i; j++) { pool.release(queue.nodes[j]); } } } else { await renderNode(node, destination, result); if (pool) { pool.release(node); } i = i + 1; } } catch (error) { throw error; } } if (batchBuffer) { const htmlString = cache ? cache.getOrCreate(batchBuffer) : markHTMLString(batchBuffer); destination.write(htmlString); } } function canBatch(node) { return node.type === "text" || node.type === "html-string"; } function renderNodeToString(node) { switch (node.type) { case "text": return node.content ? escapeHTML(node.content) : ""; case "html-string": return node.html || ""; case "component": case "instruction": { return ""; } } } async function renderNode(node, destination, result) { const cache = result._experimentalQueuedRendering?.htmlStringCache; switch (node.type) { case "text": { if (node.content) { const escaped = escapeHTML(node.content); const htmlString = cache ? cache.getOrCreate(escaped) : markHTMLString(escaped); destination.write(htmlString); } break; } case "html-string": { if (node.html) { const htmlString = cache ? cache.getOrCreate(node.html) : markHTMLString(node.html); destination.write(htmlString); } break; } case "instruction": { if (node.instruction) { destination.write(node.instruction); } break; } case "component": { if (node.instance) { let componentHtml = ""; const componentDestination = { write(chunk) { if (chunk instanceof Response) return; componentHtml += chunkToString(result, chunk); } }; await node.instance.render(componentDestination); if (componentHtml) { destination.write(componentHtml); } } break; } } } async function renderPage(result, componentFactory, props, children, streaming, route) { if (!isAstroComponentFactory(componentFactory)) { result._metadata.headInTree = result.componentMetadata.get(componentFactory.moduleId)?.containsHead ?? false; const pageProps = { ...props ?? {}, "server:root": true }; let str; if (result._experimentalQueuedRendering && result._experimentalQueuedRendering.enabled) { let vnode = await componentFactory(pageProps); if (componentFactory["astro:html"] && typeof vnode === "string") { vnode = markHTMLString(vnode); } const queue = await buildRenderQueue( vnode, result, result._experimentalQueuedRendering.pool ); let html = ""; let renderedFirst = false; const destination = { write(chunk) { if (chunk instanceof Response) return; if (!renderedFirst && !result.partial) { renderedFirst = true; const chunkStr = String(chunk); if (!/" : "\n"; html += doctype; } } html += chunkToString(result, chunk); } }; await renderQueue(queue, destination); str = html; } else { str = await renderComponentToString( result, componentFactory.name, componentFactory, pageProps, {}, true, route ); } const bytes = encoder.encode(str); const headers2 = new Headers([ ["Content-Type", "text/html"], ["Content-Length", bytes.byteLength.toString()] ]); if (result.shouldInjectCspMetaTags && (result.cspDestination === "header" || result.cspDestination === "adapter")) { headers2.set("content-security-policy", renderCspContent(result)); } return new Response(bytes, { headers: headers2, status: result.response.status }); } result._metadata.headInTree = result.componentMetadata.get(componentFactory.moduleId)?.containsHead ?? false; let body; if (streaming) { if (isNode && !isDeno) { const nodeBody = await renderToAsyncIterable( result, componentFactory, props, children, true, route ); body = nodeBody; } else { body = await renderToReadableStream(result, componentFactory, props, children, true, route); } } else { body = await renderToString(result, componentFactory, props, children, true, route); } if (body instanceof Response) return body; const init = result.response; const headers = new Headers(init.headers); if (result.shouldInjectCspMetaTags && result.cspDestination === "header" || result.cspDestination === "adapter") { headers.set("content-security-policy", renderCspContent(result)); } if (!streaming && typeof body === "string") { body = encoder.encode(body); headers.set("Content-Length", body.byteLength.toString()); } let status = init.status; let statusText = init.statusText; if (route?.route === "/404") { status = 404; if (statusText === "OK") { statusText = "Not Found"; } } else if (route?.route === "/500") { status = 500; if (statusText === "OK") { statusText = "Internal Server Error"; } } if (status) { return new Response(body, { ...init, headers, status, statusText }); } else { return new Response(body, { ...init, headers }); } } "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_".split("").reduce((v, c) => (v[c.charCodeAt(0)] = c, v), []); "-0123456789_".split("").reduce((v, c) => (v[c.charCodeAt(0)] = c, v), []); function __astro_tag_component__(Component, rendererName) { if (!Component) return; if (typeof Component !== "function") return; Object.defineProperty(Component, Renderer, { value: rendererName, enumerable: false, writable: false }); } function spreadAttributes(values = {}, _name, { class: scopedClassName } = {}) { let output = ""; if (scopedClassName) { if (typeof values.class !== "undefined") { values.class += ` ${scopedClassName}`; } else if (typeof values["class:list"] !== "undefined") { values["class:list"] = [values["class:list"], scopedClassName]; } else { values.class = scopedClassName; } } for (const [key, value] of Object.entries(values)) { output += addAttribute(value, key, true, _name); } return markHTMLString(output); } function defineStyleVars(defs) { let output = ""; let arr = !Array.isArray(defs) ? [defs] : defs; for (const vars of arr) { for (const [key, value] of Object.entries(vars)) { if (value || value === 0) { output += `--${key}: ${value};`; } } } return markHTMLString(output); } function deduplicateDirectiveValues(existingDirective, newDirective) { const [directiveName, ...existingValues] = existingDirective.split(/\s+/).filter(Boolean); const [newDirectiveName, ...newValues] = newDirective.split(/\s+/).filter(Boolean); if (directiveName !== newDirectiveName) { return void 0; } const finalDirectives = Array.from(/* @__PURE__ */ new Set([...existingValues, ...newValues])); return `${directiveName} ${finalDirectives.join(" ")}`; } function pushDirective(directives, newDirective) { let deduplicated = false; if (directives.length === 0) { return [newDirective]; } const finalDirectives = []; for (const directive of directives) { if (deduplicated) { finalDirectives.push(directive); continue; } const result = deduplicateDirectiveValues(directive, newDirective); if (result) { finalDirectives.push(result); deduplicated = true; } else { finalDirectives.push(directive); finalDirectives.push(newDirective); } } return finalDirectives; } async function callMiddleware(onRequest, apiContext, responseFunction) { let nextCalled = false; let responseFunctionPromise = void 0; const next = async (payload) => { nextCalled = true; responseFunctionPromise = responseFunction(apiContext, payload); return responseFunctionPromise; }; const middlewarePromise = onRequest(apiContext, next); return await Promise.resolve(middlewarePromise).then(async (value) => { if (nextCalled) { if (typeof value !== "undefined") { if (value instanceof Response === false) { throw new AstroError(MiddlewareNotAResponse); } return value; } else { if (responseFunctionPromise) { return responseFunctionPromise; } else { throw new AstroError(MiddlewareNotAResponse); } } } else if (typeof value === "undefined") { throw new AstroError(MiddlewareNoDataOrNextCalled); } else if (value instanceof Response === false) { throw new AstroError(MiddlewareNotAResponse); } else { return value; } }); } const EMPTY_OPTIONS = Object.freeze({ tags: [] }); class NoopAstroCache { enabled = false; set() { } get tags() { return []; } get options() { return EMPTY_OPTIONS; } async invalidate() { } } let hasWarned = false; class DisabledAstroCache { enabled = false; #logger; constructor(logger) { this.#logger = logger; } #warn() { if (!hasWarned) { hasWarned = true; this.#logger?.warn( "cache", "`cache.set()` was called but caching is not enabled. Configure a cache provider in your Astro config under `experimental.cache` to enable caching." ); } } set() { this.#warn(); } get tags() { return []; } get options() { return EMPTY_OPTIONS; } async invalidate() { throw new AstroError(CacheNotEnabled); } } function createRequest({ url, headers, method = "GET", body = void 0, logger, isPrerendered = false, routePattern, init }) { const headersObj = isPrerendered ? void 0 : headers instanceof Headers ? headers : new Headers( // Filter out HTTP/2 pseudo-headers. These are internally-generated headers added to all HTTP/2 requests with trusted metadata about the request. // Examples include `:method`, `:scheme`, `:authority`, and `:path`. // 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. // See https://httpwg.org/specs/rfc7540.html#HttpRequest Object.entries(headers).filter(([name]) => !name.startsWith(":")) ); if (typeof url === "string") url = new URL(url); if (isPrerendered) { url.search = ""; } const request = new Request(url, { method, headers: headersObj, // body is made available only if the request is for a page that will be on-demand rendered body: isPrerendered ? null : body, ...init }); if (isPrerendered) { let _headers = request.headers; const { value, writable, ...headersDesc } = Object.getOwnPropertyDescriptor(request, "headers") || {}; Object.defineProperty(request, "headers", { ...headersDesc, get() { logger.warn( null, `\`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.` ); return _headers; }, set(newHeaders) { _headers = newHeaders; } }); } return request; } function template({ title, pathname, statusCode = 404, tabTitle, body }) { return ` ${tabTitle}

${statusCode ? `${statusCode}: ` : ""}${title}

${body || `
Path: ${escape(pathname)}
`}
`; } const DEFAULT_404_ROUTE = { component: DEFAULT_404_COMPONENT, params: [], pattern: /^\/404\/?$/, prerender: false, pathname: "/404", segments: [[{ content: "404", dynamic: false, spread: false }]], type: "page", route: "/404", fallbackRoutes: [], isIndex: false, origin: "internal", distURL: [] }; async function default404Page({ pathname }) { return new Response( template({ statusCode: 404, title: "Not found", tabTitle: "404: Not Found", pathname }), { status: 404, headers: { "Content-Type": "text/html" } } ); } default404Page.isAstroComponentFactory = true; const default404Instance = { default: default404Page }; const ROUTE404_RE = /^\/404\/?$/; const ROUTE500_RE = /^\/500\/?$/; function isRoute404(route) { return ROUTE404_RE.test(route); } function isRoute500(route) { return ROUTE500_RE.test(route); } function findRouteToRewrite({ payload, routes, request, trailingSlash, buildFormat, base, outDir }) { let newUrl = void 0; if (payload instanceof URL) { newUrl = payload; } else if (payload instanceof Request) { newUrl = new URL(payload.url); } else { newUrl = new URL(collapseDuplicateSlashes(payload), new URL(request.url).origin); } const { pathname, resolvedUrlPathname } = normalizeRewritePathname( newUrl.pathname, base, trailingSlash, buildFormat ); newUrl.pathname = resolvedUrlPathname; const decodedPathname = decodeURI(pathname); if (isRoute404(decodedPathname)) { const errorRoute = routes.find((route) => route.route === "/404"); if (errorRoute) { return { routeData: errorRoute, newUrl, pathname: decodedPathname }; } } if (isRoute500(decodedPathname)) { const errorRoute = routes.find((route) => route.route === "/500"); if (errorRoute) { return { routeData: errorRoute, newUrl, pathname: decodedPathname }; } } let foundRoute; for (const route of routes) { if (route.pattern.test(decodedPathname)) { if (route.params && route.params.length !== 0 && route.distURL && route.distURL.length !== 0) { if (!route.distURL.find( (url) => url.href.replace(outDir.toString(), "").replace(/(?:\/index\.html|\.html)$/, "") === trimSlashes(pathname) )) { continue; } } foundRoute = route; break; } } if (foundRoute) { return { routeData: foundRoute, newUrl, pathname: decodedPathname }; } else { const custom404 = routes.find((route) => route.route === "/404"); if (custom404) { return { routeData: custom404, newUrl, pathname }; } else { return { routeData: DEFAULT_404_ROUTE, newUrl, pathname }; } } } function copyRequest(newUrl, oldRequest, isPrerendered, logger, routePattern) { if (oldRequest.bodyUsed) { throw new AstroError(RewriteWithBodyUsed); } return createRequest({ url: newUrl, method: oldRequest.method, body: oldRequest.body, isPrerendered, logger, headers: isPrerendered ? {} : oldRequest.headers, routePattern, init: { referrer: oldRequest.referrer, referrerPolicy: oldRequest.referrerPolicy, mode: oldRequest.mode, credentials: oldRequest.credentials, cache: oldRequest.cache, redirect: oldRequest.redirect, integrity: oldRequest.integrity, signal: oldRequest.signal, keepalive: oldRequest.keepalive, // https://fetch.spec.whatwg.org/#dom-request-duplex // @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 duplex: "half" } }); } function setOriginPathname(request, pathname, trailingSlash, buildFormat) { if (!pathname) { pathname = "/"; } const shouldAppendSlash = shouldAppendForwardSlash(trailingSlash, buildFormat); let finalPathname; if (pathname === "/") { finalPathname = "/"; } else if (shouldAppendSlash) { finalPathname = appendForwardSlash(pathname); } else { finalPathname = removeTrailingForwardSlash(pathname); } Reflect.set(request, originPathnameSymbol, encodeURIComponent(finalPathname)); } function getOriginPathname(request) { const origin = Reflect.get(request, originPathnameSymbol); if (origin) { return decodeURIComponent(origin); } return new URL(request.url).pathname; } function normalizeRewritePathname(urlPathname, base, trailingSlash, buildFormat) { let pathname = collapseDuplicateSlashes(urlPathname); const shouldAppendSlash = shouldAppendForwardSlash(trailingSlash, buildFormat); if (base !== "/") { const isBasePathRequest = urlPathname === base || urlPathname === removeTrailingForwardSlash(base); if (isBasePathRequest) { pathname = shouldAppendSlash ? "/" : ""; } else if (urlPathname.startsWith(base)) { pathname = shouldAppendSlash ? appendForwardSlash(urlPathname) : removeTrailingForwardSlash(urlPathname); pathname = pathname.slice(base.length); } } if (!pathname.startsWith("/") && shouldAppendSlash && urlPathname.endsWith("/")) { pathname = prependForwardSlash(pathname); } if (pathname === "/" && base !== "/" && !shouldAppendSlash) { pathname = ""; } if (buildFormat === "file") { pathname = pathname.replace(/\.html$/, ""); } let resolvedUrlPathname; if (base !== "/" && (pathname === "" || pathname === "/") && !shouldAppendSlash) { resolvedUrlPathname = removeTrailingForwardSlash(base); } else { resolvedUrlPathname = joinPaths(...[base, pathname].filter(Boolean)); } return { pathname, resolvedUrlPathname }; } const NOOP_ACTIONS_MOD = { server: {} }; function defineMiddleware(fn) { return fn; } const FORM_CONTENT_TYPES = [ "application/x-www-form-urlencoded", "multipart/form-data", "text/plain" ]; const SAFE_METHODS = ["GET", "HEAD", "OPTIONS"]; function createOriginCheckMiddleware() { return defineMiddleware((context, next) => { const { request, url, isPrerendered } = context; if (isPrerendered) { return next(); } if (SAFE_METHODS.includes(request.method)) { return next(); } const isSameOrigin = request.headers.get("origin") === url.origin; const hasContentType = request.headers.has("content-type"); if (hasContentType) { const formLikeHeader = hasFormLikeHeader(request.headers.get("content-type")); if (formLikeHeader && !isSameOrigin) { return new Response(`Cross-site ${request.method} form submissions are forbidden`, { status: 403 }); } } else { if (!isSameOrigin) { return new Response(`Cross-site ${request.method} form submissions are forbidden`, { status: 403 }); } } return next(); }); } function hasFormLikeHeader(contentType) { if (contentType) { for (const FORM_CONTENT_TYPE of FORM_CONTENT_TYPES) { if (contentType.toLowerCase().includes(FORM_CONTENT_TYPE)) { return true; } } } return false; } const NOOP_MIDDLEWARE_FN = async (_ctx, next) => { const response = await next(); response.headers.set(NOOP_MIDDLEWARE_HEADER, "true"); return response; }; const RedirectComponentInstance = { default() { return new Response(null, { status: 301 }); } }; const RedirectSinglePageBuiltModule = { page: () => Promise.resolve(RedirectComponentInstance), onRequest: (_, next) => next() }; function sanitizeParams(params) { return Object.fromEntries( Object.entries(params).map(([key, value]) => { if (typeof value === "string") { return [key, value.normalize().replace(/#/g, "%23").replace(/\?/g, "%3F")]; } return [key, value]; }) ); } function getParameter(part, params) { if (part.spread) { return params[part.content.slice(3)] || ""; } if (part.dynamic) { if (!params[part.content]) { throw new TypeError(`Missing parameter: ${part.content}`); } return params[part.content]; } return part.content.normalize().replace(/\?/g, "%3F").replace(/#/g, "%23").replace(/%5B/g, "[").replace(/%5D/g, "]"); } function getSegment(segment, params) { const segmentPath = segment.map((part) => getParameter(part, params)).join(""); return segmentPath ? collapseDuplicateLeadingSlashes("/" + segmentPath) : ""; } function getRouteGenerator(segments, addTrailingSlash) { return (params) => { const sanitizedParams = sanitizeParams(params); let trailing = ""; if (addTrailingSlash === "always" && segments.length) { trailing = "/"; } const path = segments.map((segment) => getSegment(segment, sanitizedParams)).join("") + trailing; return path || "/"; }; } const VALID_PARAM_TYPES = ["string", "undefined"]; function validateGetStaticPathsParameter([key, value], route) { if (!VALID_PARAM_TYPES.includes(typeof value)) { throw new AstroError({ ...GetStaticPathsInvalidRouteParam, message: GetStaticPathsInvalidRouteParam.message(key, value, typeof value), location: { file: route } }); } } function stringifyParams(params, route, trailingSlash) { const validatedParams = {}; for (const [key, value] of Object.entries(params)) { validateGetStaticPathsParameter([key, value], route.component); if (value !== void 0) { validatedParams[key] = trimSlashes(value); } } return getRouteGenerator(route.segments, trailingSlash)(validatedParams); } function validateDynamicRouteModule(mod, { ssr, route }) { if ((!ssr || route.prerender) && !mod.getStaticPaths) { throw new AstroError({ ...GetStaticPathsRequired, location: { file: route.component } }); } } function validateGetStaticPathsResult(result, route) { if (!Array.isArray(result)) { throw new AstroError({ ...InvalidGetStaticPathsReturn, message: InvalidGetStaticPathsReturn.message(typeof result), location: { file: route.component } }); } result.forEach((pathObject) => { if (typeof pathObject === "object" && Array.isArray(pathObject) || pathObject === null) { throw new AstroError({ ...InvalidGetStaticPathsEntry, message: InvalidGetStaticPathsEntry.message( Array.isArray(pathObject) ? "array" : typeof pathObject ) }); } if (pathObject.params === void 0 || pathObject.params === null || pathObject.params && Object.keys(pathObject.params).length === 0) { throw new AstroError({ ...GetStaticPathsExpectedParams, location: { file: route.component } }); } }); } function generatePaginateFunction(routeMatch, base, trailingSlash) { return function paginateUtility(data, args = {}) { const generate = getRouteGenerator(routeMatch.segments, trailingSlash); let { pageSize: _pageSize, params: _params, props: _props } = args; const pageSize = _pageSize || 10; const paramName = "page"; const additionalParams = _params || {}; const additionalProps = _props || {}; let includesFirstPageNumber; if (routeMatch.params.includes(`...${paramName}`)) { includesFirstPageNumber = false; } else if (routeMatch.params.includes(`${paramName}`)) { includesFirstPageNumber = true; } else { throw new AstroError({ ...PageNumberParamNotFound, message: PageNumberParamNotFound.message(paramName) }); } const lastPage = Math.max(1, Math.ceil(data.length / pageSize)); const result = [...Array(lastPage).keys()].map((num) => { const pageNum = num + 1; const start = pageSize === Number.POSITIVE_INFINITY ? 0 : (pageNum - 1) * pageSize; const end = Math.min(start + pageSize, data.length); const params = { ...additionalParams, [paramName]: includesFirstPageNumber || pageNum > 1 ? String(pageNum) : void 0 }; const current = addRouteBase(generate({ ...params }), base); const next = pageNum === lastPage ? void 0 : addRouteBase(generate({ ...params, page: String(pageNum + 1) }), base); const prev = pageNum === 1 ? void 0 : addRouteBase( generate({ ...params, page: !includesFirstPageNumber && pageNum - 1 === 1 ? void 0 : String(pageNum - 1) }), base ); const first = pageNum === 1 ? void 0 : addRouteBase( generate({ ...params, page: includesFirstPageNumber ? "1" : void 0 }), base ); const last = pageNum === lastPage ? void 0 : addRouteBase(generate({ ...params, page: String(lastPage) }), base); return { params, props: { ...additionalProps, page: { data: data.slice(start, end), start, end: end - 1, size: pageSize, total: data.length, currentPage: pageNum, lastPage, url: { current, next, prev, first, last } } } }; }); return result; }; } function addRouteBase(route, base) { let routeWithBase = joinPaths(base, route); if (routeWithBase === "") routeWithBase = "/"; return routeWithBase; } async function callGetStaticPaths({ mod, route, routeCache, ssr, base, trailingSlash }) { const cached = routeCache.get(route); if (!mod) { throw new Error("This is an error caused by Astro and not your code. Please file an issue."); } if (cached?.staticPaths) { return cached.staticPaths; } validateDynamicRouteModule(mod, { ssr, route }); if (ssr && !route.prerender) { const entry = Object.assign([], { keyed: /* @__PURE__ */ new Map() }); routeCache.set(route, { ...cached, staticPaths: entry }); return entry; } let staticPaths = []; if (!mod.getStaticPaths) { throw new Error("Unexpected Error."); } staticPaths = await mod.getStaticPaths({ // Q: Why the cast? // A: So users downstream can have nicer typings, we have to make some sacrifice in our internal typings, which necessitate a cast here paginate: generatePaginateFunction(route, base, trailingSlash), routePattern: route.route }); validateGetStaticPathsResult(staticPaths, route); const keyedStaticPaths = staticPaths; keyedStaticPaths.keyed = /* @__PURE__ */ new Map(); for (const sp of keyedStaticPaths) { const paramsKey = stringifyParams(sp.params, route, trailingSlash); keyedStaticPaths.keyed.set(paramsKey, sp); } routeCache.set(route, { ...cached, staticPaths: keyedStaticPaths }); return keyedStaticPaths; } class RouteCache { logger; cache = {}; runtimeMode; constructor(logger, runtimeMode = "production") { this.logger = logger; this.runtimeMode = runtimeMode; } /** Clear the cache. */ clearAll() { this.cache = {}; } set(route, entry) { const key = this.key(route); if (this.runtimeMode === "production" && this.cache[key]?.staticPaths) { this.logger.warn(null, `Internal Warning: route cache overwritten. (${key})`); } this.cache[key] = entry; } get(route) { return this.cache[this.key(route)]; } key(route) { return `${route.route}_${route.component}`; } } function findPathItemByKey(staticPaths, params, route, logger, trailingSlash) { const paramsKey = stringifyParams(params, route, trailingSlash); const matchedStaticPath = staticPaths.keyed.get(paramsKey); if (matchedStaticPath) { return matchedStaticPath; } logger.debug("router", `findPathItemByKey() - Unexpected cache miss looking for ${paramsKey}`); } function getPattern(segments, base, addTrailingSlash) { const pathname = segments.map((segment) => { if (segment.length === 1 && segment[0].spread) { return "(?:\\/(.*?))?"; } else { return "\\/" + segment.map((part) => { if (part.spread) { return "(.*?)"; } else if (part.dynamic) { return "([^/]+?)"; } else { return part.content.normalize().replace(/\?/g, "%3F").replace(/#/g, "%23").replace(/%5B/g, "[").replace(/%5D/g, "]").replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); } }).join(""); } }).join(""); const trailing = addTrailingSlash && segments.length ? getTrailingSlashPattern(addTrailingSlash) : "$"; let initial = "\\/"; if (addTrailingSlash === "never" && base !== "/") { initial = ""; } return new RegExp(`^${pathname || initial}${trailing}`); } function getTrailingSlashPattern(addTrailingSlash) { if (addTrailingSlash === "always") { return "\\/$"; } if (addTrailingSlash === "never") { return "$"; } return "\\/?$"; } const SERVER_ISLAND_ROUTE = "/_server-islands/[name]"; const SERVER_ISLAND_COMPONENT = "_server-islands.astro"; function badRequest(reason) { return new Response(null, { status: 400, statusText: "Bad request: " + reason }); } const DEFAULT_BODY_SIZE_LIMIT = 1024 * 1024; async function getRequestData(request, bodySizeLimit = DEFAULT_BODY_SIZE_LIMIT) { switch (request.method) { case "GET": { const url = new URL(request.url); const params = url.searchParams; if (!params.has("s") || !params.has("e") || !params.has("p")) { return badRequest("Missing required query parameters."); } const encryptedSlots = params.get("s"); return { encryptedComponentExport: params.get("e"), encryptedProps: params.get("p"), encryptedSlots }; } case "POST": { try { const body = await readBodyWithLimit(request, bodySizeLimit); const raw = new TextDecoder().decode(body); const data = JSON.parse(raw); if (Object.hasOwn(data, "slots") && typeof data.slots === "object") { return badRequest("Plaintext slots are not allowed. Slots must be encrypted."); } if (Object.hasOwn(data, "componentExport") && typeof data.componentExport === "string") { return badRequest( "Plaintext componentExport is not allowed. componentExport must be encrypted." ); } return data; } catch (e) { if (e instanceof BodySizeLimitError) { return new Response(null, { status: 413, statusText: e.message }); } if (e instanceof SyntaxError) { return badRequest("Request format is invalid."); } throw e; } } default: { return new Response(null, { status: 405 }); } } } function createEndpoint(manifest) { const page = async (result) => { const params = result.params; if (!params.name) { return new Response(null, { status: 400, statusText: "Bad request" }); } const componentId = params.name; const data = await getRequestData(result.request, manifest.serverIslandBodySizeLimit); if (data instanceof Response) { return data; } const serverIslandMappings = await manifest.serverIslandMappings?.(); const serverIslandMap = await serverIslandMappings?.serverIslandMap; let imp = serverIslandMap?.get(componentId); if (!imp) { return new Response(null, { status: 404, statusText: "Not found" }); } const key = await manifest.key; let componentExport; try { componentExport = await decryptString( key, data.encryptedComponentExport, `export:${componentId}` ); } catch (_e) { return badRequest("Encrypted componentExport value is invalid."); } const encryptedProps = data.encryptedProps; let props = {}; if (encryptedProps !== "") { try { const propString = await decryptString(key, encryptedProps, `props:${componentId}`); props = JSON.parse(propString); } catch (_e) { return badRequest("Encrypted props value is invalid."); } } let decryptedSlots = {}; const encryptedSlots = data.encryptedSlots; if (encryptedSlots !== "") { try { const slotsString = await decryptString(key, encryptedSlots, `slots:${componentId}`); decryptedSlots = JSON.parse(slotsString); } catch (_e) { return badRequest("Encrypted slots value is invalid."); } } const componentModule = await imp(); let Component = componentModule[componentExport]; const slots = {}; for (const prop in decryptedSlots) { slots[prop] = createSlotValueFromString(decryptedSlots[prop]); } result.response.headers.set("X-Robots-Tag", "noindex"); if (isAstroComponentFactory(Component)) { const ServerIsland = Component; Component = function(...args) { return ServerIsland.apply(this, args); }; Object.assign(Component, ServerIsland); Component.propagation = "self"; } return renderTemplate`${renderComponent(result, "Component", Component, props, slots)}`; }; page.isAstroComponentFactory = true; const instance = { default: page, partial: true }; return instance; } function createDefaultRoutes(manifest) { const root = new URL(manifest.rootDir); return [ { instance: default404Instance, matchesComponent: (filePath) => filePath.href === new URL(DEFAULT_404_COMPONENT, root).href, route: DEFAULT_404_ROUTE.route, component: DEFAULT_404_COMPONENT }, { instance: createEndpoint(manifest), matchesComponent: (filePath) => filePath.href === new URL(SERVER_ISLAND_COMPONENT, root).href, route: SERVER_ISLAND_ROUTE, component: SERVER_ISLAND_COMPONENT } ]; } function deserializeManifest(serializedManifest, routesList) { const routes = []; if (serializedManifest.routes) { for (const serializedRoute of serializedManifest.routes) { routes.push({ ...serializedRoute, routeData: deserializeRouteData(serializedRoute.routeData) }); const route = serializedRoute; route.routeData = deserializeRouteData(serializedRoute.routeData); } } const assets = new Set(serializedManifest.assets); const componentMetadata = new Map(serializedManifest.componentMetadata); const inlinedScripts = new Map(serializedManifest.inlinedScripts); const clientDirectives = new Map(serializedManifest.clientDirectives); const key = decodeKey(serializedManifest.key); return { // in case user middleware exists, this no-op middleware will be reassigned (see plugin-ssr.ts) middleware() { return { onRequest: NOOP_MIDDLEWARE_FN }; }, ...serializedManifest, rootDir: new URL(serializedManifest.rootDir), srcDir: new URL(serializedManifest.srcDir), publicDir: new URL(serializedManifest.publicDir), outDir: new URL(serializedManifest.outDir), cacheDir: new URL(serializedManifest.cacheDir), buildClientDir: new URL(serializedManifest.buildClientDir), buildServerDir: new URL(serializedManifest.buildServerDir), assets, componentMetadata, inlinedScripts, clientDirectives, routes, key }; } function deserializeRouteData(rawRouteData) { return { route: rawRouteData.route, type: rawRouteData.type, // nosemgrep: javascript.lang.security.audit.detect-non-literal-regexp.detect-non-literal-regexp // This pattern is serialized from Astro's own route manifest. pattern: new RegExp(rawRouteData.pattern), params: rawRouteData.params, component: rawRouteData.component, pathname: rawRouteData.pathname || void 0, segments: rawRouteData.segments, prerender: rawRouteData.prerender, redirect: rawRouteData.redirect, redirectRoute: rawRouteData.redirectRoute ? deserializeRouteData(rawRouteData.redirectRoute) : void 0, fallbackRoutes: rawRouteData.fallbackRoutes.map((fallback) => { return deserializeRouteData(fallback); }), isIndex: rawRouteData.isIndex, origin: rawRouteData.origin, distURL: rawRouteData.distURL }; } function deserializeRouteInfo(rawRouteInfo) { return { styles: rawRouteInfo.styles, file: rawRouteInfo.file, links: rawRouteInfo.links, scripts: rawRouteInfo.scripts, routeData: deserializeRouteData(rawRouteInfo.routeData) }; } function queuePoolSize(config) { return config?.poolSize ?? 1e3; } function queueRenderingEnabled(config) { return config?.enabled ?? false; } class NodePool { textPool = []; htmlStringPool = []; componentPool = []; instructionPool = []; maxSize; enableStats; stats = { acquireFromPool: 0, acquireNew: 0, released: 0, releasedDropped: 0 }; /** * Creates a new object pool for queue nodes. * * @param maxSize - Maximum number of nodes to keep in the pool (default: 1000). * The cap is shared across all typed sub-pools. * @param enableStats - Enable statistics tracking (default: false for performance) */ constructor(maxSize = 1e3, enableStats = false) { this.maxSize = maxSize; this.enableStats = enableStats; } /** * Acquires a queue node from the pool or creates a new one if the pool is empty. * Pops from the type-specific sub-pool to reuse an existing object when available. * * @param type - The type of queue node to acquire * @param content - Optional content to set on the node (for text or html-string types) * @returns A queue node ready to be populated with data */ acquire(type, content) { const pooledNode = this.popFromTypedPool(type); if (pooledNode) { if (this.enableStats) { this.stats.acquireFromPool = this.stats.acquireFromPool + 1; } this.resetNodeContent(pooledNode, type, content); return pooledNode; } if (this.enableStats) { this.stats.acquireNew = this.stats.acquireNew + 1; } return this.createNode(type, content); } /** * Creates a new node of the specified type with the given content. * Helper method to reduce branching in acquire(). */ createNode(type, content = "") { switch (type) { case "text": return { type: "text", content }; case "html-string": return { type: "html-string", html: content }; case "component": return { type: "component", instance: void 0 }; case "instruction": return { type: "instruction", instruction: void 0 }; } } /** * Pops a node from the type-specific sub-pool. * Returns undefined if the sub-pool for the requested type is empty. */ popFromTypedPool(type) { switch (type) { case "text": return this.textPool.pop(); case "html-string": return this.htmlStringPool.pop(); case "component": return this.componentPool.pop(); case "instruction": return this.instructionPool.pop(); } } /** * Resets the content/value field on a reused pooled node. * The type discriminant is already correct since we pop from the matching sub-pool. */ resetNodeContent(node, type, content) { switch (type) { case "text": node.content = content ?? ""; break; case "html-string": node.html = content ?? ""; break; case "component": node.instance = void 0; break; case "instruction": node.instruction = void 0; break; } } /** * Returns the total number of nodes across all typed sub-pools. */ totalPoolSize() { return this.textPool.length + this.htmlStringPool.length + this.componentPool.length + this.instructionPool.length; } /** * Releases a queue node back to the pool for reuse. * If the pool is at max capacity, the node is discarded (will be GC'd). * * @param node - The node to release back to the pool */ release(node) { if (this.totalPoolSize() >= this.maxSize) { if (this.enableStats) { this.stats.releasedDropped = this.stats.releasedDropped + 1; } return; } switch (node.type) { case "text": node.content = ""; this.textPool.push(node); break; case "html-string": node.html = ""; this.htmlStringPool.push(node); break; case "component": node.instance = void 0; this.componentPool.push(node); break; case "instruction": node.instruction = void 0; this.instructionPool.push(node); break; } if (this.enableStats) { this.stats.released = this.stats.released + 1; } } /** * Releases all nodes in an array back to the pool. * This is a convenience method for releasing multiple nodes at once. * * @param nodes - Array of nodes to release */ releaseAll(nodes) { for (const node of nodes) { this.release(node); } } /** * Clears all typed sub-pools, discarding all cached nodes. * This can be useful if you want to free memory after a large render. */ clear() { this.textPool.length = 0; this.htmlStringPool.length = 0; this.componentPool.length = 0; this.instructionPool.length = 0; } /** * Gets the current total number of nodes across all typed sub-pools. * Useful for monitoring pool usage and tuning maxSize. * * @returns Number of nodes currently available in the pool */ size() { return this.totalPoolSize(); } /** * Gets pool statistics for debugging. * * @returns Pool usage statistics including computed metrics */ getStats() { return { ...this.stats, poolSize: this.totalPoolSize(), maxSize: this.maxSize, hitRate: this.stats.acquireFromPool + this.stats.acquireNew > 0 ? this.stats.acquireFromPool / (this.stats.acquireFromPool + this.stats.acquireNew) * 100 : 0 }; } /** * Resets pool statistics. */ resetStats() { this.stats = { acquireFromPool: 0, acquireNew: 0, released: 0, releasedDropped: 0 }; } } function newNodePool(config) { const poolSize = queuePoolSize(config); return new NodePool(poolSize); } class HTMLStringCache { cache = /* @__PURE__ */ new Map(); maxSize; constructor(maxSize = 1e3) { this.maxSize = maxSize; this.warm(COMMON_HTML_PATTERNS); } /** * Get or create an HTMLString for the given content. * If cached, the existing object is returned and moved to end (most recently used). * If not cached, a new HTMLString is created, cached, and returned. * * @param content - The HTML string content * @returns HTMLString object (cached or newly created) */ getOrCreate(content) { const cached = this.cache.get(content); if (cached) { this.cache.delete(content); this.cache.set(content, cached); return cached; } const htmlString = new HTMLString(content); this.cache.set(content, htmlString); if (this.cache.size > this.maxSize) { const firstKey = this.cache.keys().next().value; if (firstKey !== void 0) { this.cache.delete(firstKey); } } return htmlString; } /** * Get current cache size */ size() { return this.cache.size; } /** * Pre-warms the cache with common HTML patterns. * This ensures first-render cache hits for frequently used tags. * * @param patterns - Array of HTML strings to pre-cache */ warm(patterns) { for (const pattern of patterns) { if (!this.cache.has(pattern)) { this.cache.set(pattern, new HTMLString(pattern)); } } } /** * Clear the entire cache */ clear() { this.cache.clear(); } } const COMMON_HTML_PATTERNS = [ // Structural elements "
", "
", "", "", "

", "

", "
", "
", "
", "
", "
", "
", "
", "
", "", "
", "
", "", // List elements "
    ", "
", "
    ", "
", "
  • ", "
  • ", // Void/self-closing elements "
    ", "
    ", "
    ", "
    ", // Heading elements "

    ", "

    ", "

    ", "

    ", "

    ", "

    ", "

    ", "

    ", // Inline elements "", "", "", "", "", "", "", "", // Common whitespace " ", "\n" ]; function matchesLevel(messageLevel, configuredLevel) { return levels[messageLevel] >= levels[configuredLevel]; } function nodeLogDestination(config = {}) { const { level = "info" } = config; return { write(event) { let dest = process.stderr; if (levels[event.level] < levels["error"]) { dest = process.stdout; } if (!matchesLevel(event.level, level)) { return; } let trailingLine = event.newLine ? "\n" : ""; if (event.label === "SKIP_FORMAT") { dest.write(event.message + trailingLine); } else { dest.write(getEventPrefix(event) + " " + event.message + trailingLine); } } }; } function node_default(options) { return nodeLogDestination(options); } function consoleLogDestination(config = {}) { const { level = "info" } = config; return { write(event) { let dest = console.error; if (levels[event.level] < levels["error"]) { dest = console.info; } if (!matchesLevel(event.level, level)) { return; } if (event.label === "SKIP_FORMAT") { dest(event.message); } else { dest(getEventPrefix(event) + " " + event.message); } } }; } function createConsoleLogger({ level }) { return new AstroLogger({ level, destination: consoleLogDestination() }); } function console_default(options) { return consoleLogDestination(options); } const SGR_REGEX = new RegExp(`${String.fromCharCode(27)}\\[[0-9;]*m`, "g"); function jsonLoggerDestination(config = {}) { const { pretty = false, level = "info" } = config; return { write(event) { let dest = process.stderr; if (levels[event.level] < levels["error"]) { dest = process.stdout; } if (!matchesLevel(event.level, level)) { return; } let trailingLine = event.newLine ? "\n" : ""; const message = event.message.replace(SGR_REGEX, ""); if (pretty) { dest.write( JSON.stringify({ message, label: event.label, level: event.level }, null, 2) + trailingLine ); } else { dest.write( JSON.stringify({ message, label: event.label, level: event.level }) + trailingLine ); } } }; } function compose(destinations) { return { write(chunk) { for (const logger of destinations) { logger.write(chunk); } }, flush() { for (const logger of destinations) { if (logger.flush) { logger.flush(); } } }, close() { for (const logger of destinations) { if (logger.close) { logger.close(); } } } }; } async function loadLogger(config, level = "info") { let cause = void 0; try { switch (config.entrypoint) { case "astro/logger/node": { return new AstroLogger({ destination: node_default(config.config), level }); } case "astro/logger/console": { return new AstroLogger({ destination: console_default(config.config), level }); } case "astro/logger/json": { return new AstroLogger({ destination: jsonLoggerDestination(config.config), level }); } case "astro/logger/compose": { let destinations = []; if (config.config?.loggers) { const loggers = config.config?.loggers; destinations = await Promise.all( loggers.map(async (loggerConfig) => { const logger = await import( /* @vite-ignore */ loggerConfig.entrypoint ); return logger.default(loggerConfig.config); }) ); } return new AstroLogger({ destination: compose(destinations), level }); } default: { const nodeLogger = await import( /* @vite-ignore */ config.entrypoint ); return new AstroLogger({ destination: nodeLogger.default(config.config), level }); } } } catch (e) { if (e instanceof Error) { cause = e; } } const error = new AstroError({ ...UnableToLoadLogger, message: UnableToLoadLogger.message(config.entrypoint) }); if (cause) { error.cause = cause; } throw error; } class Pipeline { internalMiddleware; resolvedMiddleware = void 0; resolvedLogger = false; resolvedActions = void 0; resolvedSessionDriver = void 0; resolvedCacheProvider = void 0; compiledCacheRoutes = void 0; nodePool; htmlStringCache; logger; manifest; /** * "development" or "production" only */ runtimeMode; renderers; resolve; streaming; /** * Used to provide better error messages for `Astro.clientAddress` */ adapterName; clientDirectives; inlinedScripts; compressHTML; i18n; middleware; routeCache; /** * Used for `Astro.site`. */ site; /** * Array of built-in, internal, routes. * Used to find the route module */ defaultRoutes; actions; sessionDriver; cacheProvider; cacheConfig; serverIslands; constructor(logger, manifest, runtimeMode, renderers, resolve, 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), actions = manifest.actions, sessionDriver = manifest.sessionDriver, cacheProvider = manifest.cacheProvider, cacheConfig = manifest.cacheConfig, serverIslands = manifest.serverIslandMappings) { this.logger = logger; this.manifest = manifest; this.runtimeMode = runtimeMode; this.renderers = renderers; this.resolve = resolve; this.streaming = streaming; this.adapterName = adapterName; this.clientDirectives = clientDirectives; this.inlinedScripts = inlinedScripts; this.compressHTML = compressHTML; this.i18n = i18n; this.middleware = middleware; this.routeCache = routeCache; this.site = site; this.defaultRoutes = defaultRoutes; this.actions = actions; this.sessionDriver = sessionDriver; this.cacheProvider = cacheProvider; this.cacheConfig = cacheConfig; this.serverIslands = serverIslands; this.internalMiddleware = []; if (i18n?.strategy !== "manual") { this.internalMiddleware.push( createI18nMiddleware(i18n, manifest.base, manifest.trailingSlash, manifest.buildFormat) ); } if (manifest.experimentalQueuedRendering.enabled) { this.nodePool = this.createNodePool( manifest.experimentalQueuedRendering.poolSize ?? 1e3, false ); if (manifest.experimentalQueuedRendering.contentCache) { this.htmlStringCache = this.createStringCache(); } } } /** * Resolves the middleware from the manifest, and returns the `onRequest` function. If `onRequest` isn't there, * it returns a no-op function */ async getMiddleware() { if (this.resolvedMiddleware) { return this.resolvedMiddleware; } if (this.middleware) { const middlewareInstance = await this.middleware(); const onRequest = middlewareInstance.onRequest ?? NOOP_MIDDLEWARE_FN; const internalMiddlewares = [onRequest]; if (this.manifest.checkOrigin) { internalMiddlewares.unshift(createOriginCheckMiddleware()); } this.resolvedMiddleware = sequence(...internalMiddlewares); return this.resolvedMiddleware; } else { this.resolvedMiddleware = NOOP_MIDDLEWARE_FN; return this.resolvedMiddleware; } } /** * Clears the cached middleware so it is re-resolved on the next request. * Called via HMR when middleware files change during development. */ clearMiddleware() { this.resolvedMiddleware = void 0; } /** * Resolves the logger destination from the manifest and updates the pipeline logger. * If the user configured `experimental.logger`, the bundled logger factory is loaded * and replaces the default console destination. This is lazy and only resolves once. */ async getLogger() { if (this.resolvedLogger) { return this.logger; } this.resolvedLogger = true; if (this.manifest.experimentalLogger) { this.logger = await loadLogger(this.manifest.experimentalLogger); } return this.logger; } async getActions() { if (this.resolvedActions) { return this.resolvedActions; } else if (this.actions) { return this.actions(); } return NOOP_ACTIONS_MOD; } async getSessionDriver() { if (this.resolvedSessionDriver !== void 0) { return this.resolvedSessionDriver; } if (this.sessionDriver) { const driverModule = await this.sessionDriver(); this.resolvedSessionDriver = driverModule?.default || null; return this.resolvedSessionDriver; } this.resolvedSessionDriver = null; return null; } async getCacheProvider() { if (this.resolvedCacheProvider !== void 0) { return this.resolvedCacheProvider; } if (this.cacheProvider) { const mod = await this.cacheProvider(); const factory = mod?.default || null; this.resolvedCacheProvider = factory ? factory(this.cacheConfig?.options) : null; return this.resolvedCacheProvider; } this.resolvedCacheProvider = null; return null; } async getServerIslands() { if (this.serverIslands) { return this.serverIslands(); } return { serverIslandMap: /* @__PURE__ */ new Map(), serverIslandNameMap: /* @__PURE__ */ new Map() }; } async getAction(path) { const pathKeys = path.split(".").map((key) => decodeURIComponent(key)); let { server } = await this.getActions(); if (!server || !(typeof server === "object")) { throw new TypeError( `Expected \`server\` export in actions file to be an object. Received ${typeof server}.` ); } for (const key of pathKeys) { if (FORBIDDEN_PATH_KEYS.has(key)) { throw new AstroError({ ...ActionNotFoundError, message: ActionNotFoundError.message(pathKeys.join(".")) }); } if (!Object.hasOwn(server, key)) { throw new AstroError({ ...ActionNotFoundError, message: ActionNotFoundError.message(pathKeys.join(".")) }); } server = server[key]; } if (typeof server !== "function") { throw new TypeError( `Expected handler for action ${pathKeys.join(".")} to be a function. Received ${typeof server}.` ); } return server; } async getModuleForRoute(route) { for (const defaultRoute of this.defaultRoutes) { if (route.component === defaultRoute.component) { return { page: () => Promise.resolve(defaultRoute.instance) }; } } if (route.type === "redirect") { return RedirectSinglePageBuiltModule; } else { if (this.manifest.pageMap) { const importComponentInstance = this.manifest.pageMap.get(route.component); if (!importComponentInstance) { throw new Error( `Unexpectedly unable to find a component instance for route ${route.route}` ); } return await importComponentInstance(); } else if (this.manifest.pageModule) { return this.manifest.pageModule; } throw new Error( "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." ); } } createNodePool(poolSize, stats) { return new NodePool(poolSize, stats); } createStringCache() { return new HTMLStringCache(1e3); } } function routeIsRedirect(route) { return route?.type === "redirect"; } function routeIsFallback(route) { return route?.type === "fallback"; } function getFallbackRoute(route, routeList) { const fallbackRoute = routeList.find((r) => { if (route.route === "/" && r.routeData.route === "/") { return true; } return r.routeData.fallbackRoutes.find((f) => { return f.route === route.route; }); }); if (!fallbackRoute) { throw new Error(`No fallback route found for route ${route.route}`); } return fallbackRoute.routeData; } function routeHasHtmlExtension(route) { return route.segments.some( (segment) => segment.some((part) => !part.dynamic && part.content.includes(".html")) ); } async function getProps(opts) { const { logger, mod, routeData: route, routeCache, pathname, serverLike, base, trailingSlash } = opts; if (!route || route.pathname) { return {}; } if (routeIsRedirect(route) || routeIsFallback(route) || route.component === DEFAULT_404_COMPONENT) { return {}; } const staticPaths = await callGetStaticPaths({ mod, route, routeCache, ssr: serverLike, base, trailingSlash }); const params = getParams(route, pathname); const matchedStaticPath = findPathItemByKey(staticPaths, params, route, logger, trailingSlash); if (!matchedStaticPath && (serverLike ? route.prerender : true)) { throw new AstroError({ ...NoMatchingStaticPathFound, message: NoMatchingStaticPathFound.message(pathname), hint: NoMatchingStaticPathFound.hint([route.component]) }); } if (mod) { validatePrerenderEndpointCollision(route, mod, params); } const props = matchedStaticPath?.props ? { ...matchedStaticPath.props } : {}; return props; } function getParams(route, pathname) { if (!route.params.length) return {}; const path = pathname.endsWith(".html") && !routeHasHtmlExtension(route) ? pathname.slice(0, -5) : pathname; const allPatterns = [route, ...route.fallbackRoutes].map((r) => r.pattern); const paramsMatch = allPatterns.map((pattern) => pattern.exec(path)).find((x) => x); if (!paramsMatch) return {}; const params = {}; route.params.forEach((key, i) => { if (key.startsWith("...")) { params[key.slice(3)] = paramsMatch[i + 1] ? paramsMatch[i + 1] : void 0; } else { params[key] = paramsMatch[i + 1]; } }); return params; } function validatePrerenderEndpointCollision(route, mod, params) { if (route.type === "endpoint" && mod.getStaticPaths) { const lastSegment = route.segments[route.segments.length - 1]; const paramValues = Object.values(params); const lastParam = paramValues[paramValues.length - 1]; if (lastSegment.length === 1 && lastSegment[0].dynamic && lastParam === void 0) { throw new AstroError({ ...PrerenderDynamicEndpointPathCollide, message: PrerenderDynamicEndpointPathCollide.message(route.route), hint: PrerenderDynamicEndpointPathCollide.hint(route.component), location: { file: route.component } }); } } } function getFunctionExpression(slot) { if (!slot) return; const expressions = slot?.expressions?.filter((e) => isRenderInstruction(e) === false); if (expressions?.length !== 1) return; return expressions[0]; } class Slots { #result; #slots; #logger; constructor(result, slots, logger) { this.#result = result; this.#slots = slots; this.#logger = logger; if (slots) { for (const key of Object.keys(slots)) { if (this[key] !== void 0) { throw new AstroError({ ...ReservedSlotName, message: ReservedSlotName.message(key) }); } Object.defineProperty(this, key, { get() { return true; }, enumerable: true }); } } } has(name) { if (!this.#slots) return false; return Boolean(this.#slots[name]); } async render(name, args = []) { if (!this.#slots || !this.has(name)) return; const result = this.#result; if (!Array.isArray(args)) { this.#logger.warn( null, `Expected second parameter to be an array, received a ${typeof args}. If you're trying to pass an array as a single argument and getting unexpected results, make sure you're passing your array as an item of an array. Ex: Astro.slots.render('default', [["Hello", "World"]])` ); } else if (args.length > 0) { const slotValue = this.#slots[name]; const component = typeof slotValue === "function" ? await slotValue(result) : await slotValue; const expression = getFunctionExpression(component); if (expression) { const slot = async () => typeof expression === "function" ? expression(...args) : expression; return await renderSlotToString(result, slot).then((res) => { return res; }); } if (typeof component === "function") { return await renderJSX(result, component(...args)).then( (res) => res != null ? String(res) : res ); } } const content = await renderSlotToString(result, this.#slots[name]); const outHTML = chunkToString(result, content); return outHTML; } } function sequence(...handlers) { const filtered = handlers.filter((h) => !!h); const length = filtered.length; if (!length) { return defineMiddleware((_context, next) => { return next(); }); } return defineMiddleware((context, next) => { let carriedPayload = void 0; return applyHandle(0, context); function applyHandle(i, handleContext) { const handle = filtered[i]; const result = handle(handleContext, async (payload) => { if (i < length - 1) { if (payload) { let newRequest; if (payload instanceof Request) { newRequest = payload; } else if (payload instanceof URL) { newRequest = new Request(payload, handleContext.request.clone()); } else { newRequest = new Request( new URL(payload, handleContext.url.origin), handleContext.request.clone() ); } const oldPathname = handleContext.url.pathname; const pipeline = Reflect.get(handleContext, pipelineSymbol); const { routeData, pathname } = await pipeline.tryRewrite( payload, handleContext.request ); if (pipeline.manifest.serverLike === true && handleContext.isPrerendered === false && routeData.prerender === true) { throw new AstroError({ ...ForbiddenRewrite, message: ForbiddenRewrite.message( handleContext.url.pathname, pathname, routeData.component ), hint: ForbiddenRewrite.hint(routeData.component) }); } carriedPayload = payload; handleContext.request = newRequest; handleContext.url = new URL(newRequest.url); handleContext.params = getParams(routeData, pathname); handleContext.routePattern = routeData.route; setOriginPathname( handleContext.request, oldPathname, pipeline.manifest.trailingSlash, pipeline.manifest.buildFormat ); } return applyHandle(i + 1, handleContext); } else { return next(payload ?? carriedPayload); } }); return result; } }); } function isExternalURL(url) { return url.startsWith("http://") || url.startsWith("https://") || url.startsWith("//"); } function redirectIsExternal(redirect) { if (typeof redirect === "string") { return isExternalURL(redirect); } else { return isExternalURL(redirect.destination); } } function computeRedirectStatus(method, redirect, redirectRoute) { return redirectRoute && typeof redirect === "object" ? redirect.status : method === "GET" ? 301 : 308; } function resolveRedirectTarget(params, redirect, redirectRoute, trailingSlash) { if (typeof redirectRoute !== "undefined") { const generate = getRouteGenerator(redirectRoute.segments, trailingSlash); return generate(params); } else if (typeof redirect === "string") { if (redirectIsExternal(redirect)) { return redirect; } else { let target = redirect; for (const param of Object.keys(params)) { const paramValue = params[param]; target = target.replace(`[${param}]`, paramValue).replace(`[...${param}]`, paramValue); } return target; } } else if (typeof redirect === "undefined") { return "/"; } return redirect.destination; } async function renderRedirect(renderContext) { const { request: { method }, routeData } = renderContext; const { redirect, redirectRoute } = routeData; const status = computeRedirectStatus(method, redirect, redirectRoute); const headers = { location: encodeURI( resolveRedirectTarget( renderContext.params, redirect, redirectRoute, renderContext.pipeline.manifest.trailingSlash ) ) }; if (redirect && redirectIsExternal(redirect)) { if (typeof redirect === "string") { return Response.redirect(redirect, status); } else { return Response.redirect(redirect.destination, status); } } return new Response(null, { status, headers }); } function matchRoute(pathname, manifest) { if (isRoute404(pathname)) { const errorRoute = manifest.routes.find((route) => isRoute404(route.route)); if (errorRoute) return errorRoute; } if (isRoute500(pathname)) { const errorRoute = manifest.routes.find((route) => isRoute500(route.route)); if (errorRoute) return errorRoute; } return manifest.routes.find((route) => { return route.pattern.test(pathname) || route.fallbackRoutes.some((fallbackRoute) => fallbackRoute.pattern.test(pathname)); }); } function isRoute404or500(route) { return isRoute404(route.route) || isRoute500(route.route); } function isRouteServerIsland(route) { return route.component === SERVER_ISLAND_COMPONENT; } function isRouteExternalRedirect(route) { return !!(route.type === "redirect" && route.redirect && redirectIsExternal(route.redirect)); } function defaultSetHeaders(options) { const headers = new Headers(); const directives = []; if (options.maxAge !== void 0) { directives.push(`max-age=${options.maxAge}`); } if (options.swr !== void 0) { directives.push(`stale-while-revalidate=${options.swr}`); } if (directives.length > 0) { headers.set("CDN-Cache-Control", directives.join(", ")); } if (options.tags && options.tags.length > 0) { headers.set("Cache-Tag", options.tags.join(", ")); } if (options.lastModified) { headers.set("Last-Modified", options.lastModified.toUTCString()); } if (options.etag) { headers.set("ETag", options.etag); } return headers; } function isLiveDataEntry(value) { return value != null && typeof value === "object" && "id" in value && "data" in value && "cacheHint" in value; } const APPLY_HEADERS = /* @__PURE__ */ Symbol.for("astro:cache:apply"); const IS_ACTIVE = /* @__PURE__ */ Symbol.for("astro:cache:active"); class AstroCache { #options = {}; #tags = /* @__PURE__ */ new Set(); #disabled = false; #provider; enabled = true; constructor(provider) { this.#provider = provider; } set(input) { if (input === false) { this.#disabled = true; this.#tags.clear(); this.#options = {}; return; } this.#disabled = false; let options; if (isLiveDataEntry(input)) { if (!input.cacheHint) return; options = input.cacheHint; } else { options = input; } if ("maxAge" in options && options.maxAge !== void 0) this.#options.maxAge = options.maxAge; if ("swr" in options && options.swr !== void 0) this.#options.swr = options.swr; if ("etag" in options && options.etag !== void 0) this.#options.etag = options.etag; if (options.lastModified !== void 0) { if (!this.#options.lastModified || options.lastModified > this.#options.lastModified) { this.#options.lastModified = options.lastModified; } } if (options.tags) { for (const tag of options.tags) this.#tags.add(tag); } } get tags() { return [...this.#tags]; } /** * Get the current cache options (read-only snapshot). * Includes all accumulated options: maxAge, swr, tags, etag, lastModified. */ get options() { return { ...this.#options, tags: this.tags }; } async invalidate(input) { if (!this.#provider) { throw new AstroError(CacheNotEnabled); } let options; if (isLiveDataEntry(input)) { options = { tags: input.cacheHint?.tags ?? [] }; } else { options = input; } return this.#provider.invalidate(options); } /** @internal */ [APPLY_HEADERS](response) { if (this.#disabled) return; const finalOptions = { ...this.#options, tags: this.tags }; if (finalOptions.maxAge === void 0 && !finalOptions.tags?.length) return; const headers = this.#provider?.setHeaders?.(finalOptions) ?? defaultSetHeaders(finalOptions); for (const [key, value] of headers) { response.headers.set(key, value); } } /** @internal */ get [IS_ACTIVE]() { return !this.#disabled && (this.#options.maxAge !== void 0 || this.#tags.size > 0); } } function applyCacheHeaders(cache, response) { if (APPLY_HEADERS in cache) { cache[APPLY_HEADERS](response); } } const ROUTE_DYNAMIC_SPLIT = /\[(.+?\(.+?\)|.+?)\]/; const ROUTE_SPREAD = /^\.{3}.+$/; function getParts(part, file) { const result = []; part.split(ROUTE_DYNAMIC_SPLIT).map((str, i) => { if (!str) return; const dynamic = i % 2 === 1; const [, content] = dynamic ? /([^(]+)$/.exec(str) || [null, null] : [null, str]; if (!content || dynamic && !/^(?:\.\.\.)?[\w$]+$/.test(content)) { throw new Error(`Invalid route ${file} \u2014 parameter name must match /^[a-zA-Z0-9_$]+$/`); } result.push({ content, dynamic, spread: dynamic && ROUTE_SPREAD.test(content) }); }); return result; } function routeComparator(a, b) { const commonLength = Math.min(a.segments.length, b.segments.length); for (let index = 0; index < commonLength; index++) { const aSegment = a.segments[index]; const bSegment = b.segments[index]; const aIsStatic = aSegment.every((part) => !part.dynamic && !part.spread); const bIsStatic = bSegment.every((part) => !part.dynamic && !part.spread); if (aIsStatic && bIsStatic) { const aContent = aSegment.map((part) => part.content).join(""); const bContent = bSegment.map((part) => part.content).join(""); if (aContent !== bContent) { return aContent.localeCompare(bContent); } } if (aIsStatic !== bIsStatic) { return aIsStatic ? -1 : 1; } const aAllDynamic = aSegment.every((part) => part.dynamic); const bAllDynamic = bSegment.every((part) => part.dynamic); if (aAllDynamic !== bAllDynamic) { return aAllDynamic ? 1 : -1; } const aHasSpread = aSegment.some((part) => part.spread); const bHasSpread = bSegment.some((part) => part.spread); if (aHasSpread !== bHasSpread) { return aHasSpread ? 1 : -1; } } const aLength = a.segments.length; const bLength = b.segments.length; if (aLength !== bLength) { const aEndsInRest = a.segments.at(-1)?.some((part) => part.spread); const bEndsInRest = b.segments.at(-1)?.some((part) => part.spread); if (aEndsInRest !== bEndsInRest && Math.abs(aLength - bLength) === 1) { if (aLength > bLength && aEndsInRest) { return 1; } if (bLength > aLength && bEndsInRest) { return -1; } } return aLength > bLength ? -1 : 1; } if (a.type === "endpoint" !== (b.type === "endpoint")) { return a.type === "endpoint" ? -1 : 1; } return a.route.localeCompare(b.route); } function compileCacheRoutes(routes, base, trailingSlash) { const compiled = Object.entries(routes).map(([path, options]) => { const segments = removeLeadingForwardSlash(path).split("/").filter(Boolean).map((s) => getParts(s, path)); const pattern = getPattern(segments, base, trailingSlash); return { pattern, options, segments, route: path }; }); compiled.sort( (a, b) => routeComparator( { segments: a.segments, route: a.route, type: "page" }, { segments: b.segments, route: b.route, type: "page" } ) ); return compiled; } function matchCacheRoute(pathname, compiledRoutes) { for (const route of compiledRoutes) { if (route.pattern.test(pathname)) return route.options; } return null; } const PERSIST_SYMBOL = /* @__PURE__ */ Symbol(); const DEFAULT_COOKIE_NAME = "astro-session"; const VALID_COOKIE_REGEX = /^[\w-]+$/; const unflatten = (parsed, _) => { return unflatten$1(parsed, { URL: (href) => new URL(href) }); }; const stringify = (data, _) => { return stringify$1(data, { // Support URL objects URL: (val) => val instanceof URL && val.href }); }; class AstroSession { // The cookies object. #cookies; // The session configuration. #config; // The cookie config #cookieConfig; // The cookie name #cookieName; // The unstorage object for the session driver. #storage; #data; // The session ID. A v4 UUID. #sessionID; // Sessions to destroy. Needed because we won't have the old session ID after it's destroyed locally. #toDestroy = /* @__PURE__ */ new Set(); // Session keys to delete. Used for partial data sets to avoid overwriting the deleted value. #toDelete = /* @__PURE__ */ new Set(); // Whether the session is dirty and needs to be saved. #dirty = false; // Whether the session cookie has been set. #cookieSet = false; // Whether the session ID was sourced from a client cookie rather than freshly generated. #sessionIDFromCookie = false; // The local data is "partial" if it has not been loaded from storage yet and only // contains values that have been set or deleted in-memory locally. // We do this to avoid the need to block on loading data when it is only being set. // When we load the data from storage, we need to merge it with the local partial data, // preserving in-memory changes and deletions. #partial = true; // The driver factory function provided by the pipeline #driverFactory; static #sharedStorage = /* @__PURE__ */ new Map(); constructor({ cookies, config, runtimeMode, driverFactory, mockStorage }) { if (!config) { throw new AstroError({ ...SessionStorageInitError, message: SessionStorageInitError.message( "No driver was defined in the session configuration and the adapter did not provide a default driver." ) }); } this.#cookies = cookies; this.#driverFactory = driverFactory; const { cookie: cookieConfig = DEFAULT_COOKIE_NAME, ...configRest } = config; let cookieConfigObject; if (typeof cookieConfig === "object") { const { name = DEFAULT_COOKIE_NAME, ...rest } = cookieConfig; this.#cookieName = name; cookieConfigObject = rest; } else { this.#cookieName = cookieConfig || DEFAULT_COOKIE_NAME; } this.#cookieConfig = { sameSite: "lax", secure: runtimeMode === "production", path: "/", ...cookieConfigObject, httpOnly: true }; this.#config = configRest; if (mockStorage) { this.#storage = mockStorage; } } /** * Gets a session value. Returns `undefined` if the session or value does not exist. */ async get(key) { return (await this.#ensureData()).get(key)?.data; } /** * Checks if a session value exists. */ async has(key) { return (await this.#ensureData()).has(key); } /** * Gets all session values. */ async keys() { return (await this.#ensureData()).keys(); } /** * Gets all session values. */ async values() { return [...(await this.#ensureData()).values()].map((entry) => entry.data); } /** * Gets all session entries. */ async entries() { return [...(await this.#ensureData()).entries()].map(([key, entry]) => [key, entry.data]); } /** * Deletes a session value. */ delete(key) { this.#data?.delete(key); if (this.#partial) { this.#toDelete.add(key); } this.#dirty = true; } /** * Sets a session value. The session is created if it does not exist. */ set(key, value, { ttl } = {}) { if (!key) { throw new AstroError({ ...SessionStorageSaveError, message: "The session key was not provided." }); } let cloned; try { cloned = unflatten(JSON.parse(stringify(value))); } catch (err) { throw new AstroError( { ...SessionStorageSaveError, message: `The session data for ${key} could not be serialized.`, hint: "See the devalue library for all supported types: https://github.com/rich-harris/devalue" }, { cause: err } ); } if (!this.#cookieSet) { this.#setCookie(); this.#cookieSet = true; } this.#data ??= /* @__PURE__ */ new Map(); const lifetime = ttl ?? this.#config.ttl; const expires = typeof lifetime === "number" ? Date.now() + lifetime * 1e3 : lifetime; this.#data.set(key, { data: cloned, expires }); this.#dirty = true; } /** * Destroys the session, clearing the cookie and storage if it exists. */ destroy() { const sessionId = this.#sessionID ?? this.#cookies.get(this.#cookieName)?.value; if (sessionId) { this.#toDestroy.add(sessionId); } this.#cookies.delete(this.#cookieName, this.#cookieConfig); this.#sessionID = void 0; this.#data = void 0; this.#dirty = true; } /** * Regenerates the session, creating a new session ID. The existing session data is preserved. */ async regenerate() { let data = /* @__PURE__ */ new Map(); try { data = await this.#ensureData(); } catch (err) { console.error("Failed to load session data during regeneration:", err); } const oldSessionId = this.#sessionID; this.#sessionID = crypto.randomUUID(); this.#sessionIDFromCookie = false; this.#data = data; this.#dirty = true; await this.#setCookie(); if (oldSessionId && this.#storage) { this.#storage.removeItem(oldSessionId).catch((err) => { console.error("Failed to remove old session data:", err); }); } } // Persists the session data to storage. // This is called automatically at the end of the request. // Uses a symbol to prevent users from calling it directly. async [PERSIST_SYMBOL]() { if (!this.#dirty && !this.#toDestroy.size) { return; } const storage = await this.#ensureStorage(); if (this.#dirty && this.#data) { const data = await this.#ensureData(); this.#toDelete.forEach((key2) => data.delete(key2)); const key = this.#ensureSessionID(); let serialized; try { serialized = stringify(data); } catch (err) { throw new AstroError( { ...SessionStorageSaveError, message: SessionStorageSaveError.message( "The session data could not be serialized.", this.#config.driver ) }, { cause: err } ); } await storage.setItem(key, serialized); this.#dirty = false; } if (this.#toDestroy.size > 0) { const cleanupPromises = [...this.#toDestroy].map( (sessionId) => storage.removeItem(sessionId).catch((err) => { console.error("Failed to clean up session %s:", sessionId, err); }) ); await Promise.all(cleanupPromises); this.#toDestroy.clear(); } } get sessionID() { return this.#sessionID; } /** * Loads a session from storage with the given ID, and replaces the current session. * Any changes made to the current session will be lost. * This is not normally needed, as the session is automatically loaded using the cookie. * However it can be used to restore a session where the ID has been recorded somewhere * else (e.g. in a database). */ async load(sessionID) { this.#sessionID = sessionID; this.#data = void 0; await this.#setCookie(); await this.#ensureData(); } /** * Sets the session cookie. */ async #setCookie() { if (!VALID_COOKIE_REGEX.test(this.#cookieName)) { throw new AstroError({ ...SessionStorageSaveError, message: "Invalid cookie name. Cookie names can only contain letters, numbers, and dashes." }); } const value = this.#ensureSessionID(); this.#cookies.set(this.#cookieName, value, this.#cookieConfig); } /** * Attempts to load the session data from storage, or creates a new data object if none exists. * If there is existing partial data, it will be merged into the new data object. */ async #ensureData() { const storage = await this.#ensureStorage(); if (this.#data && !this.#partial) { return this.#data; } this.#data ??= /* @__PURE__ */ new Map(); const raw = await storage.get(this.#ensureSessionID()); if (!raw) { if (this.#sessionIDFromCookie) { this.#sessionID = crypto.randomUUID(); this.#sessionIDFromCookie = false; if (this.#cookieSet) { await this.#setCookie(); } } return this.#data; } try { const storedMap = unflatten(raw); if (!(storedMap instanceof Map)) { await this.destroy(); throw new AstroError({ ...SessionStorageInitError, message: SessionStorageInitError.message( "The session data was an invalid type.", this.#config.driver ) }); } const now = Date.now(); for (const [key, value] of storedMap) { const expired = typeof value.expires === "number" && value.expires < now; if (!this.#data.has(key) && !this.#toDelete.has(key) && !expired) { this.#data.set(key, value); } } this.#partial = false; return this.#data; } catch (err) { await this.destroy(); if (err instanceof AstroError) { throw err; } throw new AstroError( { ...SessionStorageInitError, message: SessionStorageInitError.message( "The session data could not be parsed.", this.#config.driver ) }, { cause: err } ); } } /** * Returns the session ID, generating a new one if it does not exist. */ #ensureSessionID() { if (!this.#sessionID) { const cookieValue = this.#cookies.get(this.#cookieName)?.value; if (cookieValue) { this.#sessionID = cookieValue; this.#sessionIDFromCookie = true; } else { this.#sessionID = crypto.randomUUID(); } } return this.#sessionID; } /** * Ensures the storage is initialized. * This is called automatically when a storage operation is needed. */ async #ensureStorage() { if (this.#storage) { return this.#storage; } if (AstroSession.#sharedStorage.has(this.#config.driver)) { this.#storage = AstroSession.#sharedStorage.get(this.#config.driver); return this.#storage; } if (!this.#driverFactory) { throw new AstroError({ ...SessionStorageInitError, message: SessionStorageInitError.message( "Astro could not load the driver correctly. Does it exist?", this.#config.driver ) }); } const driver = this.#driverFactory; try { this.#storage = createStorage({ driver: { ...driver(this.#config.options), // Unused methods hasItem() { return false; }, getKeys() { return []; } } }); AstroSession.#sharedStorage.set(this.#config.driver, this.#storage); return this.#storage; } catch (err) { throw new AstroError( { ...SessionStorageInitError, message: SessionStorageInitError.message("Unknown error", this.#config.driver) }, { cause: err } ); } } } function validateAndDecodePathname(pathname) { let decoded; try { decoded = decodeURI(pathname); } catch (_e) { throw new Error("Invalid URL encoding"); } const hasDecoding = decoded !== pathname; const decodedStillHasEncoding = /%[0-9a-fA-F]{2}/.test(decoded); if (hasDecoding && decodedStillHasEncoding) { throw new Error("Multi-level URL encoding is not allowed"); } return decoded; } class RenderContext { pipeline; locals; middleware; actions; serverIslands; // It must be a DECODED pathname pathname; request; routeData; status; clientAddress; cookies; params; url; props; partial; shouldInjectCspMetaTags; session; cache; skipMiddleware; constructor(pipeline, locals, middleware, actions, serverIslands, pathname, request, routeData, status, clientAddress, cookies = new AstroCookies(request), params = getParams(routeData, pathname), url = RenderContext.#createNormalizedUrl(request.url), props = {}, partial = void 0, shouldInjectCspMetaTags = pipeline.manifest.shouldInjectCspMetaTags, session = void 0, cache, skipMiddleware = false) { this.pipeline = pipeline; this.locals = locals; this.middleware = middleware; this.actions = actions; this.serverIslands = serverIslands; this.pathname = pathname; this.request = request; this.routeData = routeData; this.status = status; this.clientAddress = clientAddress; this.cookies = cookies; this.params = params; this.url = url; this.props = props; this.partial = partial; this.shouldInjectCspMetaTags = shouldInjectCspMetaTags; this.session = session; this.cache = cache; this.skipMiddleware = skipMiddleware; } static #createNormalizedUrl(requestUrl) { const url = new URL(requestUrl); try { url.pathname = validateAndDecodePathname(url.pathname); } catch { try { url.pathname = decodeURI(url.pathname); } catch { } } url.pathname = collapseDuplicateSlashes(url.pathname); return url; } /** * A flag that tells the render content if the rewriting was triggered */ isRewriting = false; /** * A safety net in case of loops */ counter = 0; result = void 0; static async create({ locals = {}, pathname, pipeline, request, routeData, clientAddress, status = 200, props, partial = void 0, shouldInjectCspMetaTags, skipMiddleware = false }) { const pipelineMiddleware = await pipeline.getMiddleware(); const pipelineActions = await pipeline.getActions(); const pipelineSessionDriver = await pipeline.getSessionDriver(); const serverIslands = await pipeline.getServerIslands(); setOriginPathname( request, pathname, pipeline.manifest.trailingSlash, pipeline.manifest.buildFormat ); const cookies = new AstroCookies(request); const session = pipeline.manifest.sessionConfig && pipelineSessionDriver ? new AstroSession({ cookies, config: pipeline.manifest.sessionConfig, runtimeMode: pipeline.runtimeMode, driverFactory: pipelineSessionDriver, mockStorage: null }) : void 0; let cache; if (!pipeline.cacheConfig) { cache = new DisabledAstroCache(pipeline.logger); } else if (pipeline.runtimeMode === "development") { cache = new NoopAstroCache(); } else { const cacheProvider = await pipeline.getCacheProvider(); cache = new AstroCache(cacheProvider); if (pipeline.cacheConfig?.routes) { if (!pipeline.compiledCacheRoutes) { pipeline.compiledCacheRoutes = compileCacheRoutes( pipeline.cacheConfig.routes, pipeline.manifest.base, pipeline.manifest.trailingSlash ); } const matched = matchCacheRoute(pathname, pipeline.compiledCacheRoutes); if (matched) { cache.set(matched); } } } return new RenderContext( pipeline, locals, sequence(...pipeline.internalMiddleware, pipelineMiddleware), pipelineActions, serverIslands, pathname, request, routeData, status, clientAddress, cookies, void 0, void 0, props, partial, shouldInjectCspMetaTags ?? pipeline.manifest.shouldInjectCspMetaTags, session, cache, skipMiddleware ); } /** * The main function of the RenderContext. * * Use this function to render any route known to Astro. * It attempts to render a route. A route can be a: * * - page * - redirect * - endpoint * - fallback */ async render(componentInstance, slots = {}) { const { middleware, pipeline } = this; const { logger, streaming, manifest } = pipeline; const props = Object.keys(this.props).length > 0 ? this.props : await getProps({ mod: componentInstance, routeData: this.routeData, routeCache: this.pipeline.routeCache, pathname: this.pathname, logger, serverLike: manifest.serverLike, base: manifest.base, trailingSlash: manifest.trailingSlash }); const actionApiContext = this.createActionAPIContext(); const apiContext = this.createAPIContext(props, actionApiContext); this.counter++; if (this.counter === 4) { return new Response("Loop Detected", { // https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/508 status: 508, statusText: "Astro detected a loop where you tried to call the rewriting logic more than four times." }); } const lastNext = async (ctx, payload) => { if (payload) { const oldPathname = this.pathname; pipeline.logger.debug("router", "Called rewriting to:", payload); const { routeData, componentInstance: newComponent, pathname, newUrl } = await pipeline.tryRewrite(payload, this.request); if (this.pipeline.manifest.serverLike === true && this.routeData.prerender === false && routeData.prerender === true) { throw new AstroError({ ...ForbiddenRewrite, message: ForbiddenRewrite.message(this.pathname, pathname, routeData.component), hint: ForbiddenRewrite.hint(routeData.component) }); } this.routeData = routeData; componentInstance = newComponent; if (payload instanceof Request) { this.request = payload; } else { this.request = copyRequest( newUrl, this.request, // need to send the flag of the previous routeData routeData.prerender, this.pipeline.logger, this.routeData.route ); } this.isRewriting = true; this.url = RenderContext.#createNormalizedUrl(this.request.url); this.params = getParams(routeData, pathname); this.pathname = pathname; this.status = 200; setOriginPathname( this.request, oldPathname, this.pipeline.manifest.trailingSlash, this.pipeline.manifest.buildFormat ); } let response2; if (!ctx.isPrerendered && !this.skipMiddleware) { const { action, setActionResult, serializeActionResult } = getActionContext(ctx); if (action?.calledFrom === "form") { const actionResult = await action.handler(); setActionResult(action.name, serializeActionResult(actionResult)); } } switch (this.routeData.type) { case "endpoint": { response2 = await renderEndpoint( componentInstance, ctx, this.routeData.prerender, logger ); break; } case "redirect": return renderRedirect(this); case "page": { this.result = await this.createResult(componentInstance, actionApiContext); try { response2 = await renderPage( this.result, componentInstance?.default, props, slots, streaming, this.routeData ); } catch (e) { this.result.cancelled = true; throw e; } response2.headers.set(ROUTE_TYPE_HEADER, "page"); if (this.routeData.route === "/404" || this.routeData.route === "/500") { response2.headers.set(REROUTE_DIRECTIVE_HEADER, "no"); } if (this.isRewriting) { response2.headers.set(REWRITE_DIRECTIVE_HEADER_KEY, REWRITE_DIRECTIVE_HEADER_VALUE); } break; } case "fallback": { return new Response(null, { status: 500, headers: { [ROUTE_TYPE_HEADER]: "fallback" } }); } } const responseCookies = getCookiesFromResponse(response2); if (responseCookies) { this.cookies.merge(responseCookies); } return response2; }; if (isRouteExternalRedirect(this.routeData)) { return renderRedirect(this); } const response = this.skipMiddleware ? await lastNext(apiContext) : await callMiddleware(middleware, apiContext, lastNext); if (response.headers.get(ROUTE_TYPE_HEADER)) { response.headers.delete(ROUTE_TYPE_HEADER); } attachCookiesToResponse(response, this.cookies); return response; } createAPIContext(props, context) { const redirect = (path, status = 302) => new Response(null, { status, headers: { Location: path } }); const rewrite = async (reroutePayload) => { return await this.#executeRewrite(reroutePayload); }; Reflect.set(context, pipelineSymbol, this.pipeline); return Object.assign(context, { props, redirect, rewrite, getActionResult: createGetActionResult(context.locals), callAction: createCallAction(context) }); } async #executeRewrite(reroutePayload) { this.pipeline.logger.debug("router", "Calling rewrite: ", reroutePayload); const oldPathname = this.pathname; const { routeData, componentInstance, newUrl, pathname } = await this.pipeline.tryRewrite( reroutePayload, this.request ); const isI18nFallback = routeData.fallbackRoutes && routeData.fallbackRoutes.length > 0; if (this.pipeline.manifest.serverLike && !this.routeData.prerender && routeData.prerender && !isI18nFallback) { throw new AstroError({ ...ForbiddenRewrite, message: ForbiddenRewrite.message(this.pathname, pathname, routeData.component), hint: ForbiddenRewrite.hint(routeData.component) }); } this.routeData = routeData; if (reroutePayload instanceof Request) { this.request = reroutePayload; } else { this.request = copyRequest( newUrl, this.request, // need to send the flag of the previous routeData routeData.prerender, this.pipeline.logger, this.routeData.route ); } this.url = RenderContext.#createNormalizedUrl(this.request.url); const newCookies = new AstroCookies(this.request); if (this.cookies) { newCookies.merge(this.cookies); } this.cookies = newCookies; this.params = getParams(routeData, pathname); this.pathname = pathname; this.isRewriting = true; this.status = 200; setOriginPathname( this.request, oldPathname, this.pipeline.manifest.trailingSlash, this.pipeline.manifest.buildFormat ); return await this.render(componentInstance); } createActionAPIContext() { const renderContext = this; const { params, pipeline, url } = this; return { // Don't allow reassignment of cookies because it doesn't work get cookies() { return renderContext.cookies; }, routePattern: this.routeData.route, isPrerendered: this.routeData.prerender, get clientAddress() { return renderContext.getClientAddress(); }, get currentLocale() { return renderContext.computeCurrentLocale(); }, generator: ASTRO_GENERATOR, get locals() { return renderContext.locals; }, set locals(_) { throw new AstroError(LocalsReassigned); }, params, get preferredLocale() { return renderContext.computePreferredLocale(); }, get preferredLocaleList() { return renderContext.computePreferredLocaleList(); }, request: this.request, site: pipeline.site, url, get originPathname() { return getOriginPathname(renderContext.request); }, get session() { if (this.isPrerendered) { pipeline.logger.warn( "session", `context.session was used when rendering the route ${colors.green(this.routePattern)}, but it is not available on prerendered routes. If you need access to sessions, make sure that the route is server-rendered using \`export const prerender = false;\` or by setting \`output\` to \`"server"\` in your Astro config to make all your routes server-rendered by default. For more information, see https://docs.astro.build/en/guides/sessions/` ); return void 0; } if (!renderContext.session) { pipeline.logger.warn( "session", `context.session was used when rendering the route ${colors.green(this.routePattern)}, but no storage configuration was provided. Either configure the storage manually or use an adapter that provides session storage. For more information, see https://docs.astro.build/en/guides/sessions/` ); return void 0; } return renderContext.session; }, get cache() { return renderContext.cache; }, get csp() { if (!pipeline.manifest.csp) { if (pipeline.runtimeMode === "production") { pipeline.logger.warn( "csp", `context.csp was used when rendering the route ${colors.green(this.routePattern)}, but CSP was not configured. For more information, see https://docs.astro.build/en/reference/experimental-flags/csp/` ); } return void 0; } return { insertDirective(payload) { if (renderContext?.result?.directives) { renderContext.result.directives = pushDirective( renderContext.result.directives, payload ); } else { renderContext?.result?.directives.push(payload); } }, insertScriptResource(resource) { renderContext.result?.scriptResources.push(resource); }, insertStyleResource(resource) { renderContext.result?.styleResources.push(resource); }, insertStyleHash(hash) { renderContext.result?.styleHashes.push(hash); }, insertScriptHash(hash) { renderContext.result?.scriptHashes.push(hash); } }; }, get logger() { if (!pipeline.manifest.experimentalLogger) { pipeline.logger.warn( null, "The Astro.logger is available only when experimental.logger is defined." ); return void 0; } return { info(msg) { pipeline.logger.info(null, msg); }, warn(msg) { pipeline.logger.warn(null, msg); }, error(msg) { pipeline.logger.error(null, msg); } }; } }; } async createResult(mod, ctx) { const { cookies, pathname, pipeline, routeData, status } = this; const { clientDirectives, inlinedScripts, compressHTML, manifest, renderers, resolve } = pipeline; const { links, scripts, styles } = await pipeline.headElements(routeData); const extraStyleHashes = []; const extraScriptHashes = []; const shouldInjectCspMetaTags = this.shouldInjectCspMetaTags; const cspAlgorithm = manifest.csp?.algorithm ?? "SHA-256"; if (shouldInjectCspMetaTags) { for (const style of styles) { extraStyleHashes.push(await generateCspDigest(style.children, cspAlgorithm)); } for (const script of scripts) { extraScriptHashes.push(await generateCspDigest(script.children, cspAlgorithm)); } } const componentMetadata = await pipeline.componentMetadata(routeData) ?? manifest.componentMetadata; const headers = new Headers({ "Content-Type": "text/html" }); const partial = typeof this.partial === "boolean" ? this.partial : Boolean(mod.partial); const actionResult = hasActionPayload(this.locals) ? deserializeActionResult(this.locals._actionPayload.actionResult) : void 0; const response = { status: actionResult?.error ? actionResult?.error.status : status, statusText: actionResult?.error ? actionResult?.error.type : "OK", get headers() { return headers; }, // Disallow `Astro.response.headers = new Headers` set headers(_) { throw new AstroError(AstroResponseHeadersReassigned); } }; const result = { base: manifest.base, userAssetsBase: manifest.userAssetsBase, cancelled: false, clientDirectives, inlinedScripts, componentMetadata, compressHTML, cookies, /** This function returns the `Astro` faux-global */ createAstro: (props, slots) => this.createAstro(result, props, slots, ctx), links, params: this.params, partial, pathname, renderers, resolve, response, request: this.request, scripts, styles, actionResult, serverIslandNameMap: this.serverIslands.serverIslandNameMap ?? /* @__PURE__ */ new Map(), key: manifest.key, trailingSlash: manifest.trailingSlash, _experimentalQueuedRendering: { pool: pipeline.nodePool, htmlStringCache: pipeline.htmlStringCache, enabled: manifest.experimentalQueuedRendering?.enabled, poolSize: manifest.experimentalQueuedRendering?.poolSize, contentCache: manifest.experimentalQueuedRendering?.contentCache }, _metadata: { hasHydrationScript: false, rendererSpecificHydrationScripts: /* @__PURE__ */ new Set(), hasRenderedHead: false, renderedScripts: /* @__PURE__ */ new Set(), hasDirectives: /* @__PURE__ */ new Set(), hasRenderedServerIslandRuntime: false, headInTree: false, extraHead: [], extraStyleHashes, extraScriptHashes, propagators: /* @__PURE__ */ new Set(), templateDepth: 0 }, cspDestination: manifest.csp?.cspDestination ?? (routeData.prerender ? "meta" : "header"), shouldInjectCspMetaTags, cspAlgorithm, // The following arrays must be cloned; otherwise, they become mutable across routes. scriptHashes: manifest.csp?.scriptHashes ? [...manifest.csp.scriptHashes] : [], scriptResources: manifest.csp?.scriptResources ? [...manifest.csp.scriptResources] : [], styleHashes: manifest.csp?.styleHashes ? [...manifest.csp.styleHashes] : [], styleResources: manifest.csp?.styleResources ? [...manifest.csp.styleResources] : [], directives: manifest.csp?.directives ? [...manifest.csp.directives] : [], isStrictDynamic: manifest.csp?.isStrictDynamic ?? false, internalFetchHeaders: manifest.internalFetchHeaders }; return result; } #astroPagePartial; /** * The Astro global is sourced in 3 different phases: * - **Static**: `.generator` and `.glob` is printed by the compiler, instantiated once per process per astro file * - **Page-level**: `.request`, `.cookies`, `.locals` etc. These remain the same for the duration of the request. * - **Component-level**: `.props`, `.slots`, and `.self` are unique to each _use_ of each component. * * 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. */ createAstro(result, props, slotValues, apiContext) { let astroPagePartial; if (this.isRewriting) { astroPagePartial = this.#astroPagePartial = this.createAstroPagePartial(result, apiContext); } else { astroPagePartial = this.#astroPagePartial ??= this.createAstroPagePartial(result, apiContext); } const astroComponentPartial = { props, self: null }; const Astro = Object.assign( Object.create(astroPagePartial), astroComponentPartial ); let _slots; Object.defineProperty(Astro, "slots", { get: () => { if (!_slots) { _slots = new Slots( result, slotValues, this.pipeline.logger ); } return _slots; } }); return Astro; } createAstroPagePartial(result, apiContext) { const renderContext = this; const { cookies, locals, params, pipeline, url } = this; const { response } = result; const redirect = (path, status = 302) => { if (this.request[responseSentSymbol$1]) { throw new AstroError({ ...ResponseSentError }); } return new Response(null, { status, headers: { Location: path } }); }; const rewrite = async (reroutePayload) => { return await this.#executeRewrite(reroutePayload); }; const callAction = createCallAction(apiContext); return { generator: ASTRO_GENERATOR, routePattern: this.routeData.route, isPrerendered: this.routeData.prerender, cookies, get session() { if (this.isPrerendered) { pipeline.logger.warn( "session", `Astro.session was used when rendering the route ${colors.green(this.routePattern)}, but it is not available on prerendered pages. If you need access to sessions, make sure that the page is server-rendered using \`export const prerender = false;\` or by setting \`output\` to \`"server"\` in your Astro config to make all your pages server-rendered by default. For more information, see https://docs.astro.build/en/guides/sessions/` ); return void 0; } if (!renderContext.session) { pipeline.logger.warn( "session", `Astro.session was used when rendering the route ${colors.green(this.routePattern)}, but no storage configuration was provided. Either configure the storage manually or use an adapter that provides session storage. For more information, see https://docs.astro.build/en/guides/sessions/` ); return void 0; } return renderContext.session; }, get cache() { return renderContext.cache; }, get clientAddress() { return renderContext.getClientAddress(); }, get currentLocale() { return renderContext.computeCurrentLocale(); }, params, get preferredLocale() { return renderContext.computePreferredLocale(); }, get preferredLocaleList() { return renderContext.computePreferredLocaleList(); }, locals, redirect, rewrite, request: this.request, response, site: pipeline.site, getActionResult: createGetActionResult(locals), get callAction() { return callAction; }, url, get originPathname() { return getOriginPathname(renderContext.request); }, get csp() { if (!pipeline.manifest.csp) { if (pipeline.runtimeMode === "production") { pipeline.logger.warn( "csp", `Astro.csp was used when rendering the route ${colors.green(this.routePattern)}, but CSP was not configured. For more information, see https://docs.astro.build/en/reference/experimental-flags/csp/` ); } return void 0; } return { insertDirective(payload) { if (renderContext?.result?.directives) { renderContext.result.directives = pushDirective( renderContext.result.directives, payload ); } else { renderContext?.result?.directives.push(payload); } }, insertScriptResource(resource) { renderContext.result?.scriptResources.push(resource); }, insertStyleResource(resource) { renderContext.result?.styleResources.push(resource); }, insertStyleHash(hash) { renderContext.result?.styleHashes.push(hash); }, insertScriptHash(hash) { renderContext.result?.scriptHashes.push(hash); } }; }, get logger() { return { info(msg) { pipeline.logger.info(null, msg); }, warn(msg) { pipeline.logger.warn(null, msg); }, error(msg) { pipeline.logger.error(null, msg); } }; } }; } getClientAddress() { const { pipeline, routeData, clientAddress } = this; if (routeData.prerender) { throw new AstroError({ ...PrerenderClientAddressNotAvailable, message: PrerenderClientAddressNotAvailable.message(routeData.component) }); } if (clientAddress) { return clientAddress; } if (pipeline.adapterName) { throw new AstroError({ ...ClientAddressNotAvailable, message: ClientAddressNotAvailable.message(pipeline.adapterName) }); } throw new AstroError(StaticClientAddressNotAvailable); } /** * API Context may be created multiple times per request, i18n data needs to be computed only once. * So, it is computed and saved here on creation of the first APIContext and reused for later ones. */ #currentLocale; computeCurrentLocale() { const { url, pipeline: { i18n }, routeData } = this; if (!i18n) return; const { defaultLocale, locales, strategy } = i18n; const fallbackTo = strategy === "pathname-prefix-other-locales" || strategy === "domains-prefix-other-locales" ? defaultLocale : void 0; if (this.#currentLocale) { return this.#currentLocale; } let computedLocale; if (isRouteServerIsland(routeData)) { let referer = this.request.headers.get("referer"); if (referer) { if (URL.canParse(referer)) { referer = new URL(referer).pathname; } computedLocale = computeCurrentLocale(referer, locales, defaultLocale); } } else { let pathname = routeData.pathname; if (!routeData.pattern.test(url.pathname)) { for (const fallbackRoute of routeData.fallbackRoutes) { if (fallbackRoute.pattern.test(url.pathname)) { pathname = fallbackRoute.pathname; break; } } } pathname = pathname && !isRoute404or500(routeData) ? pathname : url.pathname; computedLocale = computeCurrentLocale(pathname, locales, defaultLocale); if (routeData.params.length > 0) { const localeFromParams = computeCurrentLocaleFromParams(this.params, locales); if (localeFromParams) { computedLocale = localeFromParams; } } } this.#currentLocale = computedLocale ?? fallbackTo; return this.#currentLocale; } #preferredLocale; computePreferredLocale() { const { pipeline: { i18n }, request } = this; if (!i18n) return; return this.#preferredLocale ??= computePreferredLocale(request, i18n.locales); } #preferredLocaleList; computePreferredLocaleList() { const { pipeline: { i18n }, request } = this; if (!i18n) return; return this.#preferredLocaleList ??= computePreferredLocaleList(request, i18n.locales); } } function redirectTemplate({ status, absoluteLocation, relativeLocation, from }) { const delay = status === 302 ? 2 : 0; return ` Redirecting to: ${relativeLocation} Redirecting ${from ? `from ${from} ` : ""}to ${relativeLocation} `; } function ensure404Route(manifest) { if (!manifest.routes.some((route) => route.route === "/404")) { manifest.routes.push(DEFAULT_404_ROUTE); } return manifest; } class Router { #routes; #base; #baseWithoutTrailingSlash; #buildFormat; #trailingSlash; constructor(routes, options) { this.#routes = [...routes].sort(routeComparator); this.#base = normalizeBase(options.base); this.#baseWithoutTrailingSlash = removeTrailingForwardSlash(this.#base); this.#buildFormat = options.buildFormat; this.#trailingSlash = options.trailingSlash; } /** * Match an input pathname against the route list. * If allowWithoutBase is true, a non-base-prefixed path is still considered. */ match(inputPathname, { allowWithoutBase = false } = {}) { const normalized = getRedirectForPathname(inputPathname); if (normalized.redirect) { return { type: "redirect", location: normalized.redirect, status: 301 }; } if (this.#base !== "/") { const baseWithSlash = `${this.#baseWithoutTrailingSlash}/`; if (this.#trailingSlash === "always" && (normalized.pathname === this.#baseWithoutTrailingSlash || normalized.pathname === this.#base)) { return { type: "redirect", location: baseWithSlash, status: 301 }; } if (this.#trailingSlash === "never" && normalized.pathname === baseWithSlash) { return { type: "redirect", location: this.#baseWithoutTrailingSlash, status: 301 }; } } const baseResult = stripBase( normalized.pathname, this.#base, this.#baseWithoutTrailingSlash, this.#trailingSlash ); if (!baseResult) { if (!allowWithoutBase) { return { type: "none", reason: "outside-base" }; } } let pathname = baseResult ?? normalized.pathname; if (this.#buildFormat === "file") { pathname = normalizeFileFormatPathname(pathname); } const route = this.#routes.find((candidate) => { if (candidate.pattern.test(pathname)) return true; return candidate.fallbackRoutes.some((fallbackRoute) => fallbackRoute.pattern.test(pathname)); }); if (!route) { return { type: "none", reason: "no-match" }; } const params = getParams(route, pathname); return { type: "match", route, params, pathname }; } } function normalizeBase(base) { if (!base) return "/"; if (base === "/") return base; return prependForwardSlash(base); } function getRedirectForPathname(pathname) { let value = prependForwardSlash(pathname); if (value.startsWith("//")) { const collapsed = `/${value.replace(/^\/+/, "")}`; return { pathname: value, redirect: collapsed }; } return { pathname: value }; } function stripBase(pathname, base, baseWithoutTrailingSlash, trailingSlash) { if (base === "/") return pathname; const baseWithSlash = `${baseWithoutTrailingSlash}/`; if (pathname === baseWithoutTrailingSlash || pathname === base) { return trailingSlash === "always" ? null : "/"; } if (pathname === baseWithSlash) { return trailingSlash === "never" ? null : "/"; } if (pathname.startsWith(baseWithSlash)) { return pathname.slice(baseWithoutTrailingSlash.length); } return null; } function normalizeFileFormatPathname(pathname) { if (pathname.endsWith("/index.html")) { const trimmed = pathname.slice(0, -"/index.html".length); return trimmed === "" ? "/" : trimmed; } if (pathname.endsWith(".html")) { const trimmed = pathname.slice(0, -".html".length); return trimmed === "" ? "/" : trimmed; } return pathname; } class BaseApp { manifest; manifestData; pipeline; #adapterLogger; baseWithoutTrailingSlash; #router; get logger() { return this.pipeline.logger; } get adapterLogger() { if (!this.#adapterLogger) { this.#adapterLogger = new AstroIntegrationLogger( this.logger.options, this.manifest.adapterName ); } return this.#adapterLogger; } constructor(manifest, streaming = true, ...args) { this.manifest = manifest; this.manifestData = { routes: manifest.routes.map((route) => route.routeData) }; this.baseWithoutTrailingSlash = removeTrailingForwardSlash(manifest.base); this.pipeline = this.createPipeline(streaming, manifest, ...args); ensure404Route(this.manifestData); this.#router = this.createRouter(this.manifestData); } async createRenderContext(payload) { return RenderContext.create(payload); } getAdapterLogger() { return this.adapterLogger; } /** * Resets the cached adapter logger so it picks up a new logger instance. * Used by BuildApp when the logger is replaced via setOptions(). */ resetAdapterLogger() { this.#adapterLogger = void 0; } getAllowedDomains() { return this.manifest.allowedDomains; } matchesAllowedDomains(forwardedHost, protocol) { return BaseApp.validateForwardedHost(forwardedHost, this.manifest.allowedDomains, protocol); } static validateForwardedHost(forwardedHost, allowedDomains, protocol) { if (!allowedDomains || allowedDomains.length === 0) { return false; } try { const testUrl = new URL(`${protocol || "https"}://${forwardedHost}`); return allowedDomains.some((pattern) => { return matchPattern(testUrl, pattern); }); } catch { return false; } } set setManifestData(newManifestData) { this.manifestData = newManifestData; this.#router = this.createRouter(this.manifestData); } removeBase(pathname) { pathname = collapseDuplicateLeadingSlashes(pathname); if (pathname.startsWith(this.manifest.base)) { return pathname.slice(this.baseWithoutTrailingSlash.length + 1); } return pathname; } /** * It removes the base from the request URL, prepends it with a forward slash and attempts to decoded it. * * If the decoding fails, it logs the error and return the pathname as is. * @param request */ getPathnameFromRequest(request) { const url = new URL(request.url); const pathname = prependForwardSlash(this.removeBase(url.pathname)); try { return decodeURI(pathname); } catch (e) { this.getAdapterLogger().error(e.toString()); return pathname; } } /** * Given a `Request`, it returns the `RouteData` that matches its `pathname`. By default, prerendered * routes aren't returned, even if they are matched. * * When `allowPrerenderedRoutes` is `true`, the function returns matched prerendered routes too. * @param request * @param allowPrerenderedRoutes */ match(request, allowPrerenderedRoutes = false) { const url = new URL(request.url); if (this.manifest.assets.has(url.pathname)) return void 0; let pathname = this.computePathnameFromDomain(request); if (!pathname) { pathname = prependForwardSlash(this.removeBase(url.pathname)); } const match = this.#router.match(decodeURI(pathname), { allowWithoutBase: true }); if (match.type !== "match") return void 0; const routeData = match.route; if (allowPrerenderedRoutes) { return routeData; } else if (routeData.prerender) { return void 0; } return routeData; } createRouter(manifestData) { return new Router(manifestData.routes, { base: this.manifest.base, trailingSlash: this.manifest.trailingSlash, buildFormat: this.manifest.buildFormat }); } /** * A matching route function to use in the development server. * Contrary to the `.match` function, this function resolves props and params, returning the correct * route based on the priority, segments. It also returns the correct, resolved pathname. * @param pathname */ devMatch(pathname) { return void 0; } computePathnameFromDomain(request) { let pathname = void 0; const url = new URL(request.url); 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")) { let host = request.headers.get("X-Forwarded-Host"); let protocol = request.headers.get("X-Forwarded-Proto"); if (protocol) { protocol = protocol + ":"; } else { protocol = url.protocol; } if (!host) { host = request.headers.get("Host"); } if (host && protocol) { host = host.split(":")[0]; try { let locale; const hostAsUrl = new URL(`${protocol}//${host}`); for (const [domainKey, localeValue] of Object.entries( this.manifest.i18n.domainLookupTable )) { const domainKeyAsUrl = new URL(domainKey); if (hostAsUrl.host === domainKeyAsUrl.host && hostAsUrl.protocol === domainKeyAsUrl.protocol) { locale = localeValue; break; } } if (locale) { pathname = prependForwardSlash( joinPaths(normalizeTheLocale(locale), this.removeBase(url.pathname)) ); if (this.manifest.trailingSlash === "always") { pathname = appendForwardSlash(pathname); } else if (this.manifest.trailingSlash === "never") { pathname = removeTrailingForwardSlash(pathname); } else if (url.pathname.endsWith("/")) { pathname = appendForwardSlash(pathname); } } } catch (e) { this.logger.error( "router", `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.` ); this.logger.error("router", `Error: ${e}`); } } } return pathname; } redirectTrailingSlash(pathname) { const { trailingSlash } = this.manifest; if (pathname === "/" || isInternalPath(pathname)) { return pathname; } const path = collapseDuplicateTrailingSlashes(pathname, trailingSlash !== "never"); if (path !== pathname) { return path; } if (trailingSlash === "ignore") { return pathname; } if (trailingSlash === "always" && !hasFileExtension(pathname)) { return appendForwardSlash(pathname); } if (trailingSlash === "never") { return removeTrailingForwardSlash(pathname); } return pathname; } async render(request, { addCookieHeader = false, clientAddress = Reflect.get(request, clientAddressSymbol), locals, prerenderedErrorPageFetch = fetch, routeData, waitUntil } = {}) { await this.pipeline.getLogger(); const timeStart = performance.now(); const url = new URL(request.url); const redirect = this.redirectTrailingSlash(url.pathname); if (redirect !== url.pathname) { const status = request.method === "GET" ? 301 : 308; const response2 = new Response( redirectTemplate({ status, relativeLocation: url.pathname, absoluteLocation: redirect, from: request.url }), { status, headers: { location: redirect + url.search } } ); this.#prepareResponse(response2, { addCookieHeader }); return response2; } if (routeData) { this.logger.debug( "router", "The adapter " + this.manifest.adapterName + " provided a custom RouteData for ", request.url ); this.logger.debug("router", "RouteData"); this.logger.debug("router", routeData); } const resolvedRenderOptions = { addCookieHeader, clientAddress, prerenderedErrorPageFetch, locals, routeData, waitUntil }; if (locals) { if (typeof locals !== "object") { const error = new AstroError(LocalsNotAnObject); this.logger.error(null, error.stack); return this.renderError(request, { ...resolvedRenderOptions, // If locals are invalid, we don't want to include them when // rendering the error page locals: void 0, status: 500, error }); } } if (!routeData) { if (this.isDev()) { const result = await this.devMatch(this.getPathnameFromRequest(request)); if (result) { routeData = result.routeData; } } else { routeData = this.match(request); } this.logger.debug("router", "Astro matched the following route for " + request.url); this.logger.debug("router", "RouteData:\n" + routeData); } if (!routeData) { routeData = this.manifestData.routes.find( (route) => route.component === "404.astro" || route.component === DEFAULT_404_COMPONENT ); } if (!routeData) { this.logger.debug("router", "Astro hasn't found routes that match " + request.url); this.logger.debug("router", "Here's the available routes:\n", this.manifestData); return this.renderError(request, { ...resolvedRenderOptions, status: 404 }); } let pathname = this.getPathnameFromRequest(request); if (this.isDev() && !routeHasHtmlExtension(routeData)) { pathname = pathname.replace(/\/index\.html$/, "/").replace(/\.html$/, ""); } const defaultStatus = this.getDefaultStatusCode(routeData, pathname); let response; let session; let cache; try { const componentInstance = await this.pipeline.getComponentByRoute(routeData); const renderContext = await this.createRenderContext({ pipeline: this.pipeline, locals, pathname, request, routeData, status: defaultStatus, clientAddress }); session = renderContext.session; cache = renderContext.cache; if (this.pipeline.cacheProvider) { const cacheProvider = await this.pipeline.getCacheProvider(); if (cacheProvider?.onRequest) { response = await cacheProvider.onRequest( { request, url: new URL(request.url), waitUntil: resolvedRenderOptions.waitUntil }, async () => { const res = await renderContext.render(componentInstance); applyCacheHeaders(cache, res); return res; } ); response.headers.delete("CDN-Cache-Control"); response.headers.delete("Cache-Tag"); } else { response = await renderContext.render(componentInstance); applyCacheHeaders(cache, response); } } else { response = await renderContext.render(componentInstance); } const isRewrite = response.headers.has(REWRITE_DIRECTIVE_HEADER_KEY); this.logThisRequest({ pathname, method: request.method, statusCode: response.status, isRewrite, timeStart }); } catch (err) { this.logger.error(null, err.stack || err.message || String(err)); return this.renderError(request, { ...resolvedRenderOptions, status: 500, error: err }); } finally { await session?.[PERSIST_SYMBOL](); } if (REROUTABLE_STATUS_CODES.includes(response.status) && // If the body isn't null, that means the user sets the 404 status // but uses the current route to handle the 404 response.body === null && response.headers.get(REROUTE_DIRECTIVE_HEADER) !== "no") { return this.renderError(request, { ...resolvedRenderOptions, response, status: response.status, // We don't have an error to report here. Passing null means we pass nothing intentionally // while undefined means there's no error error: response.status === 500 ? null : void 0 }); } this.#prepareResponse(response, { addCookieHeader }); return response; } #prepareResponse(response, { addCookieHeader }) { for (const headerName of [ REROUTE_DIRECTIVE_HEADER, REWRITE_DIRECTIVE_HEADER_KEY, NOOP_MIDDLEWARE_HEADER, ROUTE_TYPE_HEADER ]) { if (response.headers.has(headerName)) { response.headers.delete(headerName); } } if (addCookieHeader) { for (const setCookieHeaderValue of getSetCookiesFromResponse(response)) { response.headers.append("set-cookie", setCookieHeaderValue); } } this.logger.flush(); Reflect.set(response, responseSentSymbol$1, true); } setCookieHeaders(response) { return getSetCookiesFromResponse(response); } /** * Reads all the cookies written by `Astro.cookie.set()` onto the passed response. * For example, * ```ts * for (const cookie_ of App.getSetCookieFromResponse(response)) { * const cookie: string = cookie_ * } * ``` * @param response The response to read cookies from. * @returns An iterator that yields key-value pairs as equal-sign-separated strings. */ static getSetCookieFromResponse = getSetCookiesFromResponse; /** * If it is a known error code, try sending the according page (e.g. 404.astro / 500.astro). * This also handles pre-rendered /404 or /500 routes */ async renderError(request, { status, response: originalResponse, skipMiddleware = false, error, ...resolvedRenderOptions }) { const errorRoutePath = `/${status}${this.manifest.trailingSlash === "always" ? "/" : ""}`; const errorRouteData = matchRoute(errorRoutePath, this.manifestData); const url = new URL(request.url); if (errorRouteData) { if (errorRouteData.prerender) { const maybeDotHtml = errorRouteData.route.endsWith(`/${status}`) ? ".html" : ""; const statusURL = new URL(`${this.baseWithoutTrailingSlash}/${status}${maybeDotHtml}`, url); if (statusURL.toString() !== request.url && resolvedRenderOptions.prerenderedErrorPageFetch) { const response2 = await resolvedRenderOptions.prerenderedErrorPageFetch( statusURL.toString() ); const override = { status, removeContentEncodingHeaders: true }; const newResponse = this.mergeResponses(response2, originalResponse, override); this.#prepareResponse(newResponse, resolvedRenderOptions); return newResponse; } } const mod = await this.pipeline.getComponentByRoute(errorRouteData); let session; try { const renderContext = await this.createRenderContext({ locals: resolvedRenderOptions.locals, pipeline: this.pipeline, skipMiddleware, pathname: this.getPathnameFromRequest(request), request, routeData: errorRouteData, status, props: { error }, clientAddress: resolvedRenderOptions.clientAddress }); session = renderContext.session; const response2 = await renderContext.render(mod); const newResponse = this.mergeResponses(response2, originalResponse); this.#prepareResponse(newResponse, resolvedRenderOptions); return newResponse; } catch { if (skipMiddleware === false) { return this.renderError(request, { ...resolvedRenderOptions, status, response: originalResponse, skipMiddleware: true }); } } finally { await session?.[PERSIST_SYMBOL](); } } const response = this.mergeResponses(new Response(null, { status }), originalResponse); this.#prepareResponse(response, resolvedRenderOptions); return response; } mergeResponses(newResponse, originalResponse, override) { let newResponseHeaders = newResponse.headers; if (override?.removeContentEncodingHeaders) { newResponseHeaders = new Headers(newResponseHeaders); newResponseHeaders.delete("Content-Encoding"); newResponseHeaders.delete("Content-Length"); } if (!originalResponse) { if (override !== void 0) { return new Response(newResponse.body, { status: override.status, statusText: newResponse.statusText, headers: newResponseHeaders }); } return newResponse; } const status = override?.status ? override.status : originalResponse.status === 200 ? newResponse.status : originalResponse.status; try { originalResponse.headers.delete("Content-type"); originalResponse.headers.delete("Content-Length"); originalResponse.headers.delete("Transfer-Encoding"); } catch { } const newHeaders = new Headers(); const seen = /* @__PURE__ */ new Set(); for (const [name, value] of originalResponse.headers) { newHeaders.append(name, value); seen.add(name.toLowerCase()); } for (const [name, value] of newResponseHeaders) { if (!seen.has(name.toLowerCase())) { newHeaders.append(name, value); } } const mergedResponse = new Response(newResponse.body, { status, statusText: status === 200 ? newResponse.statusText : originalResponse.statusText, // If you're looking at here for possible bugs, it means that it's not a bug. // With the middleware, users can meddle with headers, and we should pass to the 404/500. // If users see something weird, it's because they are setting some headers they should not. // // Although, we don't want it to replace the content-type, because the error page must return `text/html` headers: newHeaders }); const originalCookies = getCookiesFromResponse(originalResponse); const newCookies = getCookiesFromResponse(newResponse); if (originalCookies) { if (newCookies) { for (const cookieValue of AstroCookies.consume(newCookies)) { originalResponse.headers.append("set-cookie", cookieValue); } } attachCookiesToResponse(mergedResponse, originalCookies); } else if (newCookies) { attachCookiesToResponse(mergedResponse, newCookies); } return mergedResponse; } getDefaultStatusCode(routeData, pathname) { if (!routeData.pattern.test(pathname)) { for (const fallbackRoute of routeData.fallbackRoutes) { if (fallbackRoute.pattern.test(pathname)) { return 302; } } } const route = removeTrailingForwardSlash(routeData.route); if (route.endsWith("/404")) return 404; if (route.endsWith("/500")) return 500; return 200; } getManifest() { return this.pipeline.manifest; } logThisRequest({ pathname, method, statusCode, isRewrite, timeStart }) { const timeEnd = performance.now(); this.logRequest({ pathname, method, statusCode, isRewrite, reqTime: timeEnd - timeStart }); } } function getAssetsPrefix(fileExtension, assetsPrefix) { let prefix = ""; if (!assetsPrefix) { prefix = ""; } else if (typeof assetsPrefix === "string") { prefix = assetsPrefix; } else { const dotLessFileExtension = fileExtension.slice(1); prefix = assetsPrefix[dotLessFileExtension] || assetsPrefix.fallback; } return prefix; } const URL_PARSE_BASE = "https://astro.build"; function splitAssetPath(path) { const parsed = new URL(path, URL_PARSE_BASE); const isAbsolute = URL.canParse(path); const pathname = !isAbsolute && !path.startsWith("/") ? parsed.pathname.slice(1) : parsed.pathname; return { pathname, suffix: `${parsed.search}${parsed.hash}` }; } function createAssetLink(href, base, assetsPrefix, queryParams) { const { pathname, suffix } = splitAssetPath(href); let url = ""; if (assetsPrefix) { const pf = getAssetsPrefix(fileExtension(pathname), assetsPrefix); url = joinPaths(pf, slash(pathname)) + suffix; } else if (base) { url = prependForwardSlash(joinPaths(base, slash(pathname))) + suffix; } else { url = href; } return url; } function createStylesheetElement(stylesheet, base, assetsPrefix, queryParams) { if (stylesheet.type === "inline") { return { props: {}, children: stylesheet.content }; } else { return { props: { rel: "stylesheet", href: createAssetLink(stylesheet.src, base, assetsPrefix) }, children: "" }; } } function createStylesheetElementSet(stylesheets, base, assetsPrefix, queryParams) { return new Set( stylesheets.map((s) => createStylesheetElement(s, base, assetsPrefix)) ); } const slotName = (str) => str.trim().replace(/[-_]([a-z])/g, (_, w) => w.toUpperCase()); async function check(Component, props, { default: children = null, ...slotted } = {}) { if (typeof Component !== "function") return false; const slots = {}; for (const [key, value] of Object.entries(slotted)) { const name = slotName(key); slots[name] = value; } try { const result = await Component({ ...props, ...slots, children }); return result[AstroJSX]; } catch (e) { throwEnhancedErrorIfMdxComponent(e, Component); } return false; } async function renderToStaticMarkup(Component, props = {}, { default: children = null, ...slotted } = {}) { const slots = {}; for (const [key, value] of Object.entries(slotted)) { const name = slotName(key); slots[name] = value; } const { result } = this; try { const html = await renderJSX(result, createVNode(Component, { ...props, ...slots, children })); return { html }; } catch (e) { throwEnhancedErrorIfMdxComponent(e, Component); throw e; } } function throwEnhancedErrorIfMdxComponent(error, Component) { if (Component[/* @__PURE__ */ Symbol.for("mdx-component")]) { if (AstroUserError.is(error)) return; error.title = error.name; error.hint = `This issue often occurs when your MDX component encounters runtime errors.`; throw error; } } const renderer = { name: "astro:jsx", check, renderToStaticMarkup }; var server_default = renderer; const renderers = [Object.assign({"name":"astro:jsx","serverEntrypoint":"file:///C:/Users/Harun/OneDrive/Desktop/my%20pc%20desktop/node_modules/@astrojs/mdx/dist/server.js"}, { ssr: server_default }),]; const serializedData = [{"file":"","links":[],"scripts":[],"styles":[],"routeData":{"type":"page","isIndex":false,"route":"/404","pattern":"^\\/404\\/?$","segments":[[{"content":"404","dynamic":false,"spread":false}]],"params":[],"component":"node_modules/@astrojs/starlight/routes/static/404.astro","pathname":"/404","prerender":true,"fallbackRoutes":[],"distURL":[],"origin":"external","_meta":{"trailingSlash":"ignore"}}},{"file":"","links":[],"scripts":[],"styles":[],"routeData":{"route":"/about","isIndex":false,"type":"page","pattern":"^\\/about\\/?$","segments":[[{"content":"about","dynamic":false,"spread":false}]],"params":[],"component":"src/pages/about.astro","pathname":"/about","prerender":true,"fallbackRoutes":[],"distURL":[],"origin":"project","_meta":{"trailingSlash":"ignore"}}},{"file":"","links":[],"scripts":[],"styles":[],"routeData":{"route":"/articles/[slug]","isIndex":false,"type":"page","pattern":"^\\/articles\\/([^/]+?)\\/?$","segments":[[{"content":"articles","dynamic":false,"spread":false}],[{"content":"slug","dynamic":true,"spread":false}]],"params":["slug"],"component":"src/pages/articles/[slug].astro","prerender":true,"fallbackRoutes":[],"distURL":[],"origin":"project","_meta":{"trailingSlash":"ignore"}}},{"file":"","links":[],"scripts":[],"styles":[],"routeData":{"route":"/articles","isIndex":true,"type":"page","pattern":"^\\/articles\\/?$","segments":[[{"content":"articles","dynamic":false,"spread":false}]],"params":[],"component":"src/pages/articles/index.astro","pathname":"/articles","prerender":true,"fallbackRoutes":[],"distURL":[],"origin":"project","_meta":{"trailingSlash":"ignore"}}},{"file":"","links":[],"scripts":[],"styles":[],"routeData":{"route":"/contact","isIndex":false,"type":"page","pattern":"^\\/contact\\/?$","segments":[[{"content":"contact","dynamic":false,"spread":false}]],"params":[],"component":"src/pages/contact.astro","pathname":"/contact","prerender":true,"fallbackRoutes":[],"distURL":[],"origin":"project","_meta":{"trailingSlash":"ignore"}}},{"file":"","links":[],"scripts":[],"styles":[],"routeData":{"route":"/","isIndex":true,"type":"page","pattern":"^\\/$","segments":[],"params":[],"component":"src/pages/index.astro","pathname":"/","prerender":true,"fallbackRoutes":[],"distURL":[],"origin":"project","_meta":{"trailingSlash":"ignore"}}},{"file":"","links":[],"scripts":[],"styles":[],"routeData":{"type":"page","isIndex":false,"route":"/[...slug]","pattern":"^(?:\\/(.*?))?\\/?$","segments":[[{"content":"...slug","dynamic":true,"spread":true}]],"params":["...slug"],"component":"node_modules/@astrojs/starlight/routes/static/index.astro","prerender":true,"fallbackRoutes":[],"distURL":[],"origin":"external","_meta":{"trailingSlash":"ignore"}}}]; serializedData.map(deserializeRouteInfo); const _page0 = () => import('./404_BN0AmpT8.mjs'); const _page1 = () => import('./about_mO09-rr8.mjs'); const _page2 = () => import('./_slug__FNaN52r3.mjs'); const _page3 = () => import('./index_D9IeIxh-.mjs'); const _page4 = () => import('./contact_CBxMxonn.mjs'); const _page5 = () => import('./index_Nguhw-YR.mjs'); const _page6 = () => import('./index_DkAZzI2h.mjs'); const pageMap = new Map([ ["node_modules/@astrojs/starlight/routes/static/404.astro", _page0], ["src/pages/about.astro", _page1], ["src/pages/articles/[slug].astro", _page2], ["src/pages/articles/index.astro", _page3], ["src/pages/contact.astro", _page4], ["src/pages/index.astro", _page5], ["node_modules/@astrojs/starlight/routes/static/index.astro", _page6] ]); const _manifest = deserializeManifest(({"rootDir":"file:///C:/Users/Harun/OneDrive/Desktop/my%20pc%20desktop/","cacheDir":"file:///C:/Users/Harun/OneDrive/Desktop/my%20pc%20desktop/node_modules/.astro/","outDir":"file:///C:/Users/Harun/OneDrive/Desktop/my%20pc%20desktop/dist/","srcDir":"file:///C:/Users/Harun/OneDrive/Desktop/my%20pc%20desktop/src/","publicDir":"file:///C:/Users/Harun/OneDrive/Desktop/my%20pc%20desktop/public/","buildClientDir":"file:///C:/Users/Harun/OneDrive/Desktop/my%20pc%20desktop/dist/client/","buildServerDir":"file:///C:/Users/Harun/OneDrive/Desktop/my%20pc%20desktop/dist/server/","adapterName":"","assetsDir":"_astro","routes":[{"file":"","links":[],"scripts":[{"type":"external","value":"_astro/page.BIhdncjw.js"}],"styles":[{"type":"external","src":"_astro/common.DzFF2Dhy.css"},{"type":"external","src":"_astro/Code.BcHZMqfA.css"}],"routeData":{"type":"page","isIndex":false,"route":"/404","pattern":"^\\/404\\/?$","segments":[[{"content":"404","dynamic":false,"spread":false}]],"params":[],"component":"node_modules/@astrojs/starlight/routes/static/404.astro","pathname":"/404","prerender":true,"fallbackRoutes":[],"distURL":[],"origin":"external","_meta":{"trailingSlash":"ignore"}}},{"file":"","links":[],"scripts":[{"type":"external","value":"_astro/page.BIhdncjw.js"}],"styles":[{"type":"inline","content":"*{box-sizing:border-box}body{margin:0;font-family:system-ui,Arial,sans-serif;line-height:1.6;color:#111827;background:#fff}a{color:#0369a1;text-decoration:none}img{max-width:100%;height:auto}.site-header{display:flex;justify-content:space-between;align-items:center;padding:16px 24px;border-bottom:1px solid #e5e7eb}.logo{font-weight:700;font-size:22px}nav{display:flex;gap:16px}main{max-width:1100px;margin:0 auto;padding:32px 24px}.site-footer{padding:24px;border-top:1px solid #e5e7eb;text-align:center}\n"}],"routeData":{"route":"/about","isIndex":false,"type":"page","pattern":"^\\/about\\/?$","segments":[[{"content":"about","dynamic":false,"spread":false}]],"params":[],"component":"src/pages/about.astro","pathname":"/about","prerender":true,"fallbackRoutes":[],"distURL":[],"origin":"project","_meta":{"trailingSlash":"ignore"}}},{"file":"","links":[],"scripts":[{"type":"external","value":"_astro/page.BIhdncjw.js"}],"styles":[{"type":"inline","content":"*{box-sizing:border-box}body{margin:0;font-family:system-ui,Arial,sans-serif;line-height:1.6;color:#111827;background:#fff}a{color:#0369a1;text-decoration:none}img{max-width:100%;height:auto}.site-header{display:flex;justify-content:space-between;align-items:center;padding:16px 24px;border-bottom:1px solid #e5e7eb}.logo{font-weight:700;font-size:22px}nav{display:flex;gap:16px}main{max-width:1100px;margin:0 auto;padding:32px 24px}.site-footer{padding:24px;border-top:1px solid #e5e7eb;text-align:center}\n"}],"routeData":{"route":"/articles/[slug]","isIndex":false,"type":"page","pattern":"^\\/articles\\/([^/]+?)\\/?$","segments":[[{"content":"articles","dynamic":false,"spread":false}],[{"content":"slug","dynamic":true,"spread":false}]],"params":["slug"],"component":"src/pages/articles/[slug].astro","prerender":true,"fallbackRoutes":[],"distURL":[],"origin":"project","_meta":{"trailingSlash":"ignore"}}},{"file":"","links":[],"scripts":[{"type":"external","value":"_astro/page.BIhdncjw.js"}],"styles":[{"type":"inline","content":"*{box-sizing:border-box}body{margin:0;font-family:system-ui,Arial,sans-serif;line-height:1.6;color:#111827;background:#fff}a{color:#0369a1;text-decoration:none}img{max-width:100%;height:auto}.site-header{display:flex;justify-content:space-between;align-items:center;padding:16px 24px;border-bottom:1px solid #e5e7eb}.logo{font-weight:700;font-size:22px}nav{display:flex;gap:16px}main{max-width:1100px;margin:0 auto;padding:32px 24px}.site-footer{padding:24px;border-top:1px solid #e5e7eb;text-align:center}\n.article-card:where(.astro-di2nlc57){padding:20px;border:1px solid #e5e7eb;border-radius:12px;margin-bottom:16px}.article-card:where(.astro-di2nlc57) h2:where(.astro-di2nlc57){margin-top:0}\n"}],"routeData":{"route":"/articles","isIndex":true,"type":"page","pattern":"^\\/articles\\/?$","segments":[[{"content":"articles","dynamic":false,"spread":false}]],"params":[],"component":"src/pages/articles/index.astro","pathname":"/articles","prerender":true,"fallbackRoutes":[],"distURL":[],"origin":"project","_meta":{"trailingSlash":"ignore"}}},{"file":"","links":[],"scripts":[{"type":"external","value":"_astro/page.BIhdncjw.js"}],"styles":[{"type":"inline","content":"*{box-sizing:border-box}body{margin:0;font-family:system-ui,Arial,sans-serif;line-height:1.6;color:#111827;background:#fff}a{color:#0369a1;text-decoration:none}img{max-width:100%;height:auto}.site-header{display:flex;justify-content:space-between;align-items:center;padding:16px 24px;border-bottom:1px solid #e5e7eb}.logo{font-weight:700;font-size:22px}nav{display:flex;gap:16px}main{max-width:1100px;margin:0 auto;padding:32px 24px}.site-footer{padding:24px;border-top:1px solid #e5e7eb;text-align:center}\n"}],"routeData":{"route":"/contact","isIndex":false,"type":"page","pattern":"^\\/contact\\/?$","segments":[[{"content":"contact","dynamic":false,"spread":false}]],"params":[],"component":"src/pages/contact.astro","pathname":"/contact","prerender":true,"fallbackRoutes":[],"distURL":[],"origin":"project","_meta":{"trailingSlash":"ignore"}}},{"file":"","links":[],"scripts":[{"type":"external","value":"_astro/page.BIhdncjw.js"}],"styles":[{"type":"inline","content":"*{box-sizing:border-box}body{margin:0;font-family:system-ui,Arial,sans-serif;line-height:1.6;color:#111827;background:#fff}a{color:#0369a1;text-decoration:none}img{max-width:100%;height:auto}.site-header{display:flex;justify-content:space-between;align-items:center;padding:16px 24px;border-bottom:1px solid #e5e7eb}.logo{font-weight:700;font-size:22px}nav{display:flex;gap:16px}main{max-width:1100px;margin:0 auto;padding:32px 24px}.site-footer{padding:24px;border-top:1px solid #e5e7eb;text-align:center}\n"}],"routeData":{"route":"/","isIndex":true,"type":"page","pattern":"^\\/$","segments":[],"params":[],"component":"src/pages/index.astro","pathname":"/","prerender":true,"fallbackRoutes":[],"distURL":[],"origin":"project","_meta":{"trailingSlash":"ignore"}}},{"file":"","links":[],"scripts":[{"type":"external","value":"_astro/page.BIhdncjw.js"}],"styles":[{"type":"external","src":"_astro/common.DzFF2Dhy.css"},{"type":"external","src":"_astro/Code.BcHZMqfA.css"}],"routeData":{"type":"page","isIndex":false,"route":"/[...slug]","pattern":"^(?:\\/(.*?))?\\/?$","segments":[[{"content":"...slug","dynamic":true,"spread":true}]],"params":["...slug"],"component":"node_modules/@astrojs/starlight/routes/static/index.astro","prerender":true,"fallbackRoutes":[],"distURL":[],"origin":"external","_meta":{"trailingSlash":"ignore"}}}],"serverLike":false,"middlewareMode":"classic","base":"/","trailingSlash":"ignore","compressHTML":true,"experimentalQueuedRendering":{"enabled":false,"poolSize":0,"contentCache":false},"componentMetadata":[["C:/Users/Harun/OneDrive/Desktop/my pc desktop/src/pages/about.astro",{"propagation":"none","containsHead":true}],["C:/Users/Harun/OneDrive/Desktop/my pc desktop/src/pages/articles/[slug].astro",{"propagation":"none","containsHead":true}],["C:/Users/Harun/OneDrive/Desktop/my pc desktop/src/pages/articles/index.astro",{"propagation":"none","containsHead":true}],["C:/Users/Harun/OneDrive/Desktop/my pc desktop/src/pages/contact.astro",{"propagation":"none","containsHead":true}],["C:/Users/Harun/OneDrive/Desktop/my pc desktop/src/pages/index.astro",{"propagation":"none","containsHead":true}],["C:/Users/Harun/OneDrive/Desktop/my pc desktop/node_modules/@astrojs/starlight/routes/static/404.astro",{"propagation":"in-tree","containsHead":true}],["C:/Users/Harun/OneDrive/Desktop/my pc desktop/node_modules/@astrojs/starlight/routes/static/index.astro",{"propagation":"in-tree","containsHead":true}],["\u0000astro:content",{"propagation":"in-tree","containsHead":false}],["C:/Users/Harun/OneDrive/Desktop/my pc desktop/node_modules/@astrojs/starlight/routes/common.astro",{"propagation":"in-tree","containsHead":false}],["\u0000virtual:astro:page:node_modules/@astrojs/starlight/routes/static/404@_@astro",{"propagation":"in-tree","containsHead":false}],["\u0000virtual:astro:pages",{"propagation":"in-tree","containsHead":false}],["\u0000virtual:astro:manifest",{"propagation":"in-tree","containsHead":false}],["C:/Users/Harun/OneDrive/Desktop/my pc desktop/node_modules/astro/dist/entrypoints/prerender.js",{"propagation":"in-tree","containsHead":false}],["\u0000virtual:astro:page:node_modules/@astrojs/starlight/routes/static/index@_@astro",{"propagation":"in-tree","containsHead":false}],["C:/Users/Harun/OneDrive/Desktop/my pc desktop/node_modules/@astrojs/starlight/utils/routing/data.ts",{"propagation":"in-tree","containsHead":false}],["C:/Users/Harun/OneDrive/Desktop/my pc desktop/node_modules/@astrojs/starlight/utils/routing/index.ts",{"propagation":"in-tree","containsHead":false}],["C:/Users/Harun/OneDrive/Desktop/my pc desktop/node_modules/@astrojs/starlight/utils/navigation.ts",{"propagation":"in-tree","containsHead":false}],["C:/Users/Harun/OneDrive/Desktop/my pc desktop/node_modules/@astrojs/starlight/components/SidebarPersister.astro",{"propagation":"in-tree","containsHead":false}],["C:/Users/Harun/OneDrive/Desktop/my pc desktop/node_modules/@astrojs/starlight/components/Sidebar.astro",{"propagation":"in-tree","containsHead":false}],["\u0000virtual:starlight/components/Sidebar",{"propagation":"in-tree","containsHead":false}],["C:/Users/Harun/OneDrive/Desktop/my pc desktop/node_modules/@astrojs/starlight/components/SidebarSublist.astro",{"propagation":"in-tree","containsHead":false}],["C:/Users/Harun/OneDrive/Desktop/my pc desktop/node_modules/@astrojs/starlight/utils/translations.ts",{"propagation":"in-tree","containsHead":false}],["C:/Users/Harun/OneDrive/Desktop/my pc desktop/node_modules/@astrojs/starlight/internal.ts",{"propagation":"in-tree","containsHead":false}],["C:/Users/Harun/OneDrive/Desktop/my pc desktop/node_modules/@astrojs/starlight/locals.ts",{"propagation":"in-tree","containsHead":false}],["\u0000virtual:astro:middleware",{"propagation":"in-tree","containsHead":false}]],"renderers":[],"clientDirectives":[["idle","(()=>{var l=(n,t)=>{let i=async()=>{await(await n())()},e=typeof t.value==\"object\"?t.value:void 0,s={timeout:e==null?void 0:e.timeout};\"requestIdleCallback\"in window?window.requestIdleCallback(i,s):setTimeout(i,s.timeout||200)};(self.Astro||(self.Astro={})).idle=l;window.dispatchEvent(new Event(\"astro:idle\"));})();"],["load","(()=>{var e=async t=>{await(await t())()};(self.Astro||(self.Astro={})).load=e;window.dispatchEvent(new Event(\"astro:load\"));})();"],["media","(()=>{var n=(a,t)=>{let i=async()=>{await(await a())()};if(t.value){let e=matchMedia(t.value);e.matches?i():e.addEventListener(\"change\",i,{once:!0})}};(self.Astro||(self.Astro={})).media=n;window.dispatchEvent(new Event(\"astro:media\"));})();"],["only","(()=>{var e=async t=>{await(await t())()};(self.Astro||(self.Astro={})).only=e;window.dispatchEvent(new Event(\"astro:only\"));})();"],["visible","(()=>{var a=(s,i,o)=>{let r=async()=>{await(await s())()},t=typeof i.value==\"object\"?i.value:void 0,c={rootMargin:t==null?void 0:t.rootMargin},n=new IntersectionObserver(e=>{for(let l of e)if(l.isIntersecting){n.disconnect(),r();break}},c);for(let e of o.children)n.observe(e)};(self.Astro||(self.Astro={})).visible=a;window.dispatchEvent(new Event(\"astro:visible\"));})();"]],"entryModules":{"\u0000virtual:astro:actions/noop-entrypoint":"chunks/noop-entrypoint_BOlrdqWF.mjs","\u0000virtual:astro:middleware":"chunks/_virtual_astro_middleware_BNm4SpGT.mjs","\u0000virtual:astro:session-driver":"chunks/_virtual_astro_session-driver_DYx9Bb3p.mjs","\u0000virtual:astro:server-island-manifest":"chunks/_virtual_astro_server-island-manifest_CQQ1F5PF.mjs","\u0000virtual:astro:page:node_modules/@astrojs/starlight/routes/static/404@_@astro":"chunks/404_BN0AmpT8.mjs","\u0000virtual:astro:page:src/pages/about@_@astro":"chunks/about_mO09-rr8.mjs","\u0000virtual:astro:page:src/pages/articles/[slug]@_@astro":"chunks/_slug__FNaN52r3.mjs","\u0000virtual:astro:page:src/pages/articles/index@_@astro":"chunks/index_D9IeIxh-.mjs","\u0000virtual:astro:page:src/pages/contact@_@astro":"chunks/contact_CBxMxonn.mjs","\u0000virtual:astro:page:src/pages/index@_@astro":"chunks/index_Nguhw-YR.mjs","\u0000virtual:astro:page:node_modules/@astrojs/starlight/routes/static/index@_@astro":"chunks/index_DkAZzI2h.mjs","C:\\Users\\Harun\\OneDrive\\Desktop\\my pc desktop\\.astro\\content-assets.mjs":"chunks/content-assets_BAMCPLHh.mjs","\u0000virtual:astro:get-image":"chunks/_virtual_astro_get-image_B78SXbXJ.mjs","C:\\Users\\Harun\\OneDrive\\Desktop\\my pc desktop\\.astro\\content-modules.mjs":"chunks/content-modules_DWClcio9.mjs","\u0000astro:data-layer-content":"chunks/_astro_data-layer-content_Cmfc1iOE.mjs","\u0000virtual:astro-expressive-code/config":"chunks/config_JSx-82B-.mjs","C:/Users/Harun/OneDrive/Desktop/my pc desktop/node_modules/astro-expressive-code/dist/index.js":"chunks/index_BD-MIWs7.mjs","\u0000virtual:astro-expressive-code/preprocess-config":"chunks/preprocess-config_m1vAPKKt.mjs","C:/Users/Harun/OneDrive/Desktop/my pc desktop/node_modules/astro/dist/assets/services/sharp.js":"chunks/sharp_CRb0jIiB.mjs","C:/Users/Harun/OneDrive/Desktop/my pc desktop/src/content/docs/index.mdx?astroPropagatedAssets":"chunks/index_BnaSx3Et.mjs","\u0000virtual:astro-expressive-code/ec-config":"chunks/ec-config_CzTTOeiV.mjs","C:/Users/Harun/OneDrive/Desktop/my pc desktop/src/content/docs/index.mdx":"chunks/index_Bqt0Uj9X.mjs","astro/entrypoints/prerender":"prerender-entry.CEIvaNt8.mjs","C:/Users/Harun/OneDrive/Desktop/my pc desktop/node_modules/@astrojs/starlight/components/LanguageSelect.astro?astro&type=script&index=0&lang.ts":"_astro/LanguageSelect.astro_astro_type_script_index_0_lang.Ce-i7NLC.js","C:/Users/Harun/OneDrive/Desktop/my pc desktop/node_modules/@astrojs/starlight/components/MobileMenuToggle.astro?astro&type=script&index=0&lang.ts":"_astro/MobileMenuToggle.astro_astro_type_script_index_0_lang.CsfLbggW.js","C:/Users/Harun/OneDrive/Desktop/my pc desktop/node_modules/@astrojs/starlight/components/MobileTableOfContents.astro?astro&type=script&index=0&lang.ts":"_astro/MobileTableOfContents.astro_astro_type_script_index_0_lang.hwBsy0Mo.js","C:/Users/Harun/OneDrive/Desktop/my pc desktop/node_modules/@astrojs/starlight/components/Page.astro?astro&type=script&index=0&lang.ts":"_astro/Page.astro_astro_type_script_index_0_lang.BHQeG8Vj.js","C:/Users/Harun/OneDrive/Desktop/my pc desktop/node_modules/@astrojs/starlight/components/ThemeSelect.astro?astro&type=script&index=0&lang.ts":"_astro/ThemeSelect.astro_astro_type_script_index_0_lang.Znk7Hhgg.js","C:/Users/Harun/OneDrive/Desktop/my pc desktop/node_modules/@astrojs/starlight/user-components/Tabs.astro?astro&type=script&index=0&lang.ts":"_astro/Tabs.astro_astro_type_script_index_0_lang._fLr8MwR.js","C:/Users/Harun/OneDrive/Desktop/my pc desktop/node_modules/@pagefind/default-ui/npm_dist/mjs/ui-core.mjs":"_astro/ui-core.D2oRCWSx.js","C:/Users/Harun/OneDrive/Desktop/my pc desktop/node_modules/@astrojs/starlight/components/Search.astro?astro&type=script&index=0&lang.ts":"_astro/Search.astro_astro_type_script_index_0_lang.Rw77DzG6.js","astro:scripts/page.js":"_astro/page.BIhdncjw.js","C:/Users/Harun/OneDrive/Desktop/my pc desktop/node_modules/@astrojs/starlight/components/TableOfContents.astro?astro&type=script&index=0&lang.ts":"_astro/TableOfContents.astro_astro_type_script_index_0_lang.FuRcXuRY.js","astro:scripts/before-hydration.js":""},"inlinedScripts":[["C:/Users/Harun/OneDrive/Desktop/my pc desktop/node_modules/@astrojs/starlight/components/LanguageSelect.astro?astro&type=script&index=0&lang.ts","class s extends HTMLElement{constructor(){super();const e=this.querySelector(\"select\");e&&(e.addEventListener(\"change\",t=>{t.currentTarget instanceof HTMLSelectElement&&(window.location.pathname=t.currentTarget.value)}),window.addEventListener(\"pageshow\",t=>{if(!t.persisted)return;const n=e.querySelector(\"option[selected]\")?.index;n!==e.selectedIndex&&(e.selectedIndex=n??0)}))}}customElements.define(\"starlight-lang-select\",s);"],["C:/Users/Harun/OneDrive/Desktop/my pc desktop/node_modules/@astrojs/starlight/components/MobileMenuToggle.astro?astro&type=script&index=0&lang.ts","class s extends HTMLElement{constructor(){super(),this.btn=this.querySelector(\"button\"),this.btn.addEventListener(\"click\",()=>this.toggleExpanded());const t=this.closest(\"nav\");t&&t.addEventListener(\"keyup\",e=>this.closeOnEscape(e))}setExpanded(t){this.setAttribute(\"aria-expanded\",String(t)),document.body.toggleAttribute(\"data-mobile-menu-expanded\",t)}toggleExpanded(){this.setExpanded(this.getAttribute(\"aria-expanded\")!==\"true\")}closeOnEscape(t){t.code===\"Escape\"&&(this.setExpanded(!1),this.btn.focus())}}customElements.define(\"starlight-menu-button\",s);"],["C:/Users/Harun/OneDrive/Desktop/my pc desktop/node_modules/@astrojs/starlight/components/Page.astro?astro&type=script&index=0&lang.ts","const a=document.getElementById(\"starlight__sidebar\"),n=a?.querySelector(\"sl-sidebar-state-persist\"),o=\"sl-sidebar-state\",i=()=>{let t=[];const e=n?.dataset.hash||\"\";try{const s=sessionStorage.getItem(o),r=JSON.parse(s||\"{}\");Array.isArray(r.open)&&r.hash===e&&(t=r.open)}catch{}return{hash:e,open:t,scroll:a?.scrollTop||0}},c=t=>{try{sessionStorage.setItem(o,JSON.stringify(t))}catch{}},d=()=>c(i()),l=(t,e)=>{const s=i();s.open[e]=t,c(s)};n?.addEventListener(\"click\",t=>{if(!(t.target instanceof Element))return;const e=t.target.closest(\"summary\")?.closest(\"details\");if(!e)return;const s=e.querySelector(\"sl-sidebar-restore\"),r=parseInt(s?.dataset.index||\"\");isNaN(r)||l(!e.open,r)});addEventListener(\"visibilitychange\",()=>{document.visibilityState===\"hidden\"&&d()});addEventListener(\"pageHide\",d);"],["C:/Users/Harun/OneDrive/Desktop/my pc desktop/node_modules/@astrojs/starlight/components/ThemeSelect.astro?astro&type=script&index=0&lang.ts","const r=\"starlight-theme\",o=e=>e===\"auto\"||e===\"dark\"||e===\"light\"?e:\"auto\",c=()=>o(typeof localStorage<\"u\"&&localStorage.getItem(r));function n(e){typeof localStorage<\"u\"&&localStorage.setItem(r,e===\"light\"||e===\"dark\"?e:\"\")}const l=()=>matchMedia(\"(prefers-color-scheme: light)\").matches?\"light\":\"dark\";function t(e){StarlightThemeProvider.updatePickers(e),document.documentElement.dataset.theme=e===\"auto\"?l():e,n(e)}matchMedia(\"(prefers-color-scheme: light)\").addEventListener(\"change\",()=>{c()===\"auto\"&&t(\"auto\")});class s extends HTMLElement{constructor(){super(),t(c()),this.querySelector(\"select\")?.addEventListener(\"change\",a=>{a.currentTarget instanceof HTMLSelectElement&&t(o(a.currentTarget.value))})}}customElements.define(\"starlight-theme-select\",s);"],["C:/Users/Harun/OneDrive/Desktop/my pc desktop/node_modules/@astrojs/starlight/user-components/Tabs.astro?astro&type=script&index=0&lang.ts","class r extends HTMLElement{static#e=new Map;#t;#n=\"starlight-synced-tabs__\";constructor(){super();const t=this.querySelector('[role=\"tablist\"]');if(this.tabs=[...t.querySelectorAll('[role=\"tab\"]')],this.panels=[...this.querySelectorAll(':scope > [role=\"tabpanel\"]')],this.#t=this.dataset.syncKey,this.#t){const i=r.#e.get(this.#t)??[];i.push(this),r.#e.set(this.#t,i)}this.tabs.forEach((i,c)=>{i.addEventListener(\"click\",e=>{e.preventDefault();const n=t.querySelector('[aria-selected=\"true\"]');e.currentTarget!==n&&this.switchTab(e.currentTarget,c)}),i.addEventListener(\"keydown\",e=>{const n=this.tabs.indexOf(e.currentTarget),s=e.key===\"ArrowLeft\"?n-1:e.key===\"ArrowRight\"?n+1:e.key===\"Home\"?0:e.key===\"End\"?this.tabs.length-1:null;s!==null&&this.tabs[s]&&(e.preventDefault(),this.switchTab(this.tabs[s],s))})})}switchTab(t,i,c=!0){if(!t)return;const e=c?this.getBoundingClientRect().top:0;this.tabs.forEach(s=>{s.setAttribute(\"aria-selected\",\"false\"),s.setAttribute(\"tabindex\",\"-1\")}),this.panels.forEach(s=>{s.hidden=!0});const n=this.panels[i];n&&(n.hidden=!1),t.removeAttribute(\"tabindex\"),t.setAttribute(\"aria-selected\",\"true\"),c&&(t.focus(),r.#r(this,t),window.scrollTo({top:window.scrollY+(this.getBoundingClientRect().top-e),behavior:\"instant\"}))}#i(t){!this.#t||typeof localStorage>\"u\"||localStorage.setItem(this.#n+this.#t,t)}static#r(t,i){const c=t.#t,e=r.#s(i);if(!c||!e)return;const n=r.#e.get(c);if(n){for(const s of n){if(s===t)continue;const a=s.tabs.findIndex(o=>r.#s(o)===e);a!==-1&&s.switchTab(s.tabs[a],a,!1)}t.#i(e)}}static#s(t){return t.textContent?.trim()}}customElements.define(\"starlight-tabs\",r);"]],"assets":["/_astro/houston.CZZyCf7p.webp","/_astro/print.DNXP8c50.css","/_astro/Code.BcHZMqfA.css","/_astro/common.DzFF2Dhy.css","/_astro/page.BIhdncjw.js","/file:///C:/Users/Harun/OneDrive/Desktop/my%20pc%20desktop/dist/404.html","/file:///C:/Users/Harun/OneDrive/Desktop/my%20pc%20desktop/dist/about/index.html","/file:///C:/Users/Harun/OneDrive/Desktop/my%20pc%20desktop/dist/articles/index.html","/file:///C:/Users/Harun/OneDrive/Desktop/my%20pc%20desktop/dist/contact/index.html","/file:///C:/Users/Harun/OneDrive/Desktop/my%20pc%20desktop/dist/index.html"],"i18n":{"fallbackType":"redirect","strategy":"pathname-prefix-other-locales","locales":["en"],"defaultLocale":"en","domainLookupTable":{}},"buildFormat":"directory","checkOrigin":false,"actionBodySizeLimit":1048576,"serverIslandBodySizeLimit":1048576,"allowedDomains":[],"key":"TyguYO0+DRnDzg7O3qqi9RO/OY9hU/2mh8LmFs6Iue4=","image":{},"devToolbar":{"enabled":false,"debugInfoOutput":""},"logLevel":"info","shouldInjectCspMetaTags":false})); const manifestRoutes = _manifest.routes; const manifest = Object.assign(_manifest, { renderers, actions: () => import('./noop-entrypoint_BOlrdqWF.mjs'), middleware: () => import('./_virtual_astro_middleware_BNm4SpGT.mjs'), sessionDriver: () => import('./_virtual_astro_session-driver_DYx9Bb3p.mjs'), serverIslandMappings: () => import('./_virtual_astro_server-island-manifest_CQQ1F5PF.mjs'), routes: manifestRoutes, pageMap, }); const VIRTUAL_PAGE_MODULE_ID = "virtual:astro:page:"; const VIRTUAL_PAGE_RESOLVED_MODULE_ID = "\0" + VIRTUAL_PAGE_MODULE_ID; const ASTRO_PAGE_EXTENSION_POST_PATTERN = "@_@"; function getVirtualModulePageName(virtualModulePrefix, path) { const extension = fileExtension(path); return virtualModulePrefix + (extension.startsWith(".") ? path.slice(0, -extension.length) + extension.replace(".", ASTRO_PAGE_EXTENSION_POST_PATTERN) : path); } const SCRIPT_ID_PREFIX = `astro:scripts/`; const BEFORE_HYDRATION_SCRIPT_ID = `${SCRIPT_ID_PREFIX}${"before-hydration"}.js`; const PAGE_SCRIPT_ID = `${SCRIPT_ID_PREFIX}${"page"}.js`; const ASTRO_PAGE_KEY_SEPARATOR = "&"; function makePageDataKey(route, componentPath) { return route + ASTRO_PAGE_KEY_SEPARATOR + componentPath; } function getPageData(internals, route, component) { let pageData = internals.pagesByKeys.get(makePageDataKey(route, component)); if (pageData) { return pageData; } return void 0; } function cssOrder(a, b) { let depthA = a.depth, depthB = b.depth, orderA = a.order, orderB = b.order; if (orderA === -1 && orderB >= 0) { return 1; } else if (orderB === -1 && orderA >= 0) { return -1; } else if (orderA > orderB) { return 1; } else if (orderA < orderB) { return -1; } else { if (depthA === -1) { return -1; } else if (depthB === -1) { return 1; } else { return depthA > depthB ? -1 : 1; } } } function mergeInlineCss(acc, current) { const lastAdded = acc.at(acc.length - 1); const lastWasInline = lastAdded?.type === "inline"; const currentIsInline = current?.type === "inline"; if (lastWasInline && currentIsInline) { const merged = { type: "inline", content: lastAdded.content + current.content }; acc[acc.length - 1] = merged; return acc; } acc.push(current); return acc; } class BuildPipeline extends Pipeline { internals; options; manifest; defaultRoutes; getName() { return "BuildPipeline"; } /** * This cache is needed to map a single `RouteData` to its file path. * @private */ #routesByFilePath = /* @__PURE__ */ new WeakMap(); getSettings() { if (!this.options) { throw new Error("No options defined"); } return this.options.settings; } getOptions() { if (!this.options) { throw new Error("No options defined"); } return this.options; } getInternals() { if (!this.internals) { throw new Error("No internals defined"); } return this.internals; } constructor(manifest, defaultRoutes = createDefaultRoutes(manifest)) { const resolveCache = /* @__PURE__ */ new Map(); async function resolve(specifier) { if (resolveCache.has(specifier)) { return resolveCache.get(specifier); } const hashedFilePath = manifest.entryModules[specifier]; if (typeof hashedFilePath !== "string" || hashedFilePath === "") { if (specifier === BEFORE_HYDRATION_SCRIPT_ID) { resolveCache.set(specifier, ""); return ""; } throw new Error(`Cannot find the built path for ${specifier}`); } const assetLink = createAssetLink(hashedFilePath, manifest.base, manifest.assetsPrefix); resolveCache.set(specifier, assetLink); return assetLink; } const logger = createConsoleLogger({ level: manifest.logLevel }); super(logger, manifest, "production", manifest.renderers, resolve, manifest.serverLike); this.manifest = manifest; this.defaultRoutes = defaultRoutes; if (queueRenderingEnabled(this.manifest.experimentalQueuedRendering)) { this.nodePool = newNodePool(this.manifest.experimentalQueuedRendering); if (this.manifest.experimentalQueuedRendering.contentCache) { this.htmlStringCache = new HTMLStringCache(1e3); } } } getRoutes() { return this.getOptions().routesList.routes; } static create({ manifest }) { return new BuildPipeline(manifest); } setInternals(internals) { this.internals = internals; } setOptions(options) { this.options = options; } headElements(routeData) { const { manifest: { assetsPrefix, base } } = this; const settings = this.getSettings(); const internals = this.getInternals(); const links = /* @__PURE__ */ new Set(); const pageBuildData = getPageData(internals, routeData.route, routeData.component); const scripts = /* @__PURE__ */ new Set(); const sortedCssAssets = pageBuildData?.styles.sort(cssOrder).map(({ sheet }) => sheet).reduce(mergeInlineCss, []); const styles = createStylesheetElementSet(sortedCssAssets ?? [], base, assetsPrefix); if (settings.scripts.some((script) => script.stage === "page")) { const hashedFilePath = internals.entrySpecifierToBundleMap.get(PAGE_SCRIPT_ID); if (typeof hashedFilePath !== "string") { throw new Error(`Cannot find the built path for ${PAGE_SCRIPT_ID}`); } const src = createAssetLink(hashedFilePath, base, assetsPrefix); scripts.add({ props: { type: "module", src }, children: "" }); } for (const script of settings.scripts) { if (script.stage === "head-inline") { scripts.add({ props: {}, children: script.content }); } } return { scripts, styles, links }; } componentMetadata() { } /** * It collects the routes to generate during the build. * It returns a map of page information and their relative entry point as a string. */ retrieveRoutesToGenerate() { const pages = /* @__PURE__ */ new Set(); const defaultRouteComponents = new Set(this.defaultRoutes.map((route) => route.component)); for (const { routeData } of this.manifest.routes) { if (routeIsRedirect(routeData)) { pages.add(routeData); continue; } if (routeIsFallback(routeData) && i18nHasFallback(this.manifest)) { pages.add(routeData); continue; } if (defaultRouteComponents.has(routeData.component)) { continue; } pages.add(routeData); const moduleSpecifier = getVirtualModulePageName( VIRTUAL_PAGE_RESOLVED_MODULE_ID, routeData.component ); const filePath = this.internals?.entrySpecifierToBundleMap.get(moduleSpecifier); if (filePath) { this.#routesByFilePath.set(routeData, filePath); } } return pages; } async getComponentByRoute(routeData) { const module = await this.getModuleForRoute(routeData); return module.page(); } async getModuleForRoute(route) { for (const defaultRoute of this.defaultRoutes) { if (route.component === defaultRoute.component) { return { page: () => Promise.resolve(defaultRoute.instance) }; } } let routeToProcess = route; if (routeIsRedirect(route)) { if (route.redirectRoute) { routeToProcess = route.redirectRoute; } else { return RedirectSinglePageBuiltModule; } } else if (routeIsFallback(route)) { routeToProcess = getFallbackRoute(route, this.manifest.routes); } if (this.manifest.pageMap) { const importComponentInstance = this.manifest.pageMap.get(routeToProcess.component); if (!importComponentInstance) { throw new Error( `Unexpectedly unable to find a component instance for route ${route.route}` ); } return await importComponentInstance(); } else if (this.manifest.pageModule) { return this.manifest.pageModule; } throw new Error( "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." ); } async tryRewrite(payload, request) { const { routeData, pathname, newUrl } = findRouteToRewrite({ payload, request, routes: this.manifest.routes.map((routeInfo) => routeInfo.routeData), trailingSlash: this.manifest.trailingSlash, buildFormat: this.manifest.buildFormat, base: this.manifest.base, outDir: this.manifest.serverLike ? this.manifest.buildClientDir : this.manifest.outDir }); const componentInstance = await this.getComponentByRoute(routeData); return { routeData, componentInstance, newUrl, pathname }; } } function i18nHasFallback(manifest) { if (manifest.i18n && manifest.i18n.fallback) { return Object.keys(manifest.i18n.fallback).length > 0; } return false; } class BuildApp extends BaseApp { createPipeline(_streaming, manifest, ..._args) { return BuildPipeline.create({ manifest }); } async createRenderContext(payload) { return await super.createRenderContext({ ...payload }); } isDev() { return true; } setInternals(internals) { this.pipeline.setInternals(internals); } setOptions(options) { this.pipeline.setOptions(options); this.logger.setDestination(options.logger.options.destination); this.resetAdapterLogger(); } getOptions() { return this.pipeline.getOptions(); } getSettings() { return this.pipeline.getSettings(); } async renderError(request, options) { if (options.status === 500) { if (options.response) { return options.response; } throw options.error; } else { return super.renderError(request, { ...options, prerenderedErrorPageFetch: void 0 }); } } getQueueStats() { if (this.pipeline.nodePool) { return this.pipeline.nodePool.getStats(); } } logRequest(_options) { } } const app = new BuildApp(manifest); export { AstroUserError as A, MissingSharp as B, createVNode as C, app as D, ExpectedImage as E, Fragment as F, manifest as G, ImageMissingAlt as I, LocalImageUsedWrongly as L, MissingImageDimension as M, NoImageMetadata as N, RenderUndefinedEntryError as R, UnknownContentCollectionError as U, __astro_tag_component__ as _, renderTemplate as a, addAttribute as b, renderHead as c, defineMiddleware as d, renderSlot as e, createRenderInstruction as f, AstroError as g, spreadAttributes as h, FontFamilyNotFound as i, defineStyleVars as j, renderElement$1 as k, generateCspDigest as l, maybeRenderHead as m, createHeadAndContent as n, InvalidComponentArgs as o, FailedToFetchRemoteImageDimensions as p, RemoteImageNotAllowed as q, renderComponent as r, sequence as s, UnsupportedImageFormat as t, unescapeHTML as u, IncompatibleDescriptorOptions as v, UnsupportedImageConversion as w, ExpectedImageOptions as x, ExpectedNotESMImage as y, InvalidImageService as z };