| type ServerIslandDiscovery = { | ||
| resolvedPath: string; | ||
| localName: string; | ||
| specifier: string; | ||
| importer: string; | ||
| }; | ||
| type ServerIslandRecord = Omit<ServerIslandDiscovery, 'resolvedPath'> & { | ||
| islandName: string; | ||
| }; | ||
| export declare class ServerIslandsState { | ||
| private islandsByResolvedPath; | ||
| private resolvedPathByIslandName; | ||
| private referenceIdByResolvedPath; | ||
| hasIslands(): boolean; | ||
| /** | ||
| * Record a discovered server island. | ||
| * | ||
| * Dedupe is based on `resolvedPath`: if the same resolved path is discovered | ||
| * again from a different importer/specifier, the first record is preserved. | ||
| * This keeps island names stable across repeated scans. | ||
| */ | ||
| discover(island: ServerIslandDiscovery): ServerIslandRecord; | ||
| getDiscoveredIslands(): Iterable<ServerIslandRecord>; | ||
| hasReferenceId(resolvedPath: string): boolean; | ||
| setReferenceId(resolvedPath: string, referenceId: string): void; | ||
| getDiscoveredIslandEntries(): Iterable<[string, ServerIslandRecord]>; | ||
| /** | ||
| * Build import-map source from discovered islands. | ||
| * | ||
| * Used by non-SSR build output and dev replacement paths where we can import | ||
| * directly from discovered component paths. | ||
| */ | ||
| createImportMapSourceFromDiscovered(toImportPath: (fileName: string) => string): string; | ||
| /** | ||
| * Build import-map source from Rollup reference ids. | ||
| * | ||
| * Used by SSR build output: reference ids are resolved to final emitted chunk | ||
| * file names before generating import() mappings. | ||
| */ | ||
| createImportMapSourceFromReferences(resolveFileName: (referenceId: string) => string, toImportPath: (fileName: string) => string): string; | ||
| createNameMapSource(): string; | ||
| private createImportMapSource; | ||
| } | ||
| export {}; |
| class ServerIslandsState { | ||
| // Canonical source of discovered islands keyed by resolved component path. | ||
| islandsByResolvedPath = /* @__PURE__ */ new Map(); | ||
| // Reverse lookup used to keep island names unique and stable. | ||
| resolvedPathByIslandName = /* @__PURE__ */ new Map(); | ||
| // Rollup reference ids emitted for SSR chunks, keyed by resolved path. | ||
| referenceIdByResolvedPath = /* @__PURE__ */ new Map(); | ||
| hasIslands() { | ||
| return this.islandsByResolvedPath.size > 0; | ||
| } | ||
| /** | ||
| * Record a discovered server island. | ||
| * | ||
| * Dedupe is based on `resolvedPath`: if the same resolved path is discovered | ||
| * again from a different importer/specifier, the first record is preserved. | ||
| * This keeps island names stable across repeated scans. | ||
| */ | ||
| discover(island) { | ||
| const { resolvedPath, ...discovery } = island; | ||
| const existing = this.islandsByResolvedPath.get(resolvedPath); | ||
| if (existing) { | ||
| return existing; | ||
| } | ||
| let name = island.localName; | ||
| let idx = 1; | ||
| while (this.resolvedPathByIslandName.has(name)) { | ||
| name += idx++; | ||
| } | ||
| const record = { | ||
| ...discovery, | ||
| islandName: name | ||
| }; | ||
| this.islandsByResolvedPath.set(resolvedPath, record); | ||
| this.resolvedPathByIslandName.set(name, resolvedPath); | ||
| return record; | ||
| } | ||
| getDiscoveredIslands() { | ||
| return this.islandsByResolvedPath.values(); | ||
| } | ||
| hasReferenceId(resolvedPath) { | ||
| return this.referenceIdByResolvedPath.has(resolvedPath); | ||
| } | ||
| setReferenceId(resolvedPath, referenceId) { | ||
| this.referenceIdByResolvedPath.set(resolvedPath, referenceId); | ||
| } | ||
| getDiscoveredIslandEntries() { | ||
| return this.islandsByResolvedPath.entries(); | ||
| } | ||
| /** | ||
| * Build import-map source from discovered islands. | ||
| * | ||
| * Used by non-SSR build output and dev replacement paths where we can import | ||
| * directly from discovered component paths. | ||
| */ | ||
| createImportMapSourceFromDiscovered(toImportPath) { | ||
| const entries = Array.from( | ||
| this.islandsByResolvedPath, | ||
| ([resolvedPath, island]) => [island.islandName, resolvedPath] | ||
| ); | ||
| return this.createImportMapSource(entries, toImportPath); | ||
| } | ||
| /** | ||
| * Build import-map source from Rollup reference ids. | ||
| * | ||
| * Used by SSR build output: reference ids are resolved to final emitted chunk | ||
| * file names before generating import() mappings. | ||
| */ | ||
| createImportMapSourceFromReferences(resolveFileName, toImportPath) { | ||
| const entries = []; | ||
| for (const [resolvedPath, referenceId] of this.referenceIdByResolvedPath) { | ||
| const island = this.islandsByResolvedPath.get(resolvedPath); | ||
| if (!island) continue; | ||
| entries.push([island.islandName, resolveFileName(referenceId)]); | ||
| } | ||
| return this.createImportMapSource(entries, toImportPath); | ||
| } | ||
| createNameMapSource() { | ||
| const entries = Array.from( | ||
| this.islandsByResolvedPath, | ||
| ([resolvedPath, island]) => [resolvedPath, island.islandName] | ||
| ); | ||
| return `new Map(${JSON.stringify(entries, null, 2)})`; | ||
| } | ||
| createImportMapSource(entries, toImportPath) { | ||
| const mappings = Array.from(entries, ([islandName, fileName]) => { | ||
| const importPath = toImportPath(fileName); | ||
| return ` [${JSON.stringify(islandName)}, () => import(${JSON.stringify(importPath)})],`; | ||
| }); | ||
| return `new Map([ | ||
| ${mappings.join("\n")} | ||
| ])`; | ||
| } | ||
| } | ||
| export { | ||
| ServerIslandsState | ||
| }; |
| class BuildTimeAstroVersionProvider { | ||
| // Injected during the build through esbuild define | ||
| version = "6.0.6"; | ||
| version = "6.0.7"; | ||
| } | ||
@@ -5,0 +5,0 @@ export { |
@@ -120,3 +120,6 @@ import { existsSync, promises as fs } from "node:fs"; | ||
| html: code, | ||
| metadata | ||
| metadata: { | ||
| ...metadata, | ||
| imagePaths: (metadata.localImagePaths ?? []).concat(metadata.remoteImagePaths ?? []) | ||
| } | ||
| }; | ||
@@ -193,3 +196,3 @@ } | ||
| } | ||
| if (previousAstroVersion && previousAstroVersion !== "6.0.6") { | ||
| if (previousAstroVersion && previousAstroVersion !== "6.0.7") { | ||
| logger.info("Astro version changed"); | ||
@@ -202,4 +205,4 @@ shouldClear = true; | ||
| } | ||
| if ("6.0.6") { | ||
| this.#store.metaStore().set("astro-version", "6.0.6"); | ||
| if ("6.0.7") { | ||
| this.#store.metaStore().set("astro-version", "6.0.7"); | ||
| } | ||
@@ -206,0 +209,0 @@ if (currentConfigDigest) { |
@@ -1,1 +0,1 @@ | ||
| export { NodeApp, loadApp, loadManifest, createRequest, writeResponse } from '../node.js'; | ||
| export { NodeApp, loadApp, loadManifest, createRequest, writeResponse, getAbortControllerCleanup, } from '../node.js'; |
@@ -1,5 +0,13 @@ | ||
| import { NodeApp, loadApp, loadManifest, createRequest, writeResponse } from "../node.js"; | ||
| import { | ||
| NodeApp, | ||
| loadApp, | ||
| loadManifest, | ||
| createRequest, | ||
| writeResponse, | ||
| getAbortControllerCleanup | ||
| } from "../node.js"; | ||
| export { | ||
| NodeApp, | ||
| createRequest, | ||
| getAbortControllerCleanup, | ||
| loadApp, | ||
@@ -6,0 +14,0 @@ loadManifest, |
@@ -8,1 +8,2 @@ import type { MiddlewareHandler } from '../../types/public/common.js'; | ||
| export declare function createOriginCheckMiddleware(): MiddlewareHandler; | ||
| export declare function hasFormLikeHeader(contentType: string | null): boolean; |
@@ -47,3 +47,4 @@ import { defineMiddleware } from "../middleware/defineMiddleware.js"; | ||
| export { | ||
| createOriginCheckMiddleware | ||
| createOriginCheckMiddleware, | ||
| hasFormLikeHeader | ||
| }; |
@@ -93,2 +93,19 @@ import type { IncomingMessage, ServerResponse } from 'node:http'; | ||
| } | ||
| /** | ||
| * Returns the cleanup function for the AbortController and socket listeners created by `createRequest()` | ||
| * for the NodeJS IncomingMessage. This should only be called directly if the request is not | ||
| * being handled by Astro, i.e. if not calling `writeResponse()` after `createRequest()`. | ||
| * ```js | ||
| * import { createRequest, getAbortControllerCleanup } from 'astro/app/node'; | ||
| * import { createServer } from 'node:http'; | ||
| * | ||
| * const server = createServer(async (req, res) => { | ||
| * const request = createRequest(req); | ||
| * const cleanup = getAbortControllerCleanup(req); | ||
| * if (cleanup) cleanup(); | ||
| * // can now safely call another handler | ||
| * }) | ||
| * ``` | ||
| */ | ||
| export declare function getAbortControllerCleanup(req?: NodeRequest): (() => void) | undefined; | ||
| /** @deprecated This will be removed in a future major version. */ | ||
@@ -95,0 +112,0 @@ export declare function loadManifest(rootFolder: URL): Promise<SSRManifest>; |
@@ -281,2 +281,3 @@ import fs from "node:fs"; | ||
| createRequest, | ||
| getAbortControllerCleanup, | ||
| loadApp, | ||
@@ -283,0 +284,0 @@ loadManifest, |
@@ -1,2 +0,2 @@ | ||
| const ASTRO_VERSION = "6.0.6"; | ||
| const ASTRO_VERSION = "6.0.7"; | ||
| const ASTRO_GENERATOR = `Astro v${ASTRO_VERSION}`; | ||
@@ -3,0 +3,0 @@ const REROUTE_DIRECTIVE_HEADER = "X-Astro-Reroute"; |
@@ -46,2 +46,3 @@ import nodeFs from "node:fs"; | ||
| import { joinPaths } from "./path.js"; | ||
| import { ServerIslandsState } from "./server-islands/shared-state.js"; | ||
| import { vitePluginServerIslands } from "./server-islands/vite-plugin-server-islands.js"; | ||
@@ -84,2 +85,3 @@ import { vitePluginCacheProvider } from "./cache/vite-plugin.js"; | ||
| }); | ||
| const serverIslandsState = new ServerIslandsState(); | ||
| validateEnvPrefixAgainstSchema(settings.config); | ||
@@ -101,2 +103,3 @@ const commonConfig = { | ||
| routesList, | ||
| serverIslandsState, | ||
| command: command === "dev" ? "serve" : "build" | ||
@@ -139,3 +142,3 @@ }), | ||
| vitePluginActions({ fs, settings }), | ||
| vitePluginServerIslands({ settings, logger }), | ||
| vitePluginServerIslands({ settings, logger, serverIslandsState }), | ||
| vitePluginSessionDriver({ settings }), | ||
@@ -142,0 +145,0 @@ vitePluginCacheProvider({ settings }), |
@@ -29,3 +29,3 @@ import fs from "node:fs"; | ||
| const logger = restart.container.logger; | ||
| const currentVersion = "6.0.6"; | ||
| const currentVersion = "6.0.7"; | ||
| const isPrerelease = currentVersion.includes("-"); | ||
@@ -32,0 +32,0 @@ if (!isPrerelease) { |
@@ -272,3 +272,3 @@ import colors from "piccolore"; | ||
| ` ${bgGreen(black(` ${commandName} `))} ${green( | ||
| `v${"6.0.6"}` | ||
| `v${"6.0.7"}` | ||
| )} ${headline}` | ||
@@ -275,0 +275,0 @@ ); |
@@ -7,2 +7,3 @@ import colors from "piccolore"; | ||
| computeCurrentLocale, | ||
| computeCurrentLocaleFromParams, | ||
| computePreferredLocale, | ||
@@ -741,2 +742,8 @@ computePreferredLocaleList | ||
| computedLocale = computeCurrentLocale(pathname, locales, defaultLocale); | ||
| if (routeData.params.length > 0) { | ||
| const localeFromParams = computeCurrentLocaleFromParams(this.params, locales); | ||
| if (localeFromParams) { | ||
| computedLocale = localeFromParams; | ||
| } | ||
| } | ||
| } | ||
@@ -743,0 +750,0 @@ this.#currentLocale = computedLocale ?? fallbackTo; |
@@ -5,2 +5,10 @@ import { redirectIsExternal } from "../redirects/render.js"; | ||
| 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) => { | ||
@@ -7,0 +15,0 @@ return route.pattern.test(pathname) || route.fallbackRoutes.some((fallbackRoute) => fallbackRoute.pattern.test(pathname)); |
@@ -13,2 +13,3 @@ import { shouldAppendForwardSlash } from "../build/util.js"; | ||
| import { DEFAULT_404_ROUTE } from "./internal/astro-designed-error-pages.js"; | ||
| import { isRoute404, isRoute500 } from "./internal/route-errors.js"; | ||
| function findRouteToRewrite({ | ||
@@ -57,2 +58,14 @@ payload, | ||
| 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; | ||
@@ -59,0 +72,0 @@ for (const route of routes) { |
| import type { Plugin as VitePlugin } from 'vite'; | ||
| import type { AstroPluginOptions } from '../../types/astro.js'; | ||
| import type { ServerIslandsState } from './shared-state.js'; | ||
| export declare const SERVER_ISLAND_MANIFEST = "virtual:astro:server-island-manifest"; | ||
| export declare const SERVER_ISLAND_MAP_MARKER = "$$server-islands-map$$"; | ||
| export declare function vitePluginServerIslands({ settings }: AstroPluginOptions): VitePlugin; | ||
| export declare function vitePluginServerIslands({ settings, serverIslandsState, }: AstroPluginOptions & { | ||
| serverIslandsState: ServerIslandsState; | ||
| }): VitePlugin; |
@@ -10,32 +10,18 @@ import { ASTRO_VITE_ENVIRONMENT_NAMES } from "../constants.js"; | ||
| const serverIslandNameMapReplaceExp = /['"]\$\$server-islands-name-map\$\$['"]/g; | ||
| function createServerIslandImportMapSource(entries, toImportPath) { | ||
| const mappings = Array.from(entries, ([islandName, fileName]) => { | ||
| const importPath = toImportPath(fileName); | ||
| return ` [${JSON.stringify(islandName)}, () => import(${JSON.stringify(importPath)})],`; | ||
| }); | ||
| return `new Map([ | ||
| ${mappings.join("\n")} | ||
| ])`; | ||
| } | ||
| function createNameMapSource(entries) { | ||
| return `new Map(${JSON.stringify(Array.from(entries), null, 2)})`; | ||
| } | ||
| function vitePluginServerIslands({ settings }) { | ||
| function vitePluginServerIslands({ | ||
| settings, | ||
| serverIslandsState | ||
| }) { | ||
| let command = "serve"; | ||
| let ssrEnvironment = null; | ||
| const serverIslandMap = /* @__PURE__ */ new Map(); | ||
| const serverIslandNameMap = /* @__PURE__ */ new Map(); | ||
| const serverIslandSourceMap = /* @__PURE__ */ new Map(); | ||
| const referenceIdMap = /* @__PURE__ */ new Map(); | ||
| function ensureServerIslandReferenceIds(ctx) { | ||
| for (const [resolvedPath, islandName] of serverIslandNameMap) { | ||
| if (referenceIdMap.has(resolvedPath)) continue; | ||
| const source = serverIslandSourceMap.get(resolvedPath); | ||
| for (const [resolvedPath, island] of serverIslandsState.getDiscoveredIslandEntries()) { | ||
| if (serverIslandsState.hasReferenceId(resolvedPath)) continue; | ||
| const referenceId = ctx.emitFile({ | ||
| type: "chunk", | ||
| id: source?.id ?? resolvedPath, | ||
| importer: source?.importer, | ||
| name: islandName | ||
| id: island.specifier, | ||
| importer: island.importer, | ||
| name: island.islandName | ||
| }); | ||
| referenceIdMap.set(resolvedPath, referenceId); | ||
| serverIslandsState.setReferenceId(resolvedPath, referenceId); | ||
| } | ||
@@ -90,29 +76,23 @@ } | ||
| for (const comp of astro.serverComponents) { | ||
| if (!serverIslandNameMap.has(comp.resolvedPath)) { | ||
| if (!settings.adapter) { | ||
| throw new AstroError(AstroErrorData.NoAdapterInstalledServerIslands); | ||
| } | ||
| let name = comp.localName; | ||
| let idx = 1; | ||
| while (serverIslandMap.has(name)) { | ||
| name += idx++; | ||
| } | ||
| serverIslandNameMap.set(comp.resolvedPath, name); | ||
| serverIslandMap.set(name, comp.resolvedPath); | ||
| serverIslandSourceMap.set(comp.resolvedPath, { id: comp.specifier, importer: id }); | ||
| if (!settings.adapter) { | ||
| throw new AstroError(AstroErrorData.NoAdapterInstalledServerIslands); | ||
| } | ||
| if (isBuildSsr && !referenceIdMap.has(comp.resolvedPath)) { | ||
| const islandName = serverIslandNameMap.get(comp.resolvedPath); | ||
| const source = serverIslandSourceMap.get(comp.resolvedPath); | ||
| const island = serverIslandsState.discover({ | ||
| resolvedPath: comp.resolvedPath, | ||
| localName: comp.localName, | ||
| specifier: comp.specifier ?? comp.resolvedPath, | ||
| importer: id | ||
| }); | ||
| if (isBuildSsr && !serverIslandsState.hasReferenceId(comp.resolvedPath)) { | ||
| const referenceId = this.emitFile({ | ||
| type: "chunk", | ||
| id: source?.id ?? comp.resolvedPath, | ||
| importer: source?.importer, | ||
| name: islandName | ||
| id: island.specifier, | ||
| importer: island.importer, | ||
| name: island.islandName | ||
| }); | ||
| referenceIdMap.set(comp.resolvedPath, referenceId); | ||
| serverIslandsState.setReferenceId(comp.resolvedPath, referenceId); | ||
| } | ||
| } | ||
| } | ||
| if (serverIslandNameMap.size > 0 && serverIslandMap.size > 0 && ssrEnvironment) { | ||
| if (serverIslandsState.hasIslands() && ssrEnvironment) { | ||
| const mod = ssrEnvironment.moduleGraph.getModuleById(RESOLVED_SERVER_ISLAND_MANIFEST); | ||
@@ -125,3 +105,3 @@ if (mod) { | ||
| if (command === "build" && settings.buildOutput) { | ||
| const hasServerIslands = serverIslandNameMap.size > 0; | ||
| const hasServerIslands = serverIslandsState.hasIslands(); | ||
| if (hasServerIslands && settings.buildOutput !== "server") { | ||
@@ -131,8 +111,7 @@ throw new AstroError(AstroErrorData.NoAdapterInstalledServerIslands); | ||
| } | ||
| if (command !== "build" && serverIslandNameMap.size > 0 && serverIslandMap.size > 0) { | ||
| const mapSource = createServerIslandImportMapSource( | ||
| serverIslandMap, | ||
| if (command !== "build" && serverIslandsState.hasIslands()) { | ||
| const mapSource = serverIslandsState.createImportMapSourceFromDiscovered( | ||
| (fileName) => fileName | ||
| ); | ||
| const nameMapSource = createNameMapSource(serverIslandNameMap); | ||
| const nameMapSource = serverIslandsState.createNameMapSource(); | ||
| return { | ||
@@ -157,17 +136,12 @@ code: ` | ||
| const dots = isRelativeChunk ? ".." : "."; | ||
| const mapEntries = []; | ||
| for (const [resolvedPath, referenceId] of referenceIdMap) { | ||
| const fileName = this.getFileName(referenceId); | ||
| const islandName = serverIslandNameMap.get(resolvedPath); | ||
| if (!islandName) continue; | ||
| mapEntries.push([islandName, fileName]); | ||
| } | ||
| mapSource = createServerIslandImportMapSource( | ||
| mapEntries, | ||
| mapSource = serverIslandsState.createImportMapSourceFromReferences( | ||
| (referenceId) => this.getFileName(referenceId), | ||
| (fileName) => `${dots}/${fileName}` | ||
| ); | ||
| } else { | ||
| mapSource = createServerIslandImportMapSource(serverIslandMap, (fileName) => fileName); | ||
| mapSource = serverIslandsState.createImportMapSourceFromDiscovered( | ||
| (fileName) => fileName | ||
| ); | ||
| } | ||
| const nameMapSource = createNameMapSource(serverIslandNameMap); | ||
| const nameMapSource = serverIslandsState.createNameMapSource(); | ||
| return { | ||
@@ -174,0 +148,0 @@ code: code.replace(serverIslandMapReplaceExp, mapSource).replace(serverIslandNameMapReplaceExp, nameMapSource), |
@@ -51,11 +51,18 @@ import { appendForwardSlash } from "@astrojs/internal-helpers/path"; | ||
| case "notFound": { | ||
| const notFoundRes = new Response(response.body, { | ||
| status: 404, | ||
| headers: response.headers | ||
| }); | ||
| notFoundRes.headers.set(REROUTE_DIRECTIVE_HEADER, "no"); | ||
| 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) { | ||
| notFoundRes.headers.set("Location", routeDecision.location); | ||
| headers.set("Location", routeDecision.location); | ||
| } | ||
| return notFoundRes; | ||
| return new Response(null, { status: 404, headers }); | ||
| } | ||
@@ -62,0 +69,0 @@ case "continue": |
@@ -24,2 +24,8 @@ import type { Locales } from '../types/public/config.js'; | ||
| export declare function computeCurrentLocale(pathname: string, locales: Locales, defaultLocale: string): string | undefined; | ||
| /** | ||
| * Check if any of the route's resolved param values match a configured locale. | ||
| * This handles dynamic routes like `[locale]` or `[...path]` where the locale | ||
| * isn't in a static segment of the route pathname. | ||
| */ | ||
| export declare function computeCurrentLocaleFromParams(params: Record<string, string | undefined>, locales: Locales): string | undefined; | ||
| export {}; |
+22
-0
@@ -137,4 +137,26 @@ import { getAllCodes, normalizeTheLocale, normalizeThePath } from "./index.js"; | ||
| } | ||
| 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; | ||
| } | ||
| } | ||
| export { | ||
| computeCurrentLocale, | ||
| computeCurrentLocaleFromParams, | ||
| computePreferredLocale, | ||
@@ -141,0 +163,0 @@ computePreferredLocaleList, |
@@ -37,2 +37,10 @@ import { fileURLToPath } from "node:url"; | ||
| const normalizedSrcDir = normalizePath(fileURLToPath(settings.config.srcDir)); | ||
| let encodedKeyPromise; | ||
| function getEncodedKey() { | ||
| encodedKeyPromise ??= (async () => { | ||
| const key = hasEnvironmentKey() ? await getEnvironmentKey() : await createKey(); | ||
| return encodeKey(key); | ||
| })(); | ||
| return encodedKeyPromise; | ||
| } | ||
| function reloadManifest(path, server) { | ||
@@ -71,3 +79,3 @@ if (path != null && normalizePath(path).startsWith(normalizedSrcDir)) { | ||
| } else { | ||
| const serialized = await createSerializedManifest(settings); | ||
| const serialized = await createSerializedManifest(settings, await getEncodedKey()); | ||
| manifestData = JSON.stringify(serialized); | ||
@@ -108,3 +116,3 @@ } | ||
| } | ||
| async function createSerializedManifest(settings) { | ||
| async function createSerializedManifest(settings, encodedKey) { | ||
| let i18nManifest; | ||
@@ -167,3 +175,3 @@ let csp; | ||
| // 1mb default | ||
| key: await encodeKey(hasEnvironmentKey() ? await getEnvironmentKey() : await createKey()), | ||
| key: encodedKey ?? await encodeKey(hasEnvironmentKey() ? await getEnvironmentKey() : await createKey()), | ||
| sessionConfig: sessionConfigToManifest(settings.config.session), | ||
@@ -170,0 +178,0 @@ cacheConfig: cacheConfigToManifest( |
@@ -22,3 +22,3 @@ import { AsyncLocalStorage } from "node:async_hooks"; | ||
| import { createViteLoader } from "../core/module-loader/index.js"; | ||
| import { isRouteServerIsland, matchAllRoutes } from "../core/routing/match.js"; | ||
| import { matchAllRoutes } from "../core/routing/match.js"; | ||
| import { resolveMiddlewareMode } from "../integrations/adapter-utils.js"; | ||
@@ -130,3 +130,3 @@ import { SERIALIZED_MANIFEST_ID } from "../manifest/serialized.js"; | ||
| const matches = matchAllRoutes(pathname, routesList); | ||
| if (!matches.some((route) => route.prerender || isRouteServerIsland(route))) { | ||
| if (!matches.some((route) => route.prerender)) { | ||
| return next(); | ||
@@ -133,0 +133,0 @@ } |
@@ -21,2 +21,19 @@ import { prependForwardSlash } from "@astrojs/internal-helpers/path"; | ||
| } | ||
| async function ensureModulesLoaded(env, mod, seen = /* @__PURE__ */ new Set()) { | ||
| const id = mod.id ?? mod.url; | ||
| if (seen.has(id)) return; | ||
| seen.add(id); | ||
| for (const imp of mod.importedModules) { | ||
| if (!imp.id) continue; | ||
| if (seen.has(imp.id)) continue; | ||
| if (imp.id.includes(PROPAGATED_ASSET_QUERY_PARAM)) continue; | ||
| if (!imp.transformResult) { | ||
| try { | ||
| await env.fetchModule(imp.id); | ||
| } catch { | ||
| } | ||
| } | ||
| await ensureModulesLoaded(env, imp, seen); | ||
| } | ||
| } | ||
| function* collectCSSWithOrder(id, mod, seen = /* @__PURE__ */ new Set()) { | ||
@@ -102,2 +119,5 @@ seen.add(id); | ||
| } | ||
| if (env) { | ||
| await ensureModulesLoaded(env, mod); | ||
| } | ||
| for (const collected of collectCSSWithOrder(componentPageId, mod)) { | ||
@@ -104,0 +124,0 @@ if (!cssWithOrder.has(collected.idKey)) { |
| import type { ConfigEnv, Plugin as VitePlugin } from 'vite'; | ||
| import type { ServerIslandsState } from '../core/server-islands/shared-state.js'; | ||
| import type { AstroSettings, RoutesList } from '../types/astro.js'; | ||
@@ -7,2 +8,3 @@ export declare const ASTRO_RENDERERS_MODULE_ID = "virtual:astro:renderers"; | ||
| routesList: RoutesList; | ||
| serverIslandsState: ServerIslandsState; | ||
| command: ConfigEnv['command']; | ||
@@ -9,0 +11,0 @@ } |
@@ -23,3 +23,3 @@ import { ASTRO_VITE_ENVIRONMENT_NAMES } from "../core/constants.js"; | ||
| handler() { | ||
| if (options.command === "build" && this.environment.name === ASTRO_VITE_ENVIRONMENT_NAMES.ssr && renderers.length > 0 && !hasNonPrerenderedProjectRoute(options.routesList.routes, { | ||
| if (options.command === "build" && this.environment.name === ASTRO_VITE_ENVIRONMENT_NAMES.ssr && renderers.length > 0 && !options.serverIslandsState.hasIslands() && !hasNonPrerenderedProjectRoute(options.routesList.routes, { | ||
| includeEndpoints: false | ||
@@ -26,0 +26,0 @@ })) { |
+1
-1
| { | ||
| "name": "astro", | ||
| "version": "6.0.6", | ||
| "version": "6.0.7", | ||
| "description": "Astro is a modern site builder with web best practices, performance, and DX front-of-mind.", | ||
@@ -5,0 +5,0 @@ "type": "module", |
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 7 instances in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 7 instances in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
2610689
0.33%1181
0.17%68944
0.36%