| import { AstroError } from "../core/errors/errors.js"; | ||
| import { ActionsWithoutServerOutputError } from "../core/errors/errors-data.js"; | ||
| import { hasNonPrerenderedProjectRoute } from "../core/routing/helpers.js"; | ||
| import { viteID } from "../core/util.js"; | ||
@@ -21,7 +22,2 @@ import { ACTION_RPC_ROUTE_PATTERN, ACTIONS_TYPES_FILE, VIRTUAL_MODULE_ID } from "./consts.js"; | ||
| "astro:config:done": async (params) => { | ||
| if (params.buildOutput === "static") { | ||
| const error = new AstroError(ActionsWithoutServerOutputError); | ||
| error.stack = void 0; | ||
| throw error; | ||
| } | ||
| const stringifiedActionsImport = JSON.stringify( | ||
@@ -33,5 +29,12 @@ viteID(new URL(`./${filename}`, params.config.srcDir)) | ||
| content: `declare module "astro:actions" { | ||
| export const actions: typeof import(${stringifiedActionsImport})["server"]; | ||
| export const actions: typeof import(${stringifiedActionsImport})["server"]; | ||
| }` | ||
| }); | ||
| }, | ||
| "astro:routes:resolved": ({ routes }) => { | ||
| if (!hasNonPrerenderedProjectRoute(routes)) { | ||
| const error = new AstroError(ActionsWithoutServerOutputError); | ||
| error.stack = void 0; | ||
| throw error; | ||
| } | ||
| } | ||
@@ -38,0 +41,0 @@ } |
@@ -6,6 +6,7 @@ import type { ImageMetadata } from './types.js'; | ||
| children: string; | ||
| styles: string[]; | ||
| } | ||
| export declare function createSvgComponent({ meta, attributes, children }: SvgComponentProps): import("../runtime/server/index.js").AstroComponentFactory & ImageMetadata; | ||
| export declare function createSvgComponent({ meta, attributes, children, styles }: SvgComponentProps): import("../runtime/server/index.js").AstroComponentFactory & ImageMetadata; | ||
| type SvgAttributes = Record<string, any>; | ||
| export declare function dropAttributes(attributes: SvgAttributes): SvgAttributes; | ||
| export {}; |
@@ -0,1 +1,2 @@ | ||
| import { generateCspDigest } from "../core/encryption.js"; | ||
| import { | ||
@@ -7,6 +8,16 @@ createComponent, | ||
| } from "../runtime/server/index.js"; | ||
| function createSvgComponent({ meta, attributes, children }) { | ||
| const Component = createComponent((_, props) => { | ||
| const normalizedProps = normalizeProps(attributes, props); | ||
| return render`<svg${spreadAttributes(normalizedProps)}>${unescapeHTML(children)}</svg>`; | ||
| function createSvgComponent({ meta, attributes, children, styles }) { | ||
| const hasStyles = styles.length > 0; | ||
| const Component = createComponent({ | ||
| async factory(result, props) { | ||
| const normalizedProps = normalizeProps(attributes, props); | ||
| if (hasStyles && result.cspDestination) { | ||
| for (const style of styles) { | ||
| const hash = await generateCspDigest(style, result.cspAlgorithm); | ||
| result._metadata.extraStyleHashes.push(hash); | ||
| } | ||
| } | ||
| return render`<svg${spreadAttributes(normalizedProps)}>${unescapeHTML(children)}</svg>`; | ||
| }, | ||
| propagation: hasStyles ? "self" : "none" | ||
| }); | ||
@@ -13,0 +24,0 @@ if (import.meta.env.DEV) { |
| import { optimize } from "svgo"; | ||
| import { parse, renderSync } from "ultrahtml"; | ||
| import { ELEMENT_NODE, TEXT_NODE, parse, renderSync } from "ultrahtml"; | ||
| import { AstroError, AstroErrorData } from "../../core/errors/index.js"; | ||
@@ -28,3 +28,3 @@ import { dropAttributes } from "../runtime.js"; | ||
| const svgNode = root.children.find( | ||
| ({ name, type }) => type === 1 && name === "svg" | ||
| ({ name, type }) => type === ELEMENT_NODE && name === "svg" | ||
| ); | ||
@@ -36,7 +36,20 @@ if (!svgNode) { | ||
| const body = renderSync({ ...root, children }); | ||
| return { attributes, body }; | ||
| const styles = []; | ||
| for (const child of children) { | ||
| if (child.type === ELEMENT_NODE && child.name === "style") { | ||
| const textContent = child.children?.filter((c) => c.type === TEXT_NODE).map((c) => c.value).join(""); | ||
| if (textContent) { | ||
| styles.push(textContent); | ||
| } | ||
| } | ||
| } | ||
| return { attributes, body, styles }; | ||
| } | ||
| function makeSvgComponent(meta, contents, svgoConfig) { | ||
| const file = typeof contents === "string" ? contents : contents.toString("utf-8"); | ||
| const { attributes, body: children } = parseSvg({ | ||
| const { | ||
| attributes, | ||
| body: children, | ||
| styles | ||
| } = parseSvg({ | ||
| path: meta.fsPath, | ||
@@ -49,3 +62,4 @@ contents: file, | ||
| attributes: dropAttributes(attributes), | ||
| children | ||
| children, | ||
| styles | ||
| }; | ||
@@ -57,3 +71,7 @@ return `import { createSvgComponent } from 'astro/assets/runtime'; | ||
| const file = typeof contents === "string" ? contents : contents.toString("utf-8"); | ||
| const { attributes, body: children } = parseSvg({ | ||
| const { | ||
| attributes, | ||
| body: children, | ||
| styles | ||
| } = parseSvg({ | ||
| path: meta.fsPath, | ||
@@ -63,3 +81,3 @@ contents: file, | ||
| }); | ||
| return { attributes: dropAttributes(attributes), children }; | ||
| return { attributes: dropAttributes(attributes), children, styles }; | ||
| } | ||
@@ -66,0 +84,0 @@ export { |
| class BuildTimeAstroVersionProvider { | ||
| // Injected during the build through esbuild define | ||
| version = "6.0.4"; | ||
| version = "6.0.5"; | ||
| } | ||
@@ -5,0 +5,0 @@ export { |
@@ -192,3 +192,3 @@ import { existsSync, promises as fs } from "node:fs"; | ||
| } | ||
| if (previousAstroVersion && previousAstroVersion !== "6.0.4") { | ||
| if (previousAstroVersion && previousAstroVersion !== "6.0.5") { | ||
| logger.info("Astro version changed"); | ||
@@ -201,4 +201,4 @@ shouldClear = true; | ||
| } | ||
| if ("6.0.4") { | ||
| this.#store.metaStore().set("astro-version", "6.0.4"); | ||
| if ("6.0.5") { | ||
| this.#store.metaStore().set("astro-version", "6.0.5"); | ||
| } | ||
@@ -205,0 +205,0 @@ if (currentConfigDigest) { |
@@ -9,2 +9,6 @@ import { createContentTypesGenerator } from "./types-generator.js"; | ||
| }) { | ||
| const maxListeners = viteServer.watcher.getMaxListeners(); | ||
| if (maxListeners !== 0 && maxListeners < 50) { | ||
| viteServer.watcher.setMaxListeners(50); | ||
| } | ||
| const contentGenerator = await createContentTypesGenerator({ | ||
@@ -11,0 +15,0 @@ fs, |
@@ -466,3 +466,6 @@ import * as path from "node:path"; | ||
| } | ||
| } | ||
| }, | ||
| // Collection schemas are used for parsing collection input, so we need to tell Zod to use the | ||
| // input shape when generating a JSON schema. | ||
| io: "input" | ||
| }); | ||
@@ -469,0 +472,0 @@ const schemaStr = JSON.stringify(schema, null, 2); |
@@ -64,98 +64,102 @@ import fs from "node:fs"; | ||
| ${colors.bgGreen(colors.black(` ${verb} static routes `))}`); | ||
| const pathsWithRoutes = await prerenderer.getStaticPaths(); | ||
| const routeToHeaders = /* @__PURE__ */ new Map(); | ||
| const hasI18nDomains = ssr && options.settings.config.i18n?.domains && Object.keys(options.settings.config.i18n.domains).length > 0; | ||
| const { config } = options.settings; | ||
| const builtPaths = /* @__PURE__ */ new Set(); | ||
| const filteredPaths = pathsWithRoutes.filter(({ pathname, route }) => { | ||
| if (hasI18nDomains && route.prerender) { | ||
| throw new AstroError({ | ||
| ...AstroErrorData.NoPrerenderedRoutesWithDomains, | ||
| message: AstroErrorData.NoPrerenderedRoutesWithDomains.message(route.component) | ||
| }); | ||
| } | ||
| const normalized = removeTrailingForwardSlash(pathname); | ||
| if (!builtPaths.has(normalized)) { | ||
| builtPaths.add(normalized); | ||
| return true; | ||
| } | ||
| const matchedRoute = matchRoute(decodeURI(pathname), options.routesList); | ||
| if (!matchedRoute) { | ||
| return false; | ||
| } | ||
| if (matchedRoute === route) { | ||
| return true; | ||
| } | ||
| if (config.prerenderConflictBehavior === "error") { | ||
| throw new AstroError({ | ||
| ...AstroErrorData.PrerenderRouteConflict, | ||
| message: AstroErrorData.PrerenderRouteConflict.message( | ||
| let staticImageList = getStaticImageList(); | ||
| try { | ||
| const pathsWithRoutes = await prerenderer.getStaticPaths(); | ||
| const hasI18nDomains = ssr && options.settings.config.i18n?.domains && Object.keys(options.settings.config.i18n.domains).length > 0; | ||
| const { config } = options.settings; | ||
| const builtPaths = /* @__PURE__ */ new Set(); | ||
| const filteredPaths = pathsWithRoutes.filter(({ pathname, route }) => { | ||
| if (hasI18nDomains && route.prerender) { | ||
| throw new AstroError({ | ||
| ...AstroErrorData.NoPrerenderedRoutesWithDomains, | ||
| message: AstroErrorData.NoPrerenderedRoutesWithDomains.message(route.component) | ||
| }); | ||
| } | ||
| const normalized = removeTrailingForwardSlash(pathname); | ||
| if (!builtPaths.has(normalized)) { | ||
| builtPaths.add(normalized); | ||
| return true; | ||
| } | ||
| const matchedRoute = matchRoute(decodeURI(pathname), options.routesList); | ||
| if (!matchedRoute) { | ||
| return false; | ||
| } | ||
| if (matchedRoute === route) { | ||
| return true; | ||
| } | ||
| if (config.prerenderConflictBehavior === "error") { | ||
| throw new AstroError({ | ||
| ...AstroErrorData.PrerenderRouteConflict, | ||
| message: AstroErrorData.PrerenderRouteConflict.message( | ||
| matchedRoute.route, | ||
| route.route, | ||
| normalized | ||
| ), | ||
| hint: AstroErrorData.PrerenderRouteConflict.hint(matchedRoute.route, route.route) | ||
| }); | ||
| } else if (config.prerenderConflictBehavior === "warn") { | ||
| const msg = AstroErrorData.PrerenderRouteConflict.message( | ||
| matchedRoute.route, | ||
| route.route, | ||
| normalized | ||
| ), | ||
| hint: AstroErrorData.PrerenderRouteConflict.hint(matchedRoute.route, route.route) | ||
| }); | ||
| } else if (config.prerenderConflictBehavior === "warn") { | ||
| const msg = AstroErrorData.PrerenderRouteConflict.message( | ||
| matchedRoute.route, | ||
| route.route, | ||
| normalized | ||
| ); | ||
| logger.warn("build", msg); | ||
| } | ||
| return false; | ||
| }); | ||
| if (config.build.concurrency > 1) { | ||
| const limit = PLimit(config.build.concurrency); | ||
| const BATCH_SIZE = 1e5; | ||
| for (let i = 0; i < filteredPaths.length; i += BATCH_SIZE) { | ||
| const batch = filteredPaths.slice(i, i + BATCH_SIZE); | ||
| const promises = []; | ||
| for (const { pathname, route } of batch) { | ||
| promises.push( | ||
| limit( | ||
| () => generatePathWithPrerenderer( | ||
| prerenderer, | ||
| pathname, | ||
| route, | ||
| options, | ||
| routeToHeaders, | ||
| logger | ||
| ); | ||
| logger.warn("build", msg); | ||
| } | ||
| return false; | ||
| }); | ||
| if (config.build.concurrency > 1) { | ||
| const limit = PLimit(config.build.concurrency); | ||
| const BATCH_SIZE = 1e5; | ||
| for (let i = 0; i < filteredPaths.length; i += BATCH_SIZE) { | ||
| const batch = filteredPaths.slice(i, i + BATCH_SIZE); | ||
| const promises = []; | ||
| for (const { pathname, route } of batch) { | ||
| promises.push( | ||
| limit( | ||
| () => generatePathWithPrerenderer( | ||
| prerenderer, | ||
| pathname, | ||
| route, | ||
| options, | ||
| routeToHeaders, | ||
| logger | ||
| ) | ||
| ) | ||
| ) | ||
| ); | ||
| } | ||
| await Promise.all(promises); | ||
| } | ||
| } else { | ||
| for (const { pathname, route } of filteredPaths) { | ||
| await generatePathWithPrerenderer( | ||
| prerenderer, | ||
| pathname, | ||
| route, | ||
| options, | ||
| routeToHeaders, | ||
| logger | ||
| ); | ||
| } | ||
| await Promise.all(promises); | ||
| } | ||
| } else { | ||
| for (const { pathname, route } of filteredPaths) { | ||
| await generatePathWithPrerenderer( | ||
| prerenderer, | ||
| pathname, | ||
| route, | ||
| options, | ||
| routeToHeaders, | ||
| logger | ||
| ); | ||
| } | ||
| } | ||
| for (const { route: generatedRoute } of filteredPaths) { | ||
| if (generatedRoute.distURL && generatedRoute.distURL.length > 0) { | ||
| for (const pageData of Object.values(options.allPages)) { | ||
| if (pageData.route.route === generatedRoute.route && pageData.route.component === generatedRoute.component) { | ||
| pageData.route.distURL = generatedRoute.distURL; | ||
| break; | ||
| for (const { route: generatedRoute } of filteredPaths) { | ||
| if (generatedRoute.distURL && generatedRoute.distURL.length > 0) { | ||
| for (const pageData of Object.values(options.allPages)) { | ||
| if (pageData.route.route === generatedRoute.route && pageData.route.component === generatedRoute.component) { | ||
| pageData.route.distURL = generatedRoute.distURL; | ||
| break; | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } | ||
| const staticImageList = getStaticImageList(); | ||
| if (prerenderer.collectStaticImages) { | ||
| const adapterImages = await prerenderer.collectStaticImages(); | ||
| for (const [path, entry] of adapterImages) { | ||
| staticImageList.set(path, entry); | ||
| staticImageList = getStaticImageList(); | ||
| if (prerenderer.collectStaticImages) { | ||
| const adapterImages = await prerenderer.collectStaticImages(); | ||
| for (const [path, entry] of adapterImages) { | ||
| staticImageList.set(path, entry); | ||
| } | ||
| } | ||
| } finally { | ||
| await prerenderer.teardown?.(); | ||
| } | ||
| await prerenderer.teardown?.(); | ||
| logger.info( | ||
@@ -332,3 +336,7 @@ null, | ||
| if (pathname === "/" || pathname === "") { | ||
| buildPathname = collapseDuplicateTrailingSlashes(base + ending, trailingSlash !== "never"); | ||
| if (format === "file") { | ||
| buildPathname = joinPaths(base, "index.html"); | ||
| } else { | ||
| buildPathname = collapseDuplicateTrailingSlashes(base + ending, trailingSlash !== "never"); | ||
| } | ||
| } else if (routeType === "endpoint") { | ||
@@ -335,0 +343,0 @@ const buildPathRelative = removeLeadingForwardSlash(pathname); |
| import { normalizeEntryId } from "./plugin-component-entry.js"; | ||
| import { ASTRO_VITE_ENVIRONMENT_NAMES } from "../../constants.js"; | ||
| function getRollupInputAsSet(rollupInput) { | ||
| if (Array.isArray(rollupInput)) { | ||
| return new Set(rollupInput); | ||
| } else if (typeof rollupInput === "string") { | ||
| return /* @__PURE__ */ new Set([rollupInput]); | ||
| } else if (rollupInput && typeof rollupInput === "object") { | ||
| return new Set(Object.values(rollupInput)); | ||
| } else { | ||
| return /* @__PURE__ */ new Set(); | ||
| } | ||
| } | ||
| function pluginInternals(options, internals) { | ||
| let input; | ||
| return { | ||
@@ -30,15 +40,4 @@ name: "@astro/plugin-build-internals", | ||
| }, | ||
| configResolved(config) { | ||
| const rollupInput = config.build?.rollupOptions?.input; | ||
| if (Array.isArray(rollupInput)) { | ||
| input = new Set(rollupInput); | ||
| } else if (typeof rollupInput === "string") { | ||
| input = /* @__PURE__ */ new Set([rollupInput]); | ||
| } else if (rollupInput && typeof rollupInput === "object") { | ||
| input = new Set(Object.values(rollupInput)); | ||
| } else { | ||
| input = /* @__PURE__ */ new Set(); | ||
| } | ||
| }, | ||
| async generateBundle(_options, bundle) { | ||
| const input = getRollupInputAsSet(this.environment?.config.build.rollupOptions.input); | ||
| const promises = []; | ||
@@ -45,0 +44,0 @@ const mapping = /* @__PURE__ */ new Map(); |
@@ -37,3 +37,3 @@ import fs from "node:fs"; | ||
| import { getSSRAssets } from "./internal.js"; | ||
| import { serverIslandPlaceholderMap } from "../server-islands/vite-plugin-server-islands.js"; | ||
| import { SERVER_ISLAND_MAP_MARKER } from "../server-islands/vite-plugin-server-islands.js"; | ||
| const PRERENDER_ENTRY_FILENAME_PREFIX = "prerender-entry"; | ||
@@ -47,3 +47,3 @@ function extractRelevantChunks(outputs, prerender) { | ||
| const needsManifestInjection = chunk.moduleIds.includes(SERIALIZED_MANIFEST_RESOLVED_ID); | ||
| const needsServerIslandInjection = chunk.code.includes(serverIslandPlaceholderMap); | ||
| const needsServerIslandInjection = chunk.code.includes(SERVER_ISLAND_MAP_MARKER); | ||
| if (needsContentInjection || needsManifestInjection || needsServerIslandInjection) { | ||
@@ -223,2 +223,9 @@ extracted.push({ | ||
| async buildApp(builder2) { | ||
| settings.timer.start("Prerender build"); | ||
| let prerenderOutput = await builder2.build(builder2.environments.prerender); | ||
| settings.timer.end("Prerender build"); | ||
| extractPrerenderEntryFileName(internals, prerenderOutput); | ||
| const prerenderOutputs = viteBuildReturnToRollupOutputs(prerenderOutput); | ||
| const prerenderChunks = extractRelevantChunks(prerenderOutputs, true); | ||
| prerenderOutput = void 0; | ||
| let ssrChunks = []; | ||
@@ -235,9 +242,2 @@ if (settings.buildOutput !== "static") { | ||
| } | ||
| settings.timer.start("Prerender build"); | ||
| let prerenderOutput = await builder2.build(builder2.environments.prerender); | ||
| settings.timer.end("Prerender build"); | ||
| extractPrerenderEntryFileName(internals, prerenderOutput); | ||
| const prerenderOutputs = viteBuildReturnToRollupOutputs(prerenderOutput); | ||
| const prerenderChunks = extractRelevantChunks(prerenderOutputs, true); | ||
| prerenderOutput = void 0; | ||
| const ssrPlugins = builder2.environments[ASTRO_VITE_ENVIRONMENT_NAMES.ssr]?.config.plugins ?? []; | ||
@@ -244,0 +244,0 @@ buildPostHooks = ssrPlugins.map( |
@@ -1,2 +0,2 @@ | ||
| const ASTRO_VERSION = "6.0.4"; | ||
| const ASTRO_VERSION = "6.0.5"; | ||
| const ASTRO_GENERATOR = `Astro v${ASTRO_VERSION}`; | ||
@@ -3,0 +3,0 @@ const REROUTE_DIRECTIVE_HEADER = "X-Astro-Reroute"; |
@@ -29,3 +29,3 @@ import fs from "node:fs"; | ||
| const logger = restart.container.logger; | ||
| const currentVersion = "6.0.4"; | ||
| const currentVersion = "6.0.5"; | ||
| 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.4"}` | ||
| `v${"6.0.5"}` | ||
| )} ${headline}` | ||
@@ -275,0 +275,0 @@ ); |
| import type { RouteData } from '../../types/public/internal.js'; | ||
| import type { IntegrationResolvedRoute } from '../../types/public/integrations.js'; | ||
| import type { RouteInfo } from '../app/types.js'; | ||
@@ -34,2 +35,8 @@ import type { RoutesList } from '../../types/astro.js'; | ||
| export declare function getCustom500Route(manifestData: RoutesList): RouteData | undefined; | ||
| export declare function hasNonPrerenderedProjectRoute(routes: Array<Pick<RouteData, 'type' | 'origin' | 'prerender'>>, options?: { | ||
| includeEndpoints?: boolean; | ||
| }): boolean; | ||
| export declare function hasNonPrerenderedProjectRoute(routes: Array<Pick<IntegrationResolvedRoute, 'type' | 'origin' | 'isPrerendered'>>, options?: { | ||
| includeEndpoints?: boolean; | ||
| }): boolean; | ||
| export {}; |
@@ -28,2 +28,10 @@ import { isRoute404, isRoute500 } from "./internal/route-errors.js"; | ||
| } | ||
| function hasNonPrerenderedProjectRoute(routes, options) { | ||
| const includeEndpoints = options?.includeEndpoints ?? true; | ||
| const routeTypes = includeEndpoints ? ["page", "endpoint"] : ["page"]; | ||
| return routes.some((route) => { | ||
| const isPrerendered = "isPrerendered" in route ? route.isPrerendered : route.prerender; | ||
| return routeTypes.includes(route.type) && route.origin === "project" && !isPrerendered; | ||
| }); | ||
| } | ||
| export { | ||
@@ -33,4 +41,5 @@ getCustom404Route, | ||
| getFallbackRoute, | ||
| hasNonPrerenderedProjectRoute, | ||
| routeIsFallback, | ||
| routeIsRedirect | ||
| }; |
| import type { Plugin as VitePlugin } from 'vite'; | ||
| import type { AstroPluginOptions } from '../../types/astro.js'; | ||
| export declare const SERVER_ISLAND_MANIFEST = "virtual:astro:server-island-manifest"; | ||
| export declare const serverIslandPlaceholderMap = "'$$server-islands-map$$'"; | ||
| export declare const SERVER_ISLAND_MAP_MARKER = "$$server-islands-map$$"; | ||
| export declare function vitePluginServerIslands({ settings }: AstroPluginOptions): VitePlugin; |
@@ -1,6 +0,3 @@ | ||
| import fs from "node:fs"; | ||
| import { getPrerenderOutputDirectory, getServerOutputDirectory } from "../../prerender/utils.js"; | ||
| import { ASTRO_VITE_ENVIRONMENT_NAMES } from "../constants.js"; | ||
| import { AstroError, AstroErrorData } from "../errors/index.js"; | ||
| import { appendForwardSlash } from "../path.js"; | ||
| import { ASTRO_VITE_ENVIRONMENT_NAMES } from "../constants.js"; | ||
| const SERVER_ISLAND_MANIFEST = "virtual:astro:server-island-manifest"; | ||
@@ -10,2 +7,5 @@ const RESOLVED_SERVER_ISLAND_MANIFEST = "\0" + SERVER_ISLAND_MANIFEST; | ||
| const serverIslandPlaceholderNameMap = "'$$server-islands-name-map$$'"; | ||
| const SERVER_ISLAND_MAP_MARKER = "$$server-islands-map$$"; | ||
| const serverIslandMapReplaceExp = /['"]\$\$server-islands-map\$\$['"]/g; | ||
| const serverIslandNameMapReplaceExp = /['"]\$\$server-islands-name-map\$\$['"]/g; | ||
| function createServerIslandImportMapSource(entries, toImportPath) { | ||
@@ -26,7 +26,19 @@ const mappings = Array.from(entries, ([islandName, fileName]) => { | ||
| let ssrEnvironment = null; | ||
| const referenceIdMap = /* @__PURE__ */ new Map(); | ||
| const serverIslandMap = /* @__PURE__ */ new Map(); | ||
| const serverIslandNameMap = /* @__PURE__ */ new Map(); | ||
| const resolvedIslandImports = /* @__PURE__ */ new Map(); | ||
| let ssrManifestChunk = null; | ||
| 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); | ||
| const referenceId = ctx.emitFile({ | ||
| type: "chunk", | ||
| id: source?.id ?? resolvedPath, | ||
| importer: source?.importer, | ||
| name: islandName | ||
| }); | ||
| referenceIdMap.set(resolvedPath, referenceId); | ||
| } | ||
| } | ||
| return { | ||
@@ -38,2 +50,8 @@ name: "astro:server-islands", | ||
| }, | ||
| buildStart() { | ||
| if (command !== "build" || this.environment?.name !== ASTRO_VITE_ENVIRONMENT_NAMES.ssr) { | ||
| return; | ||
| } | ||
| ensureServerIslandReferenceIds(this); | ||
| }, | ||
| configureServer(server) { | ||
@@ -65,7 +83,3 @@ ssrEnvironment = server.environments[ASTRO_VITE_ENVIRONMENT_NAMES.ssr]; | ||
| id: { | ||
| include: [ | ||
| // Allows server islands in astro and mdx files | ||
| /\.(astro|mdx)$/, | ||
| new RegExp(`^${RESOLVED_SERVER_ISLAND_MANIFEST}$`) | ||
| ] | ||
| include: [/\.(astro|mdx)$/, new RegExp(`^${RESOLVED_SERVER_ISLAND_MANIFEST}$`)] | ||
| } | ||
@@ -76,2 +90,3 @@ }, | ||
| const astro = info ? info.meta.astro : void 0; | ||
| const isBuildSsr = command === "build" && this.environment?.name === ASTRO_VITE_ENVIRONMENT_NAMES.ssr; | ||
| if (astro) { | ||
@@ -85,6 +100,3 @@ for (const comp of astro.serverComponents) { | ||
| let idx = 1; | ||
| while (true) { | ||
| if (!serverIslandMap.has(name)) { | ||
| break; | ||
| } | ||
| while (serverIslandMap.has(name)) { | ||
| name += idx++; | ||
@@ -94,12 +106,15 @@ } | ||
| serverIslandMap.set(name, comp.resolvedPath); | ||
| if (command === "build") { | ||
| const referenceId = this.emitFile({ | ||
| type: "chunk", | ||
| id: comp.specifier, | ||
| importer: id, | ||
| name: comp.localName | ||
| }); | ||
| referenceIdMap.set(comp.resolvedPath, referenceId); | ||
| } | ||
| serverIslandSourceMap.set(comp.resolvedPath, { id: comp.specifier, importer: id }); | ||
| } | ||
| if (isBuildSsr && !referenceIdMap.has(comp.resolvedPath)) { | ||
| const islandName = serverIslandNameMap.get(comp.resolvedPath); | ||
| const source = serverIslandSourceMap.get(comp.resolvedPath); | ||
| const referenceId = this.emitFile({ | ||
| type: "chunk", | ||
| id: source?.id ?? comp.resolvedPath, | ||
| importer: source?.importer, | ||
| name: islandName | ||
| }); | ||
| referenceIdMap.set(comp.resolvedPath, referenceId); | ||
| } | ||
| } | ||
@@ -120,3 +135,3 @@ } | ||
| } | ||
| if (serverIslandNameMap.size > 0 && serverIslandMap.size > 0) { | ||
| if (command !== "build" && serverIslandNameMap.size > 0 && serverIslandMap.size > 0) { | ||
| const mapSource = createServerIslandImportMapSource( | ||
@@ -129,7 +144,6 @@ serverIslandMap, | ||
| code: ` | ||
| export const serverIslandMap = ${mapSource}; | ||
| export const serverIslandMap = ${mapSource}; | ||
| export const serverIslandNameMap = ${nameMapSource}; | ||
| ` | ||
| export const serverIslandNameMap = ${nameMapSource}; | ||
| ` | ||
| }; | ||
@@ -141,7 +155,7 @@ } | ||
| renderChunk(code, chunk) { | ||
| if (code.includes(serverIslandPlaceholderMap)) { | ||
| if (command === "build") { | ||
| if (referenceIdMap.size === 0) { | ||
| return; | ||
| } | ||
| if (!code.includes(SERVER_ISLAND_MAP_MARKER)) return; | ||
| if (command === "build") { | ||
| const envName = this.environment?.name; | ||
| let mapSource; | ||
| if (envName === ASTRO_VITE_ENVIRONMENT_NAMES.ssr) { | ||
| const isRelativeChunk = !chunk.isEntry; | ||
@@ -154,96 +168,21 @@ const dots = isRelativeChunk ? ".." : "."; | ||
| if (!islandName) continue; | ||
| if (!resolvedIslandImports.has(islandName)) { | ||
| resolvedIslandImports.set(islandName, fileName); | ||
| } | ||
| mapEntries.push([islandName, fileName]); | ||
| } | ||
| const mapSource = createServerIslandImportMapSource( | ||
| mapSource = createServerIslandImportMapSource( | ||
| mapEntries, | ||
| (fileName) => `${dots}/${fileName}` | ||
| ); | ||
| const nameMapSource = createNameMapSource(serverIslandNameMap); | ||
| return { | ||
| code: code.replace(serverIslandPlaceholderMap, mapSource).replace(serverIslandPlaceholderNameMap, nameMapSource), | ||
| map: null | ||
| }; | ||
| } else { | ||
| mapSource = createServerIslandImportMapSource(serverIslandMap, (fileName) => fileName); | ||
| } | ||
| const nameMapSource = createNameMapSource(serverIslandNameMap); | ||
| return { | ||
| code: code.replace(serverIslandPlaceholderMap, "new Map();").replace(serverIslandPlaceholderNameMap, "new Map()"), | ||
| code: code.replace(serverIslandMapReplaceExp, mapSource).replace(serverIslandNameMapReplaceExp, nameMapSource), | ||
| map: null | ||
| }; | ||
| } | ||
| }, | ||
| generateBundle(_options, bundle) { | ||
| const envName = this.environment?.name; | ||
| if (envName === ASTRO_VITE_ENVIRONMENT_NAMES.ssr) { | ||
| for (const chunk of Object.values(bundle)) { | ||
| if (chunk.type === "chunk" && chunk.code.includes(serverIslandPlaceholderMap)) { | ||
| ssrManifestChunk = chunk; | ||
| break; | ||
| } | ||
| } | ||
| } | ||
| if (envName === ASTRO_VITE_ENVIRONMENT_NAMES.prerender && ssrManifestChunk) { | ||
| if (resolvedIslandImports.size > 0) { | ||
| const isRelativeChunk = ssrManifestChunk.fileName.includes("/"); | ||
| const dots = isRelativeChunk ? ".." : "."; | ||
| const mapSource = createServerIslandImportMapSource( | ||
| resolvedIslandImports, | ||
| (fileName) => `${dots}/${fileName}` | ||
| ); | ||
| const nameMapSource = createNameMapSource(serverIslandNameMap); | ||
| ssrManifestChunk.code = ssrManifestChunk.code.replace(serverIslandPlaceholderMap, mapSource).replace(serverIslandPlaceholderNameMap, nameMapSource); | ||
| } else { | ||
| ssrManifestChunk.code = ssrManifestChunk.code.replace(serverIslandPlaceholderMap, "new Map()").replace(serverIslandPlaceholderNameMap, "new Map()"); | ||
| } | ||
| } | ||
| }, | ||
| api: { | ||
| /** | ||
| * Post-build hook that patches SSR chunks containing server island placeholders. | ||
| * | ||
| * During build, SSR can run before all server islands are discovered (e.g. islands | ||
| * only used in prerendered pages). This hook runs after SSR + prerender builds and: | ||
| * 1) replaces placeholders with the complete map of discovered islands | ||
| * 2) copies island chunks emitted in prerender into the SSR output directory | ||
| * | ||
| * Two cases: | ||
| * 1. Islands were discovered: Replace placeholders with real import maps. | ||
| * 2. No islands found: Replace placeholders with empty maps. | ||
| */ | ||
| async buildPostHook({ | ||
| chunks, | ||
| mutate | ||
| }) { | ||
| const ssrChunkWithPlaceholder = chunks.find( | ||
| (c) => !c.prerender && c.code.includes(serverIslandPlaceholderMap) | ||
| ); | ||
| if (!ssrChunkWithPlaceholder) { | ||
| return; | ||
| } | ||
| if (resolvedIslandImports.size > 0) { | ||
| const isRelativeChunk = ssrChunkWithPlaceholder.fileName.includes("/"); | ||
| const dots = isRelativeChunk ? ".." : "."; | ||
| const mapSource = createServerIslandImportMapSource( | ||
| resolvedIslandImports, | ||
| (fileName) => `${dots}/${fileName}` | ||
| ); | ||
| const nameMapSource = createNameMapSource(serverIslandNameMap); | ||
| const newCode = ssrChunkWithPlaceholder.code.replace(serverIslandPlaceholderMap, mapSource).replace(serverIslandPlaceholderNameMap, nameMapSource); | ||
| mutate(ssrChunkWithPlaceholder.fileName, newCode, false); | ||
| const serverOutputDir = getServerOutputDirectory(settings); | ||
| const prerenderOutputDir = getPrerenderOutputDirectory(settings); | ||
| for (const [, fileName] of resolvedIslandImports) { | ||
| const srcPath = new URL(fileName, appendForwardSlash(prerenderOutputDir.toString())); | ||
| const destPath = new URL(fileName, appendForwardSlash(serverOutputDir.toString())); | ||
| if (!fs.existsSync(srcPath)) continue; | ||
| const destDir = new URL("./", destPath); | ||
| await fs.promises.mkdir(destDir, { recursive: true }); | ||
| await fs.promises.copyFile(srcPath, destPath); | ||
| } | ||
| } else { | ||
| const newCode = ssrChunkWithPlaceholder.code.replace(serverIslandPlaceholderMap, "new Map()").replace(serverIslandPlaceholderNameMap, "new Map()"); | ||
| mutate(ssrChunkWithPlaceholder.fileName, newCode, false); | ||
| } | ||
| } | ||
| return { | ||
| code: code.replace(serverIslandMapReplaceExp, "new Map();").replace(serverIslandNameMapReplaceExp, "new Map()"), | ||
| map: null | ||
| }; | ||
| } | ||
@@ -254,4 +193,4 @@ }; | ||
| SERVER_ISLAND_MANIFEST, | ||
| serverIslandPlaceholderMap, | ||
| SERVER_ISLAND_MAP_MARKER, | ||
| vitePluginServerIslands | ||
| }; |
@@ -22,3 +22,3 @@ import { AsyncLocalStorage } from "node:async_hooks"; | ||
| import { createViteLoader } from "../core/module-loader/index.js"; | ||
| import { matchAllRoutes } from "../core/routing/match.js"; | ||
| import { isRouteServerIsland, matchAllRoutes } from "../core/routing/match.js"; | ||
| import { resolveMiddlewareMode } from "../integrations/adapter-utils.js"; | ||
@@ -134,3 +134,3 @@ import { SERIALIZED_MANIFEST_ID } from "../manifest/serialized.js"; | ||
| const matches = matchAllRoutes(pathname, routesList); | ||
| if (!matches.some((route) => route.prerender)) { | ||
| if (!matches.some((route) => route.prerender || isRouteServerIsland(route))) { | ||
| return next(); | ||
@@ -137,0 +137,0 @@ } |
| import { ASTRO_VITE_ENVIRONMENT_NAMES } from "../core/constants.js"; | ||
| import { hasNonPrerenderedProjectRoute } from "../core/routing/helpers.js"; | ||
| const ASTRO_RENDERERS_MODULE_ID = "virtual:astro:renderers"; | ||
| const RESOLVED_ASTRO_RENDERERS_MODULE_ID = `\0${ASTRO_RENDERERS_MODULE_ID}`; | ||
| function ssrBuildNeedsRenderers(routesList) { | ||
| return routesList.routes.some( | ||
| (route) => route.type === "page" && !route.prerender && route.origin !== "internal" | ||
| ); | ||
| } | ||
| function vitePluginRenderers(options) { | ||
@@ -27,3 +23,5 @@ const renderers = options.settings.renderers; | ||
| handler() { | ||
| if (options.command === "build" && this.environment.name === ASTRO_VITE_ENVIRONMENT_NAMES.ssr && renderers.length > 0 && !ssrBuildNeedsRenderers(options.routesList)) { | ||
| if (options.command === "build" && this.environment.name === ASTRO_VITE_ENVIRONMENT_NAMES.ssr && renderers.length > 0 && !hasNonPrerenderedProjectRoute(options.routesList.routes, { | ||
| includeEndpoints: false | ||
| })) { | ||
| return { code: `export const renderers = [];` }; | ||
@@ -30,0 +28,0 @@ } |
@@ -41,3 +41,3 @@ import { ASTRO_VITE_ENVIRONMENT_NAMES } from "../core/constants.js"; | ||
| const hasHydrationScripts = settings.scripts.some((s) => s.stage === "before-hydration"); | ||
| if (hasHydrationScripts && (this.environment.name === ASTRO_VITE_ENVIRONMENT_NAMES.prerender || this.environment.name === ASTRO_VITE_ENVIRONMENT_NAMES.ssr)) { | ||
| if (hasHydrationScripts && (this.environment.name === ASTRO_VITE_ENVIRONMENT_NAMES.client || this.environment.name === ASTRO_VITE_ENVIRONMENT_NAMES.prerender || this.environment.name === ASTRO_VITE_ENVIRONMENT_NAMES.ssr)) { | ||
| this.emitFile({ | ||
@@ -44,0 +44,0 @@ type: "chunk", |
+3
-3
| { | ||
| "name": "astro", | ||
| "version": "6.0.4", | ||
| "version": "6.0.5", | ||
| "description": "Astro is a modern site builder with web best practices, performance, and DX front-of-mind.", | ||
@@ -156,4 +156,4 @@ "type": "module", | ||
| "zod": "^4.3.6", | ||
| "@astrojs/markdown-remark": "7.0.0", | ||
| "@astrojs/internal-helpers": "0.8.0", | ||
| "@astrojs/markdown-remark": "7.0.0", | ||
| "@astrojs/telemetry": "3.3.0" | ||
@@ -194,3 +194,3 @@ }, | ||
| "vitest": "^3.2.4", | ||
| "@astrojs/check": "0.9.7", | ||
| "@astrojs/check": "0.9.8", | ||
| "astro-scripts": "0.0.14" | ||
@@ -197,0 +197,0 @@ }, |
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
68633
02599197
0