astro 4.8.6 → 4.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/astro-jsx.d.ts +1 -1
  2. package/dist/@types/astro.d.ts +43 -96
  3. package/dist/actions/runtime/middleware.d.ts +1 -0
  4. package/dist/actions/runtime/middleware.js +44 -12
  5. package/dist/actions/runtime/route.js +1 -2
  6. package/dist/actions/runtime/utils.d.ts +6 -1
  7. package/dist/actions/runtime/utils.js +2 -1
  8. package/dist/actions/runtime/virtual/server.d.ts +4 -2
  9. package/dist/actions/runtime/virtual/server.js +9 -11
  10. package/dist/actions/utils.d.ts +2 -0
  11. package/dist/actions/utils.js +2 -1
  12. package/dist/container/index.d.ts +162 -0
  13. package/dist/container/index.js +234 -0
  14. package/dist/container/pipeline.d.ts +11 -0
  15. package/dist/container/pipeline.js +96 -0
  16. package/dist/core/app/node.js +4 -1
  17. package/dist/core/build/consts.d.ts +1 -0
  18. package/dist/core/build/consts.js +3 -1
  19. package/dist/core/build/generate.js +3 -3
  20. package/dist/core/build/index.js +2 -2
  21. package/dist/core/build/plugins/plugin-content.d.ts +1 -1
  22. package/dist/core/build/plugins/plugin-content.js +13 -2
  23. package/dist/core/build/plugins/plugin-manifest.js +2 -2
  24. package/dist/core/build/static-build.d.ts +2 -1
  25. package/dist/core/build/static-build.js +7 -6
  26. package/dist/core/config/schema.d.ts +92 -120
  27. package/dist/core/config/schema.js +18 -23
  28. package/dist/core/constants.js +1 -1
  29. package/dist/core/dev/dev.js +1 -1
  30. package/dist/core/messages.js +2 -2
  31. package/dist/core/render-context.d.ts +1 -1
  32. package/dist/core/render-context.js +6 -3
  33. package/dist/core/routing/manifest/create.d.ts +4 -1
  34. package/dist/core/routing/manifest/create.js +10 -8
  35. package/dist/i18n/utils.d.ts +1 -1
  36. package/dist/integrations/features-validation.js +1 -1
  37. package/dist/runtime/client/dev-toolbar/apps/utils/highlight.js +2 -0
  38. package/dist/runtime/server/jsx.js +1 -0
  39. package/dist/vite-plugin-astro-server/plugin.d.ts +0 -1
  40. package/dist/vite-plugin-astro-server/plugin.js +1 -1
  41. package/package.json +7 -3
  42. package/templates/actions.mjs +37 -12
@@ -0,0 +1,234 @@
1
+ import { posix } from "node:path";
2
+ import { validateConfig } from "../core/config/config.js";
3
+ import { ASTRO_CONFIG_DEFAULTS } from "../core/config/schema.js";
4
+ import { Logger } from "../core/logger/core.js";
5
+ import { nodeLogDestination } from "../core/logger/node.js";
6
+ import { removeLeadingForwardSlash } from "../core/path.js";
7
+ import { RenderContext } from "../core/render-context.js";
8
+ import { getParts, getPattern, validateSegment } from "../core/routing/manifest/create.js";
9
+ import { ContainerPipeline } from "./pipeline.js";
10
+ function createManifest(renderers, manifest, middleware) {
11
+ const defaultMiddleware = (_, next) => {
12
+ return next();
13
+ };
14
+ return {
15
+ rewritingEnabled: false,
16
+ trailingSlash: manifest?.trailingSlash ?? ASTRO_CONFIG_DEFAULTS.trailingSlash,
17
+ buildFormat: manifest?.buildFormat ?? ASTRO_CONFIG_DEFAULTS.build.format,
18
+ compressHTML: manifest?.compressHTML ?? ASTRO_CONFIG_DEFAULTS.compressHTML,
19
+ assets: manifest?.assets ?? /* @__PURE__ */ new Set(),
20
+ assetsPrefix: manifest?.assetsPrefix ?? void 0,
21
+ entryModules: manifest?.entryModules ?? {},
22
+ routes: manifest?.routes ?? [],
23
+ adapterName: "",
24
+ clientDirectives: manifest?.clientDirectives ?? /* @__PURE__ */ new Map(),
25
+ renderers: manifest?.renderers ?? renderers,
26
+ base: manifest?.base ?? ASTRO_CONFIG_DEFAULTS.base,
27
+ componentMetadata: manifest?.componentMetadata ?? /* @__PURE__ */ new Map(),
28
+ inlinedScripts: manifest?.inlinedScripts ?? /* @__PURE__ */ new Map(),
29
+ i18n: manifest?.i18n,
30
+ checkOrigin: false,
31
+ middleware: manifest?.middleware ?? middleware ?? defaultMiddleware
32
+ };
33
+ }
34
+ class experimental_AstroContainer {
35
+ #pipeline;
36
+ /**
37
+ * Internally used to check if the container was created with a manifest.
38
+ * @private
39
+ */
40
+ #withManifest = false;
41
+ constructor({
42
+ streaming = false,
43
+ renderers = [],
44
+ manifest,
45
+ resolve
46
+ }) {
47
+ this.#pipeline = ContainerPipeline.create({
48
+ logger: new Logger({
49
+ level: "info",
50
+ dest: nodeLogDestination
51
+ }),
52
+ manifest: createManifest(renderers, manifest),
53
+ streaming,
54
+ serverLike: true,
55
+ renderers,
56
+ resolve: async (specifier) => {
57
+ if (this.#withManifest) {
58
+ return this.#containerResolve(specifier);
59
+ } else if (resolve) {
60
+ return resolve(specifier);
61
+ }
62
+ return specifier;
63
+ }
64
+ });
65
+ }
66
+ async #containerResolve(specifier) {
67
+ const found = this.#pipeline.manifest.entryModules[specifier];
68
+ if (found) {
69
+ return new URL(found, ASTRO_CONFIG_DEFAULTS.build.client).toString();
70
+ }
71
+ return found;
72
+ }
73
+ /**
74
+ * Creates a new instance of a container.
75
+ *
76
+ * @param {AstroContainerOptions=} containerOptions
77
+ */
78
+ static async create(containerOptions = {}) {
79
+ const { streaming = false, renderers = [] } = containerOptions;
80
+ const loadedRenderers = await Promise.all(
81
+ renderers.map(async (renderer) => {
82
+ const mod = await import(renderer.serverEntrypoint);
83
+ if (typeof mod.default !== "undefined") {
84
+ return {
85
+ ...renderer,
86
+ ssr: mod.default
87
+ };
88
+ }
89
+ return void 0;
90
+ })
91
+ );
92
+ const finalRenderers = loadedRenderers.filter((r) => Boolean(r));
93
+ return new experimental_AstroContainer({ streaming, renderers: finalRenderers });
94
+ }
95
+ // NOTE: we keep this private via TS instead via `#` so it's still available on the surface, so we can play with it.
96
+ // @ematipico: I plan to use it for a possible integration that could help people
97
+ static async createFromManifest(manifest) {
98
+ const config = await validateConfig(ASTRO_CONFIG_DEFAULTS, process.cwd(), "container");
99
+ const container = new experimental_AstroContainer({
100
+ manifest
101
+ });
102
+ container.#withManifest = true;
103
+ return container;
104
+ }
105
+ #insertRoute({
106
+ path,
107
+ componentInstance,
108
+ params = {},
109
+ type = "page"
110
+ }) {
111
+ const pathUrl = new URL(path, "https://example.com");
112
+ const routeData = this.#createRoute(pathUrl, params, type);
113
+ this.#pipeline.manifest.routes.push({
114
+ routeData,
115
+ file: "",
116
+ links: [],
117
+ styles: [],
118
+ scripts: []
119
+ });
120
+ this.#pipeline.insertRoute(routeData, componentInstance);
121
+ return routeData;
122
+ }
123
+ /**
124
+ * @description
125
+ * It renders a component and returns the result as a string.
126
+ *
127
+ * ## Example
128
+ *
129
+ * ```js
130
+ * import Card from "../src/components/Card.astro";
131
+ *
132
+ * const container = await AstroContainer.create();
133
+ * const result = await container.renderToString(Card);
134
+ *
135
+ * console.log(result); // it's a string
136
+ * ```
137
+ *
138
+ *
139
+ * @param {AstroComponentFactory} component The instance of the component.
140
+ * @param {ContainerRenderOptions=} options Possible options to pass when rendering the component.
141
+ */
142
+ async renderToString(component, options = {}) {
143
+ const response = await this.renderToResponse(component, options);
144
+ return await response.text();
145
+ }
146
+ /**
147
+ * @description
148
+ * It renders a component and returns the `Response` as result of the rendering phase.
149
+ *
150
+ * ## Example
151
+ *
152
+ * ```js
153
+ * import Card from "../src/components/Card.astro";
154
+ *
155
+ * const container = await AstroContainer.create();
156
+ * const response = await container.renderToResponse(Card);
157
+ *
158
+ * console.log(response.status); // it's a number
159
+ * ```
160
+ *
161
+ *
162
+ * @param {AstroComponentFactory} component The instance of the component.
163
+ * @param {ContainerRenderOptions=} options Possible options to pass when rendering the component.
164
+ */
165
+ async renderToResponse(component, options = {}) {
166
+ const { routeType = "page", slots } = options;
167
+ const request = options?.request ?? new Request("https://example.com/");
168
+ const url = new URL(request.url);
169
+ const componentInstance = routeType === "endpoint" ? component : this.#wrapComponent(component, options.params);
170
+ const routeData = this.#insertRoute({
171
+ path: request.url,
172
+ componentInstance,
173
+ params: options.params,
174
+ type: routeType
175
+ });
176
+ const renderContext = RenderContext.create({
177
+ pipeline: this.#pipeline,
178
+ routeData,
179
+ status: 200,
180
+ middleware: this.#pipeline.middleware,
181
+ request,
182
+ pathname: url.pathname,
183
+ locals: options?.locals ?? {}
184
+ });
185
+ if (options.params) {
186
+ renderContext.params = options.params;
187
+ }
188
+ return renderContext.render(componentInstance, slots);
189
+ }
190
+ #createRoute(url, params, type) {
191
+ const segments = removeLeadingForwardSlash(url.pathname).split(posix.sep).filter(Boolean).map((s) => {
192
+ validateSegment(s);
193
+ return getParts(s, url.pathname);
194
+ });
195
+ return {
196
+ route: url.pathname,
197
+ component: "",
198
+ generate(_data) {
199
+ return "";
200
+ },
201
+ params: Object.keys(params),
202
+ pattern: getPattern(
203
+ segments,
204
+ ASTRO_CONFIG_DEFAULTS.base,
205
+ ASTRO_CONFIG_DEFAULTS.trailingSlash
206
+ ),
207
+ prerender: false,
208
+ segments,
209
+ type,
210
+ fallbackRoutes: [],
211
+ isIndex: false
212
+ };
213
+ }
214
+ /**
215
+ * If the provided component isn't a default export, the function wraps it in an object `{default: Component }` to mimic the default export.
216
+ * @param componentFactory
217
+ * @param params
218
+ * @private
219
+ */
220
+ #wrapComponent(componentFactory, params) {
221
+ if (params) {
222
+ return {
223
+ default: componentFactory,
224
+ getStaticPaths() {
225
+ return [{ params }];
226
+ }
227
+ };
228
+ }
229
+ return { default: componentFactory };
230
+ }
231
+ }
232
+ export {
233
+ experimental_AstroContainer
234
+ };
@@ -0,0 +1,11 @@
1
+ import type { ComponentInstance, RewritePayload, RouteData, SSRResult } from '../@types/astro.js';
2
+ import { type HeadElements, Pipeline } from '../core/base-pipeline.js';
3
+ export declare class ContainerPipeline extends Pipeline {
4
+ #private;
5
+ static create({ logger, manifest, renderers, resolve, serverLike, streaming, }: Pick<ContainerPipeline, 'logger' | 'manifest' | 'renderers' | 'resolve' | 'serverLike' | 'streaming'>): ContainerPipeline;
6
+ componentMetadata(_routeData: RouteData): Promise<SSRResult['componentMetadata']> | void;
7
+ headElements(routeData: RouteData): Promise<HeadElements> | HeadElements;
8
+ tryRewrite(rewritePayload: RewritePayload): Promise<[RouteData, ComponentInstance]>;
9
+ insertRoute(route: RouteData, componentInstance: ComponentInstance): void;
10
+ getComponentByRoute(_routeData: RouteData): Promise<ComponentInstance>;
11
+ }
@@ -0,0 +1,96 @@
1
+ import { Pipeline } from "../core/base-pipeline.js";
2
+ import { RouteNotFound } from "../core/errors/errors-data.js";
3
+ import { AstroError } from "../core/errors/index.js";
4
+ import {
5
+ createModuleScriptElement,
6
+ createStylesheetElementSet
7
+ } from "../core/render/ssr-element.js";
8
+ class ContainerPipeline extends Pipeline {
9
+ /**
10
+ * Internal cache to store components instances by `RouteData`.
11
+ * @private
12
+ */
13
+ #componentsInterner = /* @__PURE__ */ new WeakMap();
14
+ static create({
15
+ logger,
16
+ manifest,
17
+ renderers,
18
+ resolve,
19
+ serverLike,
20
+ streaming
21
+ }) {
22
+ return new ContainerPipeline(
23
+ logger,
24
+ manifest,
25
+ "development",
26
+ renderers,
27
+ resolve,
28
+ serverLike,
29
+ streaming
30
+ );
31
+ }
32
+ componentMetadata(_routeData) {
33
+ }
34
+ headElements(routeData) {
35
+ const routeInfo = this.manifest.routes.find((route) => route.routeData === routeData);
36
+ const links = /* @__PURE__ */ new Set();
37
+ const scripts = /* @__PURE__ */ new Set();
38
+ const styles = createStylesheetElementSet(routeInfo?.styles ?? []);
39
+ for (const script of routeInfo?.scripts ?? []) {
40
+ if ("stage" in script) {
41
+ if (script.stage === "head-inline") {
42
+ scripts.add({
43
+ props: {},
44
+ children: script.children
45
+ });
46
+ }
47
+ } else {
48
+ scripts.add(createModuleScriptElement(script));
49
+ }
50
+ }
51
+ return { links, styles, scripts };
52
+ }
53
+ async tryRewrite(rewritePayload) {
54
+ let foundRoute;
55
+ for (const route of this.manifest.routes) {
56
+ const routeData = route.routeData;
57
+ if (rewritePayload instanceof URL) {
58
+ if (routeData.pattern.test(rewritePayload.pathname)) {
59
+ foundRoute = routeData;
60
+ break;
61
+ }
62
+ } else if (rewritePayload instanceof Request) {
63
+ const url = new URL(rewritePayload.url);
64
+ if (routeData.pattern.test(url.pathname)) {
65
+ foundRoute = routeData;
66
+ break;
67
+ }
68
+ } else if (routeData.pattern.test(decodeURI(rewritePayload))) {
69
+ foundRoute = routeData;
70
+ break;
71
+ }
72
+ }
73
+ if (foundRoute) {
74
+ const componentInstance = await this.getComponentByRoute(foundRoute);
75
+ return [foundRoute, componentInstance];
76
+ } else {
77
+ throw new AstroError(RouteNotFound);
78
+ }
79
+ }
80
+ insertRoute(route, componentInstance) {
81
+ this.#componentsInterner.set(route, {
82
+ page() {
83
+ return Promise.resolve(componentInstance);
84
+ },
85
+ renderers: this.manifest.renderers,
86
+ onRequest: this.manifest.middleware
87
+ });
88
+ }
89
+ // At the moment it's not used by the container via any public API
90
+ // @ts-expect-error It needs to be implemented.
91
+ async getComponentByRoute(_routeData) {
92
+ }
93
+ }
94
+ export {
95
+ ContainerPipeline
96
+ };
@@ -48,7 +48,10 @@ class NodeApp extends App {
48
48
  Object.assign(options, makeRequestBody(req));
49
49
  }
50
50
  const request = new Request(url, options);
51
- if (req.socket?.remoteAddress) {
51
+ const clientIp = req.headers["x-forwarded-for"];
52
+ if (clientIp) {
53
+ Reflect.set(request, clientAddressSymbol, clientIp);
54
+ } else if (req.socket?.remoteAddress) {
52
55
  Reflect.set(request, clientAddressSymbol, req.socket.remoteAddress);
53
56
  }
54
57
  return request;
@@ -1 +1,2 @@
1
1
  export declare const CHUNKS_PATH = "chunks/";
2
+ export declare const CONTENT_PATH = "content/";
@@ -1,4 +1,6 @@
1
1
  const CHUNKS_PATH = "chunks/";
2
+ const CONTENT_PATH = "content/";
2
3
  export {
3
- CHUNKS_PATH
4
+ CHUNKS_PATH,
5
+ CONTENT_PATH
4
6
  };
@@ -91,7 +91,7 @@ ${bgGreen(black(` ${verb} static routes `))}`);
91
91
  if (ssr) {
92
92
  for (const [pageData, filePath] of pagesToGenerate) {
93
93
  if (pageData.route.prerender) {
94
- if (config.experimental.i18nDomains) {
94
+ if (config.i18n?.domains && Object.keys(config.i18n.domains).length > 0) {
95
95
  throw new AstroError({
96
96
  ...NoPrerenderedRoutesWithDomains,
97
97
  message: NoPrerenderedRoutesWithDomains.message(pageData.component)
@@ -210,7 +210,7 @@ async function getPathsForRoute(route, mod, pipeline, builtPaths) {
210
210
  const label = staticPaths.length === 1 ? "page" : "pages";
211
211
  logger.debug(
212
212
  "build",
213
- `\u251C\u2500\u2500 ${bold(green("\u2714"))} ${route.component} \u2192 ${magenta(`[${staticPaths.length} ${label}]`)}`
213
+ `\u251C\u2500\u2500 ${bold(green("\u221A"))} ${route.component} \u2192 ${magenta(`[${staticPaths.length} ${label}]`)}`
214
214
  );
215
215
  paths = staticPaths.map((staticPath) => {
216
216
  try {
@@ -388,7 +388,7 @@ function createBuildManifest(settings, internals, renderers, middleware) {
388
388
  buildFormat: settings.config.build.format,
389
389
  middleware,
390
390
  rewritingEnabled: settings.config.experimental.rewriting,
391
- checkOrigin: settings.config.experimental.security?.csrfProtection?.origin ?? false
391
+ checkOrigin: settings.config.security?.checkOrigin ?? false
392
392
  };
393
393
  }
394
394
  export {
@@ -129,8 +129,8 @@ class AstroBuilder {
129
129
  teardownCompiler: this.teardownCompiler,
130
130
  viteConfig
131
131
  };
132
- const { internals, ssrOutputChunkNames } = await viteBuild(opts);
133
- await staticBuild(opts, internals, ssrOutputChunkNames);
132
+ const { internals, ssrOutputChunkNames, contentFileNames } = await viteBuild(opts);
133
+ await staticBuild(opts, internals, ssrOutputChunkNames, contentFileNames);
134
134
  this.timer.assetsStart = performance.now();
135
135
  Object.keys(assets).map((k) => {
136
136
  if (!assets[k]) return;
@@ -1,5 +1,5 @@
1
1
  import { type BuildInternals } from '../internal.js';
2
2
  import type { AstroBuildPlugin } from '../plugin.js';
3
3
  import type { StaticBuildOptions } from '../types.js';
4
- export declare function copyContentToCache(opts: StaticBuildOptions): Promise<void>;
4
+ export declare function copyContentToCache(opts: StaticBuildOptions): Promise<string[]>;
5
5
  export declare function pluginContent(opts: StaticBuildOptions, internals: BuildInternals): AstroBuildPlugin;
@@ -1,6 +1,7 @@
1
1
  import { createHash } from "node:crypto";
2
2
  import fsMod from "node:fs";
3
3
  import { fileURLToPath } from "node:url";
4
+ import glob from "fast-glob";
4
5
  import pLimit from "p-limit";
5
6
  import { normalizePath } from "vite";
6
7
  import { CONTENT_RENDER_FLAG, PROPAGATED_ASSET_FLAG } from "../../../content/consts.js";
@@ -19,12 +20,12 @@ import {
19
20
  } from "../../path.js";
20
21
  import { isContentCollectionsCacheEnabled } from "../../util.js";
21
22
  import { addRollupInput } from "../add-rollup-input.js";
22
- import { CHUNKS_PATH } from "../consts.js";
23
+ import { CHUNKS_PATH, CONTENT_PATH } from "../consts.js";
23
24
  import {} from "../internal.js";
24
25
  import { copyFiles } from "../static-build.js";
25
26
  import { encodeName } from "../util.js";
26
27
  import { extendManualChunks } from "./util.js";
27
- const CONTENT_CACHE_DIR = "./content/";
28
+ const CONTENT_CACHE_DIR = "./" + CONTENT_PATH;
28
29
  const CONTENT_MANIFEST_FILE = "./manifest.json";
29
30
  const CONTENT_MANIFEST_VERSION = 1;
30
31
  const virtualEmptyModuleId = `virtual:empty-content`;
@@ -340,7 +341,17 @@ async function copyContentToCache(opts) {
340
341
  await fsMod.promises.mkdir(cacheTmp, { recursive: true });
341
342
  await copyFiles(distContentRoot, cacheTmp, true);
342
343
  await copyFiles(cacheTmp, contentCacheDir);
344
+ let files = [];
345
+ await Promise.all([
346
+ glob(`**/*.{mjs,json}`, {
347
+ cwd: fileURLToPath(cacheTmp)
348
+ }).then((f) => files.push(...f.map((file) => CONTENT_PATH + file))),
349
+ glob(`**/*.{mjs,json}`, {
350
+ cwd: fileURLToPath(new URL("./" + CHUNKS_PATH, config.outDir))
351
+ }).then((f) => files.push(...f.map((file) => CHUNKS_PATH + file)))
352
+ ]);
343
353
  await fsMod.promises.rm(cacheTmp, { recursive: true, force: true });
354
+ return files;
344
355
  }
345
356
  function pluginContent(opts, internals) {
346
357
  const { cacheDir, outDir } = opts.settings.config;
@@ -178,7 +178,7 @@ function buildManifest(opts, internals, staticFiles) {
178
178
  });
179
179
  }
180
180
  const i18n = settings.config.i18n;
181
- if (settings.config.experimental.i18nDomains && i18n && i18n.domains) {
181
+ if (i18n && i18n.domains) {
182
182
  for (const [locale, domainValue] of Object.entries(i18n.domains)) {
183
183
  domainLookupTable[domainValue] = normalizeTheLocale(locale);
184
184
  }
@@ -212,7 +212,7 @@ function buildManifest(opts, internals, staticFiles) {
212
212
  assets: staticFiles.map(prefixAssetPath),
213
213
  i18n: i18nManifest,
214
214
  buildFormat: settings.config.build.format,
215
- checkOrigin: settings.config.experimental.security?.csrfProtection?.origin ?? false,
215
+ checkOrigin: settings.config.security?.checkOrigin ?? false,
216
216
  rewritingEnabled: settings.config.experimental.rewriting
217
217
  };
218
218
  }
@@ -4,8 +4,9 @@ import type { StaticBuildOptions } from './types.js';
4
4
  export declare function viteBuild(opts: StaticBuildOptions): Promise<{
5
5
  internals: BuildInternals;
6
6
  ssrOutputChunkNames: string[];
7
+ contentFileNames: string[] | undefined;
7
8
  }>;
8
- export declare function staticBuild(opts: StaticBuildOptions, internals: BuildInternals, ssrOutputChunkNames: string[]): Promise<void>;
9
+ export declare function staticBuild(opts: StaticBuildOptions, internals: BuildInternals, ssrOutputChunkNames: string[], contentFileNames?: string[]): Promise<void>;
9
10
  export declare function copyFiles(fromFolder: URL, toFolder: URL, includeDotfiles?: boolean): Promise<void[] | undefined>;
10
11
  /**
11
12
  * This function takes the virtual module name of any page entrypoint and
@@ -75,8 +75,9 @@ async function viteBuild(opts) {
75
75
  const ssrOutputs = viteBuildReturnToRollupOutputs(ssrOutput);
76
76
  const clientOutputs = viteBuildReturnToRollupOutputs(clientOutput ?? []);
77
77
  await runPostBuildHooks(container, ssrOutputs, clientOutputs);
78
+ let contentFileNames = void 0;
78
79
  if (opts.settings.config.experimental.contentCollectionCache) {
79
- await copyContentToCache(opts);
80
+ contentFileNames = await copyContentToCache(opts);
80
81
  }
81
82
  settings.timer.end("Client build");
82
83
  internals.ssrEntryChunk = void 0;
@@ -91,15 +92,15 @@ async function viteBuild(opts) {
91
92
  }
92
93
  }
93
94
  }
94
- return { internals, ssrOutputChunkNames };
95
+ return { internals, ssrOutputChunkNames, contentFileNames };
95
96
  }
96
- async function staticBuild(opts, internals, ssrOutputChunkNames) {
97
+ async function staticBuild(opts, internals, ssrOutputChunkNames, contentFileNames) {
97
98
  const { settings } = opts;
98
99
  switch (true) {
99
100
  case settings.config.output === "static": {
100
101
  settings.timer.start("Static generate");
101
102
  await generatePages(opts, internals);
102
- await cleanServerOutput(opts, ssrOutputChunkNames, internals);
103
+ await cleanServerOutput(opts, ssrOutputChunkNames, contentFileNames, internals);
103
104
  settings.timer.end("Static generate");
104
105
  return;
105
106
  }
@@ -325,9 +326,9 @@ export const ${e.n} = noop;`;
325
326
  removeEmptyDirs(out);
326
327
  }
327
328
  }
328
- async function cleanServerOutput(opts, ssrOutputChunkNames, internals) {
329
+ async function cleanServerOutput(opts, ssrOutputChunkNames, contentFileNames, internals) {
329
330
  const out = getOutDirWithinCwd(opts.settings.config.outDir);
330
- const files = ssrOutputChunkNames.filter((f) => f.endsWith(".mjs"));
331
+ const files = ssrOutputChunkNames.filter((f) => f.endsWith(".mjs")).concat(contentFileNames ?? []);
331
332
  if (internals.manifestFileName) {
332
333
  files.push(internals.manifestFileName);
333
334
  }