@kasperpeulen/vitest-plugin-nextjs 0.0.0-alpha.0 → 0.1.0-alpha.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 (250) hide show
  1. package/README.md +249 -2
  2. package/dist/_virtual/_rolldown/runtime.js +14 -0
  3. package/dist/action-ids.d.ts +18 -0
  4. package/dist/action-ids.js +44 -0
  5. package/dist/adapter.d.ts +8 -0
  6. package/dist/adapter.js +12 -0
  7. package/dist/app-requests.d.ts +63 -0
  8. package/dist/app-requests.js +253 -0
  9. package/dist/browser-context.d.ts +24 -0
  10. package/dist/browser-context.js +157 -0
  11. package/dist/build-output.d.ts +68 -0
  12. package/dist/build-output.js +216 -0
  13. package/dist/build.d.ts +26 -0
  14. package/dist/build.js +39 -0
  15. package/dist/built-files.d.ts +9 -0
  16. package/dist/built-files.js +22 -0
  17. package/dist/cache.d.ts +44 -0
  18. package/dist/cache.js +99 -0
  19. package/dist/client-components.d.ts +3 -0
  20. package/dist/client-components.js +4 -0
  21. package/dist/client-file-key.d.ts +5 -0
  22. package/dist/client-file-key.js +5 -0
  23. package/dist/client-files.d.ts +83 -0
  24. package/dist/client-files.js +186 -0
  25. package/dist/client-graph.d.ts +94 -0
  26. package/dist/client-graph.js +266 -0
  27. package/dist/client-modules.d.ts +10 -0
  28. package/dist/client-modules.js +43 -0
  29. package/dist/client.d.ts +42 -0
  30. package/dist/client.js +263 -0
  31. package/dist/commonjs.d.ts +44 -0
  32. package/dist/commonjs.js +111 -0
  33. package/dist/compat/browser/client.d.ts +19 -0
  34. package/dist/compat/browser/client.js +13 -0
  35. package/dist/compat/build.d.ts +145 -0
  36. package/dist/compat/build.js +149 -0
  37. package/dist/compat/checks.d.ts +16 -0
  38. package/dist/compat/checks.js +148 -0
  39. package/dist/compat/patches.d.ts +13 -0
  40. package/dist/compat/patches.js +30 -0
  41. package/dist/compat/paths.d.ts +74 -0
  42. package/dist/compat/paths.js +160 -0
  43. package/dist/compat/rsc/handlers.d.ts +2 -0
  44. package/dist/compat/rsc/handlers.js +2 -0
  45. package/dist/compat/rsc/prerender.d.ts +10 -0
  46. package/dist/compat/rsc/prerender.js +9 -0
  47. package/dist/compat/server/headers.d.ts +3 -0
  48. package/dist/compat/server/headers.js +3 -0
  49. package/dist/compat/ssr/build-output.d.ts +4 -0
  50. package/dist/compat/ssr/build-output.js +3 -0
  51. package/dist/compat/ssr/cache.d.ts +6 -0
  52. package/dist/compat/ssr/cache.js +6 -0
  53. package/dist/compat/ssr/handler.d.ts +8 -0
  54. package/dist/compat/ssr/handler.js +8 -0
  55. package/dist/compat/ssr/node-server.d.ts +5 -0
  56. package/dist/compat/ssr/node-server.js +4 -0
  57. package/dist/compat/ssr/render-errors.d.ts +4 -0
  58. package/dist/compat/ssr/render-errors.js +4 -0
  59. package/dist/compat/ssr/senders.d.ts +6 -0
  60. package/dist/compat/ssr/senders.js +6 -0
  61. package/dist/compat/types.d.ts +8 -0
  62. package/dist/compat/types.js +1 -0
  63. package/dist/compile.d.ts +31 -0
  64. package/dist/compile.js +140 -0
  65. package/dist/disk.d.ts +16 -0
  66. package/dist/disk.js +13 -0
  67. package/dist/document-loads.d.ts +15 -0
  68. package/dist/document-loads.js +53 -0
  69. package/dist/document.d.ts +79 -0
  70. package/dist/document.js +328 -0
  71. package/dist/downloads.d.ts +15 -0
  72. package/dist/downloads.js +71 -0
  73. package/dist/esm-require.d.ts +11 -0
  74. package/dist/esm-require.js +32 -0
  75. package/dist/fast-crypto/index.js +1093 -0
  76. package/dist/fast-crypto.d.ts +20 -0
  77. package/dist/fast-crypto.js +151 -0
  78. package/dist/flight.d.ts +19 -0
  79. package/dist/flight.js +42 -0
  80. package/dist/form-submission.d.ts +15 -0
  81. package/dist/form-submission.js +27 -0
  82. package/dist/from-page.d.ts +5 -0
  83. package/dist/from-page.js +44 -0
  84. package/dist/globals.d.ts +1 -0
  85. package/dist/globals.js +197 -0
  86. package/dist/host-document.d.ts +26 -0
  87. package/dist/host-document.js +34 -0
  88. package/dist/index.d.ts +280 -0
  89. package/dist/index.js +281 -0
  90. package/dist/internal.d.ts +2 -0
  91. package/dist/internal.js +3 -0
  92. package/dist/leftovers.d.ts +11 -0
  93. package/dist/leftovers.js +55 -0
  94. package/dist/mode.d.ts +169 -0
  95. package/dist/mode.js +31 -0
  96. package/dist/node/LICENSES.md +3540 -0
  97. package/dist/node/assert/strict.js +29 -0
  98. package/dist/node/assert.js +3044 -0
  99. package/dist/node/buffer.js +1499 -0
  100. package/dist/node/child_process.js +45 -0
  101. package/dist/node/cluster.js +85 -0
  102. package/dist/node/console.js +96 -0
  103. package/dist/node/constants.js +495 -0
  104. package/dist/node/crypto.js +1388 -0
  105. package/dist/node/dgram.js +78 -0
  106. package/dist/node/diagnostics_channel.js +122 -0
  107. package/dist/node/dns/promises.js +129 -0
  108. package/dist/node/dns.js +137 -0
  109. package/dist/node/domain.js +43 -0
  110. package/dist/node/events.js +1155 -0
  111. package/dist/node/fs/promises.js +40 -0
  112. package/dist/node/fs.js +10375 -0
  113. package/dist/node/http.js +326 -0
  114. package/dist/node/http2.js +305 -0
  115. package/dist/node/https.js +57 -0
  116. package/dist/node/inspector/promises.js +66 -0
  117. package/dist/node/inspector.js +76 -0
  118. package/dist/node/module.js +205 -0
  119. package/dist/node/net.js +392 -0
  120. package/dist/node/os.js +259 -0
  121. package/dist/node/path/posix.js +25 -0
  122. package/dist/node/path/win32.js +25 -0
  123. package/dist/node/path.js +384 -0
  124. package/dist/node/perf_hooks.js +313 -0
  125. package/dist/node/process.js +452 -0
  126. package/dist/node/punycode.js +178 -0
  127. package/dist/node/querystring.js +934 -0
  128. package/dist/node/readline/promises.js +71 -0
  129. package/dist/node/readline.js +56 -0
  130. package/dist/node/repl.js +44 -0
  131. package/dist/node/sqlite.js +22 -0
  132. package/dist/node/stream/consumers.js +47 -0
  133. package/dist/node/stream/promises.js +6 -0
  134. package/dist/node/stream/web.js +52 -0
  135. package/dist/node/stream.js +4323 -0
  136. package/dist/node/string_decoder.js +276 -0
  137. package/dist/node/sys.js +6 -0
  138. package/dist/node/timers/promises.js +71 -0
  139. package/dist/node/timers.js +133 -0
  140. package/dist/node/tls.js +122 -0
  141. package/dist/node/trace_events.js +23 -0
  142. package/dist/node/tty.js +69 -0
  143. package/dist/node/url.js +1426 -0
  144. package/dist/node/util/types.js +1456 -0
  145. package/dist/node/util.js +4807 -0
  146. package/dist/node/v8.js +160 -0
  147. package/dist/node/vm.js +88 -0
  148. package/dist/node/wasi.js +16 -0
  149. package/dist/node/worker_threads.js +123 -0
  150. package/dist/node/zlib.js +1396 -0
  151. package/dist/node-builtins.d.ts +40 -0
  152. package/dist/node-builtins.js +74 -0
  153. package/dist/node-on-page.d.ts +46 -0
  154. package/dist/node-on-page.js +101 -0
  155. package/dist/node-platform.d.ts +36 -0
  156. package/dist/node-platform.js +152 -0
  157. package/dist/node-rendered.d.ts +21 -0
  158. package/dist/node-rendered.js +26 -0
  159. package/dist/node-server.d.ts +46 -0
  160. package/dist/node-server.js +193 -0
  161. package/dist/optimizer-cache-key.d.ts +26 -0
  162. package/dist/optimizer-cache-key.js +73 -0
  163. package/dist/own-package.d.ts +1 -0
  164. package/dist/own-package.js +6 -0
  165. package/dist/page-store.d.ts +33 -0
  166. package/dist/page-store.js +80 -0
  167. package/dist/page-timers.d.ts +22 -0
  168. package/dist/page-timers.js +47 -0
  169. package/dist/page.d.ts +112 -0
  170. package/dist/page.js +549 -0
  171. package/dist/paths.d.ts +13 -0
  172. package/dist/paths.js +47 -0
  173. package/dist/plugin.d.ts +22 -0
  174. package/dist/plugin.js +995 -0
  175. package/dist/prerender-verdict.d.ts +8 -0
  176. package/dist/prerender-verdict.js +67 -0
  177. package/dist/project/context.d.ts +546 -0
  178. package/dist/project/context.js +111 -0
  179. package/dist/project/entries.d.ts +42 -0
  180. package/dist/project/entries.js +189 -0
  181. package/dist/project/env-worker.d.ts +1 -0
  182. package/dist/project/env-worker.js +9 -0
  183. package/dist/project/env.d.ts +36 -0
  184. package/dist/project/env.js +82 -0
  185. package/dist/project/layers.d.ts +31 -0
  186. package/dist/project/layers.js +150 -0
  187. package/dist/project/loaders.d.ts +71 -0
  188. package/dist/project/loaders.js +300 -0
  189. package/dist/project/metadata.d.ts +8 -0
  190. package/dist/project/metadata.js +34 -0
  191. package/dist/project/module-exports.d.ts +29 -0
  192. package/dist/project/module-exports.js +77 -0
  193. package/dist/project/routes.d.ts +19 -0
  194. package/dist/project/routes.js +92 -0
  195. package/dist/project/routing.d.ts +46 -0
  196. package/dist/project/routing.js +280 -0
  197. package/dist/project/transform.d.ts +8 -0
  198. package/dist/project/transform.js +110 -0
  199. package/dist/project/webpack.d.ts +46 -0
  200. package/dist/project/webpack.js +160 -0
  201. package/dist/project.d.ts +264 -0
  202. package/dist/project.js +58 -0
  203. package/dist/registry-global.d.ts +5 -0
  204. package/dist/registry-global.js +5 -0
  205. package/dist/registry.d.ts +241 -0
  206. package/dist/registry.js +30 -0
  207. package/dist/route-chunks.d.ts +13 -0
  208. package/dist/route-chunks.js +32 -0
  209. package/dist/route-lookup.d.ts +34 -0
  210. package/dist/route-lookup.js +207 -0
  211. package/dist/routes-ahead-shared.d.ts +17 -0
  212. package/dist/routes-ahead-shared.js +9 -0
  213. package/dist/routes-ahead.d.ts +10 -0
  214. package/dist/routes-ahead.js +54 -0
  215. package/dist/rsc.d.ts +19 -0
  216. package/dist/rsc.js +171 -0
  217. package/dist/server-action.d.ts +9 -0
  218. package/dist/server-action.js +15 -0
  219. package/dist/server-code.d.ts +176 -0
  220. package/dist/server-code.js +357 -0
  221. package/dist/server-in-front.d.ts +37 -0
  222. package/dist/server-in-front.js +90 -0
  223. package/dist/server-layers.d.ts +22 -0
  224. package/dist/server-layers.js +33 -0
  225. package/dist/setup-browser.d.ts +1 -0
  226. package/dist/setup-browser.js +8 -0
  227. package/dist/setup-node.d.ts +1 -0
  228. package/dist/setup-node.js +6 -0
  229. package/dist/setup.d.ts +8 -0
  230. package/dist/setup.js +62 -0
  231. package/dist/speed-features.d.ts +13 -0
  232. package/dist/speed-features.js +95 -0
  233. package/dist/ssr.d.ts +70 -0
  234. package/dist/ssr.js +480 -0
  235. package/dist/static-build.d.ts +36 -0
  236. package/dist/static-build.js +92 -0
  237. package/dist/storage.d.ts +31 -0
  238. package/dist/storage.js +94 -0
  239. package/dist/styles-shared.d.ts +137 -0
  240. package/dist/styles-shared.js +124 -0
  241. package/dist/styles.d.ts +102 -0
  242. package/dist/styles.js +730 -0
  243. package/dist/stylesheet-versions.d.ts +17 -0
  244. package/dist/stylesheet-versions.js +43 -0
  245. package/dist/tester.html +10 -0
  246. package/dist/use-cache.d.ts +15 -0
  247. package/dist/use-cache.js +93 -0
  248. package/dist/vitest-version.d.ts +6 -0
  249. package/dist/vitest-version.js +12 -0
  250. package/package.json +125 -4
package/dist/styles.js ADDED
@@ -0,0 +1,730 @@
1
+ import { builtFilesPath, componentPagePath, cssDirectory, cssVersionPattern, stylesheetsChangedEvent, stylesheetsEvent } from "./styles-shared.js";
2
+ import { fontRequestOf } from "./compile.js";
3
+ import { routeChunksOf } from "./route-chunks.js";
4
+ import { clientReferenceOfModule } from "./client-files.js";
5
+ import { isBuiltin } from "node:module";
6
+ import { clientReferencesId } from "@kasperpeulen/vitest-plugin-rsc/internal/built-layers";
7
+ import { isCSSRequest, normalizePath, parseAst, send, version } from "vite";
8
+ import path from "node:path";
9
+ import { createHash } from "node:crypto";
10
+ import fs from "node:fs";
11
+ import { getPluginApi } from "@vitejs/plugin-rsc/plugin";
12
+ import { cssBuildDirPlaceholder, toBuildDir } from "@kasperpeulen/vitest-plugin-rsc/internal/static-build";
13
+ import { answerPage } from "@kasperpeulen/vitest-plugin-rsc/internal/page-bridge";
14
+ //#region src/styles.ts
15
+ const linkedQuery = "next-linked";
16
+ const linkedRE = new RegExp(`[?&]${linkedQuery}\\b`);
17
+ const directRE = /[?&]direct\b/;
18
+ const transformOnly = "transform-only";
19
+ /** The id of a stylesheet that Next links, of the id of its file, in a build or not. */
20
+ const linked = (id, build = false) => `${id}${id.includes("?") ? "&" : "?"}${linkedQuery}${build ? `&${transformOnly}` : ""}`;
21
+ const isLinked = (id) => linkedRE.test(id);
22
+ const metaKey = "vitest-plugin-rsc:next-linked";
23
+ /**
24
+ * Whether a module is that of a stylesheet that Next links, whose links the
25
+ * page moves to the version of now after a change
26
+ * (`stylesheetsChangedEvent`). One without class names, which its module
27
+ * exports as a CSS module does, and so exports nothing. Not with
28
+ * `experimental.inlineCss`, with which Next puts the CSS of a page load in a
29
+ * `<style>`, which is no link: the page loads again for it.
30
+ */
31
+ const movesItsLinks = (node) => (node.info?.meta)?.[metaKey]?.movesLinks === true;
32
+ /**
33
+ * Whether a stylesheet changes in place after a change, and what imports it
34
+ * sees nothing of it: one that accepts its own update, which Vite swaps as
35
+ * its `<style>`, and the module of a stylesheet that Next links without
36
+ * class names, whose links the page moves to the version of now
37
+ * (`stylesheetsChangedEvent`).
38
+ */
39
+ const changesInPlace = (node) => isCSSRequest(node.url) && (node.isSelfAccepting === true || movesItsLinks(node));
40
+ const isScriptRequest = (source) => /\.[cm]?[jt]sx?$/.test(source);
41
+ const codeExtensionRE = /^(?:[cm]?[jt]sx?|vue|marko|svelte|astro|imba|mdx)$/;
42
+ function isCode(id, pageExtensions) {
43
+ const file = id.split("?")[0];
44
+ const extension = /\.([^./]+)$/.exec(file)?.[1];
45
+ return extension === void 0 || codeExtensionRE.test(extension) || pageExtensions.some((pageExtension) => file.endsWith(`.${pageExtension}`));
46
+ }
47
+ /**
48
+ * The order of the cascade layers of a stylesheet, kept where Vite inlines
49
+ * its `@import`s. A layer comes in the order in which a stylesheet names it
50
+ * first, and an `@import` with `layer()` names it before an `@layer`
51
+ * statement that follows the import. `postcss-import`, with which Vite
52
+ * inlines an import, puts such a statement before the CSS of the import, so
53
+ * that its layers come first. With a statement of every layer of the imports
54
+ * at the top, which can precede an `@import`, the order is the stylesheet's
55
+ * own. Not that of a stylesheet it imports, which `postcss-import` reads
56
+ * itself, nor of a layer without a name, which a statement cannot name.
57
+ */
58
+ function declareImportedLayers(css) {
59
+ const layers = [];
60
+ let start = 0;
61
+ let importsLayer = false;
62
+ let reordered = false;
63
+ for (let at = 0;;) {
64
+ const space = /^(?:\s+|\/\*[\s\S]*?\*\/)*/.exec(css.slice(at))[0];
65
+ at += space.length;
66
+ const rule = /^@(charset|import|layer)\b((?:"[^"]*"|'[^']*'|\([^)]*\)|[^;{"'(])*);/i.exec(css.slice(at));
67
+ if (!rule) break;
68
+ const [statement, name, prelude] = rule;
69
+ at += statement.length;
70
+ if (name.toLowerCase() === "charset") start = at;
71
+ else if (name.toLowerCase() === "import") {
72
+ const layer = /\blayer\(\s*([^)\s]+)\s*\)/i.exec(prelude.replace(/"[^"]*"|'[^']*'/g, ""));
73
+ if (layer && !layers.includes(layer[1])) layers.push(layer[1]);
74
+ importsLayer ||= Boolean(layer);
75
+ } else {
76
+ reordered ||= importsLayer;
77
+ for (const layer of prelude.split(",").map((part) => part.trim())) if (layer && !layers.includes(layer)) layers.push(layer);
78
+ }
79
+ }
80
+ if (!reordered) return css;
81
+ return `${css.slice(0, start)}@layer ${layers.join(", ")};${css.slice(start)}`;
82
+ }
83
+ const directory = cssDirectory;
84
+ const versionRE = new RegExp(`^${directory}/(${cssVersionPattern})(/.*)$`);
85
+ function boundNames(node, names) {
86
+ if (!node || typeof node !== "object") return;
87
+ const { type } = node;
88
+ if (type === "Identifier") names.add(node.name);
89
+ else if (type === "ImportDeclaration") for (const { local } of node.specifiers) boundNames(local, names);
90
+ else if (type === "VariableDeclaration") for (const { id } of node.declarations) boundNames(id, names);
91
+ else if (type === "FunctionDeclaration" || type === "ClassDeclaration") boundNames(node.id, names);
92
+ else for (const key of [
93
+ "properties",
94
+ "elements",
95
+ "value",
96
+ "argument",
97
+ "left"
98
+ ]) for (const part of [node[key]].flat()) boundNames(part, names);
99
+ }
100
+ function identifiersOf(node, names) {
101
+ if (!node || typeof node !== "object") return false;
102
+ const { type } = node;
103
+ if (type === "Identifier") names.add(node.name);
104
+ let meta = type === "MetaProperty";
105
+ for (const value of Object.values(node)) if (value && typeof value === "object") meta = identifiersOf(value, names) || meta;
106
+ return meta;
107
+ }
108
+ /**
109
+ * The exports of Vite's module for a stylesheet, without the code that puts
110
+ * the CSS in the document.
111
+ *
112
+ * Vite's module for a client (`vite:css-post`) puts the CSS in a `<style>`,
113
+ * and has the class names of a CSS module as its exports, as Vite documents
114
+ * them. Its module for a server is those exports, with the constants they
115
+ * are made of: one for a class name that is no name of a variable, like
116
+ * `switch`. So the exports are kept, with the statements they use, and the
117
+ * rest is not. That holds as long as what they use is not the code of the
118
+ * `<style>`: an import, or `import.meta`.
119
+ */
120
+ function exportsOfStylesheet(code, id) {
121
+ const body = parseAst(code).body;
122
+ const isExport = (node) => node.type === "ExportNamedDeclaration" && !node.source || node.type === "ExportDefaultDeclaration";
123
+ const declaredBy = /* @__PURE__ */ new Map();
124
+ for (const node of body) {
125
+ if (isExport(node)) continue;
126
+ const names = /* @__PURE__ */ new Set();
127
+ boundNames(node, names);
128
+ for (const name of names) declaredBy.set(name, node);
129
+ }
130
+ let other;
131
+ const kept = new Set(body.filter(isExport));
132
+ for (const node of kept) {
133
+ const used = /* @__PURE__ */ new Set();
134
+ if (identifiersOf(node, used)) other = code.slice(node.start, node.end);
135
+ for (const name of used) {
136
+ const declaration = declaredBy.get(name);
137
+ if (!declaration || kept.has(declaration)) continue;
138
+ if (declaration.type === "ImportDeclaration") other = name;
139
+ else kept.add(declaration);
140
+ }
141
+ }
142
+ for (const node of body) if (node.type === "ExportNamedDeclaration" || node.type === "ExportAllDeclaration") {
143
+ if (!kept.has(node)) other = code.slice(node.start, node.end);
144
+ }
145
+ if (other !== void 0) throw new Error(`vitest-plugin-rsc: vite@${version} differs from the Vite this plugin was written for: the exports of its module for the stylesheet ${id} need more than the class names (\`${other}\`). Use a version of @kasperpeulen/vitest-plugin-nextjs that supports vite@${version}.`);
146
+ const exports = body.filter((node) => kept.has(node));
147
+ return exports.length > 0 ? exports.map((node) => code.slice(node.start, node.end)).join("\n") : noExports;
148
+ }
149
+ const noExports = "export {}";
150
+ function createStyles(options) {
151
+ const { getProject, environments } = options;
152
+ const layers = new Map(Object.entries(environments).map(([layer, name]) => [name, layer]));
153
+ const lists = new Set(options.lists);
154
+ const inlinesCss = () => getProject().config.experimental?.inlineCss === true;
155
+ const stylesheetIds = /* @__PURE__ */ new Map();
156
+ function serveAt(stylesheet) {
157
+ const url = stylesheet.url.split("?")[0];
158
+ const name = url.startsWith("/") ? url : `/${createHash("sha1").update(url).digest("hex").slice(0, 16)}.css`;
159
+ stylesheetIds.set(directory + name, stylesheet.id);
160
+ return directory + name;
161
+ }
162
+ const segments = /* @__PURE__ */ new Map();
163
+ function segmentsOf(route) {
164
+ let files = segments.get(route);
165
+ if (!files) {
166
+ files = getProject().loadRouteEntry(route).then((entry) => entry.segments);
167
+ segments.set(route, files);
168
+ files.catch(() => segments.delete(route));
169
+ }
170
+ return files;
171
+ }
172
+ const loads = /* @__PURE__ */ new Map();
173
+ function reach(vite, queue) {
174
+ const references = getPluginApi(vite.config)?.manager.clientReferenceMetaMap;
175
+ if (!references) throw new Error("vitest-plugin-rsc: vitestPluginNext() needs vitestPluginRSC() before it in the plugins.");
176
+ const graphs = {
177
+ rsc: vite.environments[environments.rsc],
178
+ browser: vite.environments[environments.browser]
179
+ };
180
+ const clientModules = /* @__PURE__ */ new Map();
181
+ const followed = /* @__PURE__ */ new Set();
182
+ const { pageExtensions = [] } = getProject().config;
183
+ async function load(layer, url) {
184
+ if (url.startsWith("/@id/")) url = url.slice(5).replace("__x00__", "\0");
185
+ const key = `${layer}:${url}`;
186
+ const inGraph = () => graphs[layer].moduleGraph.getModuleByUrl(url).catch(() => void 0);
187
+ if (queue) return queue(() => graphs[layer].transformRequest(url)).then(inGraph, () => void 0);
188
+ let loaded = loads.get(key);
189
+ if (loaded) {
190
+ const node = await loaded.module ?? await inGraph();
191
+ if (node && node.lastInvalidationTimestamp !== loaded.invalidated) loaded = void 0;
192
+ }
193
+ if (!loaded) {
194
+ const entry = {
195
+ module: graphs[layer].transformRequest(url).then(inGraph).catch((error) => {
196
+ if (error?.code === "ERR_LOAD_URL") vite.config.logger.warnOnce(`vitest-plugin-rsc: the CSS of ${url} is not linked: ${String(error)}`);
197
+ }).then(async (found) => {
198
+ entry.invalidated = (found ?? await inGraph())?.lastInvalidationTimestamp;
199
+ return found;
200
+ }),
201
+ invalidated: void 0
202
+ };
203
+ loaded = entry;
204
+ loads.set(key, loaded);
205
+ }
206
+ return loaded.module;
207
+ }
208
+ const isEnd = (id) => lists.has(id);
209
+ /** Has Vite's graphs know what `node` imports, as far as it goes. */
210
+ async function follow(layer, node) {
211
+ if (followed.has(node) || !node.id || isEnd(node.id)) return;
212
+ followed.add(node);
213
+ const reference = layer === "rsc" ? clientReferenceOfModule(references, node.id) : void 0;
214
+ if (reference) {
215
+ const client = await load("browser", reference.importId);
216
+ if (!client) return;
217
+ clientModules.set(node, client);
218
+ return follow("browser", client);
219
+ }
220
+ await Promise.all(Array.from(node.importedModules, async (imported) => {
221
+ if (!imported.id || isCSSRequest(imported.id) || isBuiltin(imported.id)) return;
222
+ if (!isCode(imported.id, pageExtensions)) return;
223
+ if (options.isHostPackageFile(imported.id.split("?")[0])) return;
224
+ const loaded = imported.transformResult ? imported : await load(layer, imported.url);
225
+ if (loaded) await follow(layer, loaded);
226
+ }));
227
+ }
228
+ /** The stylesheets that `start` reaches, in the order of the imports. */
229
+ function collect(start) {
230
+ const paths = /* @__PURE__ */ new Set();
231
+ const seen = /* @__PURE__ */ new Set();
232
+ const visit = (node) => {
233
+ if (seen.has(node) || !node.id || isEnd(node.id)) return;
234
+ seen.add(node);
235
+ const client = clientModules.get(node);
236
+ if (client) return visit(client);
237
+ for (const imported of node.importedModules) {
238
+ if (!imported.id) continue;
239
+ if (isLinked(imported.id)) paths.add(serveAt(imported));
240
+ else if (!isCSSRequest(imported.id)) visit(imported);
241
+ }
242
+ };
243
+ start.forEach(visit);
244
+ return [...paths];
245
+ }
246
+ return {
247
+ load,
248
+ follow,
249
+ collect
250
+ };
251
+ }
252
+ /**
253
+ * The stylesheets of a route, per file of a segment: see `Stylesheets`. The
254
+ * node of a test is the page of its route, and no file: its stylesheets are
255
+ * those of the files of the host that render it, `hostFiles` of
256
+ * renderServer(), in their order. Under Vitest those are the setup files
257
+ * and the test file; see `nodeFiles` in registry.ts. With `layouts: true`
258
+ * the layouts of the app around it have their own.
259
+ */
260
+ async function stylesheetsOf(vite, files, entry, inline) {
261
+ const route = options.pageRoutes().get(entry);
262
+ if (!route) return {};
263
+ const { load, follow, collect } = reach(vite);
264
+ const starts = /* @__PURE__ */ new Map();
265
+ await Promise.all((await segmentsOf(route)).map(async ({ file, stylesheetsKey }) => {
266
+ const node = await load("rsc", file);
267
+ if (node) starts.set(stylesheetsKey, [node]);
268
+ }));
269
+ if ("component" in route) starts.set(componentPagePath, hostFileNodes(vite, files, "the files that render a node, `hostFiles` of renderServer() or its default under Vitest,"));
270
+ await Promise.all([...starts.values()].flat().map((node) => follow("rsc", node)));
271
+ const contentOf = async (path) => inline && inlinesCss() ? (await cssOf(vite, path))?.code : void 0;
272
+ const fontsOf = async (path) => {
273
+ const request = fontRequestOf(stylesheetIds.get(path) ?? "");
274
+ return request === void 0 ? void 0 : (await getProject().loadFont(request)).files;
275
+ };
276
+ return Object.fromEntries(await Promise.all(Array.from(starts, async ([file, start]) => [file, await Promise.all(collect(start).map(async (path) => ({
277
+ path: await versioned(vite, path),
278
+ content: await contentOf(path),
279
+ fonts: await fontsOf(path)
280
+ })))])));
281
+ }
282
+ async function compileRoute(vite, entry) {
283
+ const route = options.pageRoutes().get(entry);
284
+ if (!route) return;
285
+ const queue = oneAtATime();
286
+ const { load, follow, collect } = reach(vite, queue);
287
+ const starts = (await Promise.all((await segmentsOf(route)).map(({ file }) => load("rsc", file)))).filter((node) => node !== void 0);
288
+ await Promise.all(starts.map((node) => follow("rsc", node)));
289
+ const rsc = vite.environments[environments.rsc];
290
+ await Promise.all(collect(starts).map((path) => Promise.all([queue(() => rsc.transformRequest(stylesheetIds.get(path))), queue(() => cssOf(vite, path))]).catch(() => {})));
291
+ }
292
+ function hostFileNodes(vite, files, named) {
293
+ const rsc = vite.environments[environments.rsc];
294
+ return files.flatMap((file) => {
295
+ if (!options.isHostFile(file)) {
296
+ vite.config.logger.warnOnce(`vitest-plugin-rsc: ${named} name ${file}, which is neither a test file or setup file of Vitest nor matched by \`host.files\` of vitestPluginNext(); an in-source test file is a file of the app. Its stylesheets are not linked.`);
297
+ return [];
298
+ }
299
+ const nodes = rsc.moduleGraph.getModulesByFile(file);
300
+ if (!nodes?.size) vite.config.logger.warnOnce(`vitest-plugin-rsc: ${named} name ${file}, which the rsc layer has not loaded: the stylesheets it imports are not linked.`);
301
+ return [...nodes ?? []];
302
+ });
303
+ }
304
+ const fileOf = (file) => normalizePath(path.resolve(getProject().root, file));
305
+ async function versioned(server, path) {
306
+ const css = await cssOf(server, path).catch(() => null);
307
+ return css ? `${directory}/${versionOf(css)}${path.slice(directory.length)}` : path;
308
+ }
309
+ /**
310
+ * The stylesheets of the files of the host that the host uses,
311
+ * `linkStylesheetsOf()`: what each imports, as for a file that renders a
312
+ * node, in their order, each once. Such a use has no page of the app, so
313
+ * the page links them itself: see client-graph.ts.
314
+ */
315
+ async function hostFilesStylesheetsOf(vite, files) {
316
+ const { follow, collect } = reach(vite);
317
+ const nodes = hostFileNodes(vite, files, "`linkStylesheetsOf()`");
318
+ await Promise.all(nodes.map((node) => follow("rsc", node)));
319
+ return linkedAt(vite, collect(nodes));
320
+ }
321
+ function linkedAt(vite, paths) {
322
+ const urlOf = (path) => path.split("/").map(encodeURIComponent).join("/");
323
+ return Promise.all(paths.map(async (path) => getProject().assetPath + urlOf(await versioned(vite, path))));
324
+ }
325
+ function changedStylesheets(graph, modules) {
326
+ const changed = /* @__PURE__ */ new Map();
327
+ if (inlinesCss()) return changed;
328
+ const reached = new Set(modules.flatMap((node) => [node, ...node.importers]));
329
+ for (const [path, id] of stylesheetIds) {
330
+ const css = graph.getModuleById(`${id}&direct`);
331
+ if (!css?.isSelfAccepting || !reached.has(css)) continue;
332
+ graph.invalidateModule(css);
333
+ changed.set(path, css);
334
+ }
335
+ return changed;
336
+ }
337
+ async function cssOf(server, path) {
338
+ const id = stylesheetIds.get(path);
339
+ return id ? server.environments[environments.rsc].transformRequest(`${id}&direct`) : null;
340
+ }
341
+ const versions = /* @__PURE__ */ new WeakMap();
342
+ function versionOf(css) {
343
+ let version = versions.get(css);
344
+ if (!version) {
345
+ version = createHash("sha1").update(css.code).update(css.map?.mappings ?? "").digest("hex").slice(0, 16);
346
+ versions.set(css, version);
347
+ }
348
+ return version;
349
+ }
350
+ async function serve(server, request, response) {
351
+ const { assetPath } = getProject();
352
+ const { pathname } = new URL(request.url, "http://n");
353
+ if (!pathname.startsWith(`${assetPath}${directory}/`)) return false;
354
+ let path;
355
+ try {
356
+ path = pathname.slice(assetPath.length).split("/").map(decodeURIComponent).join("/");
357
+ } catch {
358
+ return false;
359
+ }
360
+ const [, hash, rest] = versionRE.exec(path) ?? [];
361
+ const version = hash && !stylesheetIds.has(path) && stylesheetIds.has(directory + rest) ? hash : void 0;
362
+ if (version) path = directory + rest;
363
+ const css = await cssOf(server, path);
364
+ if (!css) return false;
365
+ const current = versionOf(css);
366
+ send(request, response, css.code, "css", {
367
+ etag: `"${current}"`,
368
+ cacheControl: version === current ? "public, max-age=31536000, immutable" : "no-cache",
369
+ headers: server.config.server.headers,
370
+ map: css.map
371
+ });
372
+ return true;
373
+ }
374
+ const built = createBuiltFiles(options, segmentsOf);
375
+ return {
376
+ plugins: [
377
+ {
378
+ name: "vitest-plugin-rsc:next-styles",
379
+ enforce: "pre",
380
+ configureServer(vite) {
381
+ answerPage(vite, stylesheetsEvent, (question) => "hostFiles" in question ? hostFilesStylesheetsOf(vite, question.hostFiles.map(fileOf)) : stylesheetsOf(vite, question.files.map(fileOf), question.entry, question.inline));
382
+ vite.watcher.on("all", () => {
383
+ for (const [key, loaded] of loads) loaded.module.then((node) => {
384
+ if (!node && loads.get(key) === loaded) loads.delete(key);
385
+ });
386
+ });
387
+ vite.middlewares.use(async (request, response, next) => {
388
+ let served;
389
+ try {
390
+ served = await serve(vite, request, response);
391
+ } catch (error) {
392
+ vite.config.logger.error(`vitest-plugin-rsc: ${request.url} failed. ${String(error)}`);
393
+ response.statusCode = 500;
394
+ response.end("Internal Server Error");
395
+ return;
396
+ }
397
+ if (!served) next();
398
+ });
399
+ },
400
+ hotUpdate: {
401
+ order: "pre",
402
+ async handler({ modules, server }) {
403
+ if (!layers.has(this.environment.name)) return;
404
+ const moved = /* @__PURE__ */ new Set();
405
+ if (this.environment.name === environments.rsc) {
406
+ const changed = changedStylesheets(this.environment.moduleGraph, modules);
407
+ if (changed.size > 0) {
408
+ const data = await linkedAt(server, [...changed.keys()]);
409
+ this.environment.hot.send({
410
+ type: "custom",
411
+ event: stylesheetsChangedEvent,
412
+ data
413
+ });
414
+ }
415
+ for (const css of changed.values()) moved.add(css);
416
+ }
417
+ const updated = modules.filter((node) => !moved.has(node) && !movesItsLinks(node));
418
+ if (updated.length < modules.length) return updated;
419
+ }
420
+ },
421
+ async resolveId(source, importer, resolveOptions) {
422
+ const layer = layers.get(this.environment.name);
423
+ if (!layer || !importer || source.includes("?") || isScriptRequest(source)) return;
424
+ const file = importer.split("?")[0];
425
+ if (layer === "rsc" && !options.isServerCode(file) && !options.isHostFile(file)) return;
426
+ const resolved = await this.resolve(source, importer, {
427
+ ...resolveOptions,
428
+ skipSelf: true
429
+ });
430
+ if (!resolved || resolved.external || resolved.id.includes("?")) return resolved;
431
+ if (!isCSSRequest(resolved.id)) return resolved;
432
+ return {
433
+ ...resolved,
434
+ id: linked(resolved.id, this.environment.mode === "build")
435
+ };
436
+ },
437
+ transform(code, id) {
438
+ if (!/\.css(?:$|\?)/.test(id) || /[?&](?:raw|url)\b/.test(id)) return;
439
+ const declared = declareImportedLayers(code);
440
+ if (declared !== code) return {
441
+ code: declared,
442
+ map: null
443
+ };
444
+ }
445
+ },
446
+ {
447
+ name: "vitest-plugin-rsc:next-styles-module",
448
+ enforce: "post",
449
+ applyToEnvironment: (environment) => layers.has(environment.name),
450
+ transform(code, id) {
451
+ if (!isLinked(id) || directRE.test(id)) return;
452
+ const exports = exportsOfStylesheet(code, id);
453
+ const movesLinks = exports === noExports && !inlinesCss();
454
+ return {
455
+ code: exports,
456
+ map: { mappings: "" },
457
+ meta: { [metaKey]: { movesLinks } }
458
+ };
459
+ }
460
+ },
461
+ ...built.plugins
462
+ ],
463
+ compileRoute,
464
+ builtFiles: built.files
465
+ };
466
+ }
467
+ function oneAtATime() {
468
+ let last = Promise.resolve();
469
+ return (task) => {
470
+ const run = last.then(() => new Promise((resolve) => setImmediate(resolve))).then(task);
471
+ last = run.catch(() => {});
472
+ return run;
473
+ };
474
+ }
475
+ const realRoots = /* @__PURE__ */ new Map();
476
+ function realRootOf(root) {
477
+ let real = realRoots.get(root);
478
+ if (real === void 0) {
479
+ real = fs.existsSync(root) ? normalizePath(fs.realpathSync(root)) : normalizePath(root);
480
+ realRoots.set(root, real);
481
+ }
482
+ return real;
483
+ }
484
+ /**
485
+ * The key of a file of the host in `hostFiles` of `BuiltFiles`, by the
486
+ * id of its module in a build: its path from the root of the project, the
487
+ * same on every machine. Nothing for a file on another drive of Windows,
488
+ * which has no way from the root: its path is the machine's.
489
+ */
490
+ function builtHostFileKey(id, root) {
491
+ const file = normalizePath(path.relative(realRootOf(normalizePath(root)), id));
492
+ return path.isAbsolute(file) ? void 0 : file;
493
+ }
494
+ /**
495
+ * The key of a module of a build, as `builtHostFileKey()` has it, when the
496
+ * module is a file of the host: matched by its path from the root, as
497
+ * `host.files` are from the root as the config has it. Nothing for a module
498
+ * that is no file, or one with a query.
499
+ */
500
+ function builtHostFileOf(id, root, isHostFile) {
501
+ if (id.startsWith("\0") || id.includes("?")) return void 0;
502
+ const file = builtHostFileKey(id, root);
503
+ if (file === void 0 || !isHostFile(path.posix.join(normalizePath(root), file))) return;
504
+ return file;
505
+ }
506
+ const builtAssetRE = /__VITE_ASSET__([\w$]+)__/g;
507
+ const publicAssetRE = /__VITE_PUBLIC_ASSET__([a-z\d]{8})__/g;
508
+ const publicAssetHash = (url) => createHash("sha256").update(url).digest("hex").slice(0, 8);
509
+ const cssUrlRE = /\burl\(\s*(?:"([^"]*)"|'([^']*)'|([^'")\s]*))\s*\)|"(\/[^"]*)"|'(\/[^']*)'/g;
510
+ /**
511
+ * The stylesheets of a static build, which has no dev server to ask. So the
512
+ * build does what Next's build does: it writes each stylesheet into a file of
513
+ * its own under `/_next/static/css/`, and the stylesheets of every page route
514
+ * into a file next to the layers, which the page reads (`builtStylesheetsOf()`
515
+ * in styles-shared.ts).
516
+ *
517
+ * The CSS is what Vite's CSS plugin compiles the file into, with the files it
518
+ * names by the way from the stylesheet. Vite leaves a stylesheet that Next
519
+ * links out of the CSS of its chunks, see `linked()`: it is on the pages that
520
+ * link it, and only there. The lists are read off the module graphs of the
521
+ * build, as `reach()` reads them off the dev server's: the rsc layer for the
522
+ * files of the segments and the files of the host, and the layer of the
523
+ * browser for the Client Components, which is built after it. The node of a
524
+ * route has the stylesheets of the files of the host that the page names
525
+ * when it renders the node, as with the dev server: the build lists them
526
+ * for every file of the host it has, by its path from the root of the
527
+ * project, which is the same on every machine.
528
+ *
529
+ * The file also lists the modules of every page route, which a page load
530
+ * starts at once with the stylesheets: see route-chunks.ts.
531
+ */
532
+ function createBuiltFiles(options, segmentsOf) {
533
+ const { environments, getProject } = options;
534
+ const lists = new Set(options.lists);
535
+ const layerOf = (environment) => environment === environments.rsc ? "rsc" : environment === environments.browser ? "browser" : void 0;
536
+ let manager;
537
+ let publicDir = false;
538
+ const key = (layer, id) => `${layer}\0${id}`;
539
+ const compiled = /* @__PURE__ */ new Map();
540
+ const files = /* @__PURE__ */ new Map();
541
+ const fonts = /* @__PURE__ */ new Map();
542
+ const routes = /* @__PURE__ */ new Map();
543
+ const hostFiles = /* @__PURE__ */ new Map();
544
+ const clients = /* @__PURE__ */ new Map();
545
+ const modules = /* @__PURE__ */ new Map();
546
+ const publicUrls = /* @__PURE__ */ new Map();
547
+ let listed = false;
548
+ const publicUrl = (hash) => {
549
+ if (!listed) {
550
+ listed = true;
551
+ const files = publicDir ? fs.readdirSync(publicDir, { recursive: true }) : [];
552
+ for (const file of files) {
553
+ const url = `/${normalizePath(String(file))}`;
554
+ publicUrls.set(publicAssetHash(url), url);
555
+ }
556
+ }
557
+ return publicUrls.get(hash);
558
+ };
559
+ function importsIn(context) {
560
+ const imports = /* @__PURE__ */ new Map();
561
+ return (id) => {
562
+ if (!imports.has(id)) {
563
+ const info = context.getModuleInfo(id);
564
+ imports.set(id, info ? [...info.importedIds, ...info.dynamicallyImportedIds] : void 0);
565
+ }
566
+ return imports.get(id);
567
+ };
568
+ }
569
+ function reachIn(imports, starts, references = {}) {
570
+ const reached = [];
571
+ const seen = /* @__PURE__ */ new Set();
572
+ const visit = (id) => {
573
+ if (seen.has(id) || lists.has(id)) return;
574
+ seen.add(id);
575
+ const reference = references[id];
576
+ if (reference) {
577
+ reached.push({ client: reference.importId });
578
+ return;
579
+ }
580
+ for (const imported of imports(id) ?? []) if (isLinked(imported)) reached.push({ stylesheet: imported });
581
+ else if (!isCSSRequest(imported)) visit(imported);
582
+ };
583
+ starts.forEach(visit);
584
+ return reached;
585
+ }
586
+ const plugin = {
587
+ name: "vitest-plugin-rsc:next-styles-build",
588
+ apply: "build",
589
+ configResolved(config) {
590
+ manager = getPluginApi(config)?.manager;
591
+ publicDir = config.publicDir || false;
592
+ },
593
+ buildStart() {
594
+ const layer = layerOf(this.environment.name);
595
+ if (!layer || manager?.isScanBuild) return;
596
+ for (const map of [compiled, files]) for (const id of map.keys()) if (id.startsWith(key(layer, ""))) map.delete(id);
597
+ if (layer === "rsc") {
598
+ routes.clear();
599
+ hostFiles.clear();
600
+ modules.clear();
601
+ } else clients.clear();
602
+ },
603
+ transform(code, id) {
604
+ const layer = layerOf(this.environment.name);
605
+ if (!layer || manager?.isScanBuild || !isLinked(id) || directRE.test(id)) return;
606
+ compiled.set(key(layer, id), code);
607
+ },
608
+ async buildEnd(error) {
609
+ const layer = layerOf(this.environment.name);
610
+ if (error || !layer || !manager || manager.isScanBuild) return;
611
+ const imports = importsIn(this);
612
+ if (layer === "rsc") {
613
+ for (const [entry, route] of options.pageRoutes()) {
614
+ const segments = /* @__PURE__ */ new Map();
615
+ for (const { file, stylesheetsKey } of await segmentsOf(route)) {
616
+ let id = normalizePath(file);
617
+ if (!this.getModuleInfo(id) && fs.existsSync(file)) id = normalizePath(fs.realpathSync(file));
618
+ const reached = reachIn(imports, [id], manager.clientReferenceMetaMap);
619
+ segments.set(stylesheetsKey, reached);
620
+ }
621
+ if ("component" in route) segments.set(componentPagePath, []);
622
+ routes.set(entry, segments);
623
+ }
624
+ const project = getProject();
625
+ const { pageExtensions = [] } = project.config;
626
+ for (const id of this.getModuleIds()) {
627
+ if (!isCode(id, pageExtensions)) continue;
628
+ const file = builtHostFileOf(id, project.root, options.isHostFile);
629
+ if (file === void 0) continue;
630
+ hostFiles.set(file, reachIn(imports, [id], manager.clientReferenceMetaMap));
631
+ }
632
+ return;
633
+ }
634
+ const stylesheetsOf = (reached) => reached.flatMap((item) => "stylesheet" in item ? [item.stylesheet] : []);
635
+ const importer = `\0${clientReferencesId}`;
636
+ const reached = [...[...routes.values()].flatMap((segments) => [...segments.values()]), ...hostFiles.values()];
637
+ for (const item of reached.flat()) {
638
+ if (!("client" in item) || clients.has(item.client)) continue;
639
+ const resolved = await this.resolve(item.client, importer);
640
+ clients.set(item.client, resolved ? stylesheetsOf(reachIn(imports, [resolved.id])) : []);
641
+ }
642
+ },
643
+ async generateBundle(_options, bundle) {
644
+ const layer = layerOf(this.environment.name);
645
+ if (!layer || manager?.isScanBuild) return;
646
+ if (layer === "rsc") {
647
+ const routes = Array.from(options.pageRoutes().keys(), (route) => {
648
+ const entry = options.entryIdOf(route);
649
+ return [route, [entry, ...this.getModuleInfo(entry)?.dynamicallyImportedIds ?? []]];
650
+ });
651
+ for (const [route, chunks] of routeChunksOf(bundle, [...lists], routes)) modules.set(route, chunks);
652
+ }
653
+ const directory = `${getProject().assetPath.slice(1)}static/css/`;
654
+ const toRoot = toBuildDir(`${directory}stylesheet.css`);
655
+ for (const [id, css] of compiled) {
656
+ if (!id.startsWith(key(layer, ""))) continue;
657
+ const source = css.replace(builtAssetRE, (_, reference) => toRoot + this.getFileName(reference)).replace(publicAssetRE, (placeholder, hash) => {
658
+ const url = publicUrl(hash);
659
+ return url ? toRoot + url.slice(1) : placeholder;
660
+ }).replaceAll(`${cssBuildDirPlaceholder}/`, toRoot);
661
+ const file = id.slice(key(layer, "").length).split("?")[0];
662
+ const name = file.startsWith("\0") ? "font" : path.basename(file).replace(/\.[^.]*$/, "");
663
+ const hash = createHash("sha256").update(source).digest("hex").slice(0, 8);
664
+ const fileName = `${directory}${name.replace(/[^\w.-]+/g, "_")}-${hash}.css`;
665
+ this.emitFile({
666
+ type: "asset",
667
+ fileName,
668
+ source
669
+ });
670
+ files.set(id, fileName);
671
+ const request = fontRequestOf(file);
672
+ if (request !== void 0) {
673
+ const { files: fontFiles } = await getProject().loadFont(request);
674
+ const assetDirectory = getProject().assetPath.slice(1);
675
+ fonts.set(fileName, fontFiles.map((font) => assetDirectory + font));
676
+ }
677
+ }
678
+ }
679
+ };
680
+ const urls = {
681
+ name: "vitest-plugin-rsc:next-styles-build-urls",
682
+ apply: "build",
683
+ enforce: "pre",
684
+ transform(code, id) {
685
+ if (!layerOf(this.environment.name) || !isLinked(id) || directRE.test(id)) return;
686
+ for (const match of code.matchAll(cssUrlRE)) {
687
+ const url = match.slice(1).find((group) => group !== void 0).replace(/\\(\W)/g, "$1");
688
+ if (!url.startsWith("/") || url.startsWith("//")) continue;
689
+ try {
690
+ const decoded = decodeURI(url);
691
+ publicUrls.set(publicAssetHash(decoded), decoded);
692
+ } catch {}
693
+ }
694
+ }
695
+ };
696
+ /**
697
+ * The stylesheets of every page route and every file of the host, and the
698
+ * modules of every page route, by the files of the build.
699
+ */
700
+ function builtFiles() {
701
+ if (routes.size === 0) return [];
702
+ const built = {
703
+ assetPath: getProject().assetPath,
704
+ routes: {},
705
+ hostFiles: {},
706
+ chunks: [],
707
+ modules: {},
708
+ fonts: Object.fromEntries([...fonts].sort(([a], [b]) => a.localeCompare(b)))
709
+ };
710
+ const indexes = /* @__PURE__ */ new Map();
711
+ for (const [route, chunks] of modules) built.modules[route] = chunks.map((chunk) => {
712
+ if (!indexes.has(chunk)) indexes.set(chunk, built.chunks.push(chunk) - 1);
713
+ return indexes.get(chunk);
714
+ });
715
+ const filesOf = (ids) => [...new Set(ids.flatMap((id) => files.get(id) ?? []))];
716
+ const idsOf = (reached) => reached.flatMap((item) => "stylesheet" in item ? [key("rsc", item.stylesheet)] : (clients.get(item.client) ?? []).map((id) => key("browser", id)));
717
+ for (const [entry, segments] of routes) built.routes[entry] = Object.fromEntries(Array.from(segments, ([segment, reached]) => [segment, filesOf(idsOf(reached))]));
718
+ for (const file of [...hostFiles.keys()].sort()) built.hostFiles[file] = filesOf(idsOf(hostFiles.get(file)));
719
+ return [{
720
+ pathname: `/${builtFilesPath}`,
721
+ body: Buffer.from(JSON.stringify(built))
722
+ }];
723
+ }
724
+ return {
725
+ plugins: [urls, plugin],
726
+ files: builtFiles
727
+ };
728
+ }
729
+ //#endregion
730
+ export { builtHostFileKey, builtHostFileOf, changesInPlace, createStyles, declareImportedLayers, exportsOfStylesheet, isCode, linked, movesItsLinks };