Socket
Book a DemoSign in
Socket

astro

Package Overview
Dependencies
Maintainers
2
Versions
1309
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

astro - npm Package Compare versions

Comparing version
6.0.4
to
6.0.5
+9
-6
dist/actions/integration.js
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 @@ }

+2
-1

@@ -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",

{
"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 @@ },