vinext 0.0.50 → 0.0.51

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 (309) hide show
  1. package/dist/build/google-fonts/fallback-metrics-data.js +14031 -0
  2. package/dist/build/google-fonts/fallback-metrics-data.js.map +1 -0
  3. package/dist/build/google-fonts/fallback-metrics.d.ts +13 -0
  4. package/dist/build/google-fonts/fallback-metrics.js +46 -0
  5. package/dist/build/google-fonts/fallback-metrics.js.map +1 -0
  6. package/dist/build/precompress.d.ts +13 -2
  7. package/dist/build/precompress.js +12 -3
  8. package/dist/build/precompress.js.map +1 -1
  9. package/dist/build/prerender.d.ts +1 -1
  10. package/dist/build/prerender.js +44 -14
  11. package/dist/build/prerender.js.map +1 -1
  12. package/dist/build/report.d.ts +5 -4
  13. package/dist/build/report.js +196 -348
  14. package/dist/build/report.js.map +1 -1
  15. package/dist/check.js +1 -0
  16. package/dist/check.js.map +1 -1
  17. package/dist/cli.js +60 -3
  18. package/dist/cli.js.map +1 -1
  19. package/dist/client/window-next.d.ts +3 -1
  20. package/dist/client/window-next.js.map +1 -1
  21. package/dist/config/dotenv.d.ts +11 -1
  22. package/dist/config/dotenv.js.map +1 -1
  23. package/dist/config/next-config.d.ts +87 -3
  24. package/dist/config/next-config.js +222 -6
  25. package/dist/config/next-config.js.map +1 -1
  26. package/dist/config/tsconfig-paths.d.ts +13 -0
  27. package/dist/config/tsconfig-paths.js +117 -0
  28. package/dist/config/tsconfig-paths.js.map +1 -0
  29. package/dist/deploy.js +3 -2
  30. package/dist/deploy.js.map +1 -1
  31. package/dist/entries/app-browser-entry.d.ts +2 -2
  32. package/dist/entries/app-browser-entry.js +26 -1
  33. package/dist/entries/app-browser-entry.js.map +1 -1
  34. package/dist/entries/app-rsc-entry.d.ts +19 -1
  35. package/dist/entries/app-rsc-entry.js +38 -12
  36. package/dist/entries/app-rsc-entry.js.map +1 -1
  37. package/dist/entries/app-rsc-manifest.d.ts +9 -0
  38. package/dist/entries/app-rsc-manifest.js +4 -1
  39. package/dist/entries/app-rsc-manifest.js.map +1 -1
  40. package/dist/entries/pages-client-entry.js +3 -5
  41. package/dist/entries/pages-client-entry.js.map +1 -1
  42. package/dist/entries/pages-server-entry.js +19 -1
  43. package/dist/entries/pages-server-entry.js.map +1 -1
  44. package/dist/index.js +130 -37
  45. package/dist/index.js.map +1 -1
  46. package/dist/plugins/client-reference-dedup.d.ts +15 -2
  47. package/dist/plugins/client-reference-dedup.js +138 -16
  48. package/dist/plugins/client-reference-dedup.js.map +1 -1
  49. package/dist/plugins/fonts.d.ts +2 -2
  50. package/dist/plugins/fonts.js +15 -6
  51. package/dist/plugins/fonts.js.map +1 -1
  52. package/dist/plugins/sass.d.ts +34 -0
  53. package/dist/plugins/sass.js +22 -0
  54. package/dist/plugins/sass.js.map +1 -0
  55. package/dist/routing/app-route-graph.d.ts +31 -2
  56. package/dist/routing/app-route-graph.js +82 -10
  57. package/dist/routing/app-route-graph.js.map +1 -1
  58. package/dist/routing/route-pattern.d.ts +56 -1
  59. package/dist/routing/route-pattern.js +60 -1
  60. package/dist/routing/route-pattern.js.map +1 -1
  61. package/dist/server/app-browser-action-result.d.ts +27 -2
  62. package/dist/server/app-browser-action-result.js +63 -2
  63. package/dist/server/app-browser-action-result.js.map +1 -1
  64. package/dist/server/app-browser-entry.js +262 -108
  65. package/dist/server/app-browser-entry.js.map +1 -1
  66. package/dist/server/app-browser-hydration.d.ts +13 -1
  67. package/dist/server/app-browser-hydration.js +9 -1
  68. package/dist/server/app-browser-hydration.js.map +1 -1
  69. package/dist/server/app-browser-navigation-controller.d.ts +14 -1
  70. package/dist/server/app-browser-navigation-controller.js +28 -9
  71. package/dist/server/app-browser-navigation-controller.js.map +1 -1
  72. package/dist/server/app-browser-popstate.d.ts +16 -0
  73. package/dist/server/app-browser-popstate.js +17 -0
  74. package/dist/server/app-browser-popstate.js.map +1 -0
  75. package/dist/server/app-browser-rsc-redirect.d.ts +28 -0
  76. package/dist/server/app-browser-rsc-redirect.js +37 -0
  77. package/dist/server/app-browser-rsc-redirect.js.map +1 -0
  78. package/dist/server/app-browser-state.d.ts +11 -7
  79. package/dist/server/app-browser-state.js +45 -27
  80. package/dist/server/app-browser-state.js.map +1 -1
  81. package/dist/server/app-browser-stream.d.ts +5 -4
  82. package/dist/server/app-browser-stream.js +5 -6
  83. package/dist/server/app-browser-stream.js.map +1 -1
  84. package/dist/server/app-browser-visible-commit.d.ts +5 -0
  85. package/dist/server/app-browser-visible-commit.js +38 -5
  86. package/dist/server/app-browser-visible-commit.js.map +1 -1
  87. package/dist/server/app-elements-wire.d.ts +38 -6
  88. package/dist/server/app-elements-wire.js +106 -6
  89. package/dist/server/app-elements-wire.js.map +1 -1
  90. package/dist/server/app-elements.d.ts +2 -2
  91. package/dist/server/app-elements.js +2 -2
  92. package/dist/server/app-elements.js.map +1 -1
  93. package/dist/server/app-fallback-renderer.d.ts +10 -1
  94. package/dist/server/app-fallback-renderer.js +37 -1
  95. package/dist/server/app-fallback-renderer.js.map +1 -1
  96. package/dist/server/app-history-state.d.ts +26 -0
  97. package/dist/server/app-history-state.js +53 -0
  98. package/dist/server/app-history-state.js.map +1 -0
  99. package/dist/server/app-page-boundary-render.d.ts +10 -1
  100. package/dist/server/app-page-boundary-render.js +13 -6
  101. package/dist/server/app-page-boundary-render.js.map +1 -1
  102. package/dist/server/app-page-boundary.js +3 -2
  103. package/dist/server/app-page-boundary.js.map +1 -1
  104. package/dist/server/app-page-cache.d.ts +13 -0
  105. package/dist/server/app-page-cache.js +25 -8
  106. package/dist/server/app-page-cache.js.map +1 -1
  107. package/dist/server/app-page-dispatch.d.ts +5 -0
  108. package/dist/server/app-page-dispatch.js +68 -11
  109. package/dist/server/app-page-dispatch.js.map +1 -1
  110. package/dist/server/app-page-element-builder.d.ts +7 -0
  111. package/dist/server/app-page-element-builder.js +32 -4
  112. package/dist/server/app-page-element-builder.js.map +1 -1
  113. package/dist/server/app-page-execution.js +2 -3
  114. package/dist/server/app-page-execution.js.map +1 -1
  115. package/dist/server/app-page-head.d.ts +7 -0
  116. package/dist/server/app-page-head.js +2 -1
  117. package/dist/server/app-page-head.js.map +1 -1
  118. package/dist/server/app-page-probe.d.ts +23 -1
  119. package/dist/server/app-page-probe.js +29 -1
  120. package/dist/server/app-page-probe.js.map +1 -1
  121. package/dist/server/app-page-render-observation.d.ts +35 -0
  122. package/dist/server/app-page-render-observation.js +68 -0
  123. package/dist/server/app-page-render-observation.js.map +1 -0
  124. package/dist/server/app-page-render.d.ts +5 -1
  125. package/dist/server/app-page-render.js +79 -3
  126. package/dist/server/app-page-render.js.map +1 -1
  127. package/dist/server/app-page-request.d.ts +1 -0
  128. package/dist/server/app-page-request.js.map +1 -1
  129. package/dist/server/app-page-response.js +3 -2
  130. package/dist/server/app-page-response.js.map +1 -1
  131. package/dist/server/app-page-route-wiring.d.ts +3 -1
  132. package/dist/server/app-page-route-wiring.js +42 -14
  133. package/dist/server/app-page-route-wiring.js.map +1 -1
  134. package/dist/server/app-page-stream.d.ts +2 -0
  135. package/dist/server/app-page-stream.js +1 -0
  136. package/dist/server/app-page-stream.js.map +1 -1
  137. package/dist/server/app-router-entry.js +1 -13
  138. package/dist/server/app-router-entry.js.map +1 -1
  139. package/dist/server/app-rsc-cache-busting.d.ts +19 -1
  140. package/dist/server/app-rsc-cache-busting.js +36 -1
  141. package/dist/server/app-rsc-cache-busting.js.map +1 -1
  142. package/dist/server/app-rsc-embedded-chunks.d.ts +9 -0
  143. package/dist/server/app-rsc-embedded-chunks.js +34 -0
  144. package/dist/server/app-rsc-embedded-chunks.js.map +1 -0
  145. package/dist/server/app-rsc-errors.d.ts +4 -1
  146. package/dist/server/app-rsc-errors.js +1 -1
  147. package/dist/server/app-rsc-errors.js.map +1 -1
  148. package/dist/server/app-rsc-handler.d.ts +12 -4
  149. package/dist/server/app-rsc-handler.js +6 -1
  150. package/dist/server/app-rsc-handler.js.map +1 -1
  151. package/dist/server/app-rsc-route-matching.d.ts +23 -0
  152. package/dist/server/app-rsc-route-matching.js +45 -23
  153. package/dist/server/app-rsc-route-matching.js.map +1 -1
  154. package/dist/server/app-server-action-execution.d.ts +35 -3
  155. package/dist/server/app-server-action-execution.js +87 -33
  156. package/dist/server/app-server-action-execution.js.map +1 -1
  157. package/dist/server/app-ssr-entry.d.ts +1 -0
  158. package/dist/server/app-ssr-entry.js +37 -13
  159. package/dist/server/app-ssr-entry.js.map +1 -1
  160. package/dist/server/app-ssr-error-meta.d.ts +14 -0
  161. package/dist/server/app-ssr-error-meta.js +50 -0
  162. package/dist/server/app-ssr-error-meta.js.map +1 -0
  163. package/dist/server/app-ssr-stream.d.ts +1 -1
  164. package/dist/server/app-ssr-stream.js +9 -12
  165. package/dist/server/app-ssr-stream.js.map +1 -1
  166. package/dist/server/artifact-compatibility.d.ts +12 -2
  167. package/dist/server/artifact-compatibility.js +12 -8
  168. package/dist/server/artifact-compatibility.js.map +1 -1
  169. package/dist/server/cache-proof.d.ts +124 -5
  170. package/dist/server/cache-proof.js +416 -18
  171. package/dist/server/cache-proof.js.map +1 -1
  172. package/dist/server/dev-lockfile.d.ts +110 -0
  173. package/dist/server/dev-lockfile.js +180 -0
  174. package/dist/server/dev-lockfile.js.map +1 -0
  175. package/dist/server/dev-server.js +15 -5
  176. package/dist/server/dev-server.js.map +1 -1
  177. package/dist/server/file-based-metadata.d.ts +13 -0
  178. package/dist/server/file-based-metadata.js +49 -2
  179. package/dist/server/file-based-metadata.js.map +1 -1
  180. package/dist/server/headers.d.ts +3 -1
  181. package/dist/server/headers.js +5 -2
  182. package/dist/server/headers.js.map +1 -1
  183. package/dist/server/html.js +1 -1
  184. package/dist/server/html.js.map +1 -1
  185. package/dist/server/http-error-responses.d.ts +10 -0
  186. package/dist/server/http-error-responses.js +11 -1
  187. package/dist/server/http-error-responses.js.map +1 -1
  188. package/dist/server/isr-cache.d.ts +2 -1
  189. package/dist/server/isr-cache.js +4 -2
  190. package/dist/server/isr-cache.js.map +1 -1
  191. package/dist/server/metadata-route-response.js +22 -5
  192. package/dist/server/metadata-route-response.js.map +1 -1
  193. package/dist/server/metadata-routes.js +27 -8
  194. package/dist/server/metadata-routes.js.map +1 -1
  195. package/dist/server/middleware-runtime.js +1 -0
  196. package/dist/server/middleware-runtime.js.map +1 -1
  197. package/dist/server/middleware.d.ts +12 -0
  198. package/dist/server/middleware.js +12 -0
  199. package/dist/server/middleware.js.map +1 -1
  200. package/dist/server/navigation-planner.d.ts +19 -5
  201. package/dist/server/navigation-planner.js +278 -17
  202. package/dist/server/navigation-planner.js.map +1 -1
  203. package/dist/server/navigation-trace.d.ts +8 -1
  204. package/dist/server/navigation-trace.js +7 -0
  205. package/dist/server/navigation-trace.js.map +1 -1
  206. package/dist/server/normalize-path.d.ts +2 -1
  207. package/dist/server/normalize-path.js +4 -1
  208. package/dist/server/normalize-path.js.map +1 -1
  209. package/dist/server/pages-api-route.js +1 -0
  210. package/dist/server/pages-api-route.js.map +1 -1
  211. package/dist/server/pages-page-data.d.ts +3 -2
  212. package/dist/server/pages-page-data.js +22 -3
  213. package/dist/server/pages-page-data.js.map +1 -1
  214. package/dist/server/pages-page-response.js +1 -1
  215. package/dist/server/prod-server.d.ts +28 -1
  216. package/dist/server/prod-server.js +62 -9
  217. package/dist/server/prod-server.js.map +1 -1
  218. package/dist/server/server-action-not-found.d.ts +16 -3
  219. package/dist/server/server-action-not-found.js +19 -1
  220. package/dist/server/server-action-not-found.js.map +1 -1
  221. package/dist/server/server-globals.d.ts +5 -0
  222. package/dist/server/server-globals.js +37 -0
  223. package/dist/server/server-globals.js.map +1 -0
  224. package/dist/server/static-file-cache.js +1 -1
  225. package/dist/server/static-file-cache.js.map +1 -1
  226. package/dist/shims/cache-runtime.d.ts +19 -2
  227. package/dist/shims/cache-runtime.js +67 -11
  228. package/dist/shims/cache-runtime.js.map +1 -1
  229. package/dist/shims/cache.d.ts +5 -18
  230. package/dist/shims/cache.js +2 -0
  231. package/dist/shims/cache.js.map +1 -1
  232. package/dist/shims/error-boundary.js +6 -8
  233. package/dist/shims/error-boundary.js.map +1 -1
  234. package/dist/shims/error.d.ts +18 -1
  235. package/dist/shims/error.js +56 -1
  236. package/dist/shims/error.js.map +1 -1
  237. package/dist/shims/fetch-cache.d.ts +4 -1
  238. package/dist/shims/fetch-cache.js +40 -5
  239. package/dist/shims/fetch-cache.js.map +1 -1
  240. package/dist/shims/font-google-base.d.ts +22 -8
  241. package/dist/shims/font-google-base.js +41 -71
  242. package/dist/shims/font-google-base.js.map +1 -1
  243. package/dist/shims/font-local.d.ts +3 -20
  244. package/dist/shims/font-local.js +23 -75
  245. package/dist/shims/font-local.js.map +1 -1
  246. package/dist/shims/font-utils.d.ts +51 -0
  247. package/dist/shims/font-utils.js +97 -0
  248. package/dist/shims/font-utils.js.map +1 -0
  249. package/dist/shims/hash-scroll.d.ts +7 -0
  250. package/dist/shims/hash-scroll.js +30 -0
  251. package/dist/shims/hash-scroll.js.map +1 -0
  252. package/dist/shims/headers.d.ts +8 -11
  253. package/dist/shims/headers.js +22 -2
  254. package/dist/shims/headers.js.map +1 -1
  255. package/dist/shims/image.d.ts +1 -0
  256. package/dist/shims/image.js +144 -78
  257. package/dist/shims/image.js.map +1 -1
  258. package/dist/shims/internal/app-router-context.d.ts +6 -6
  259. package/dist/shims/internal/app-router-context.js +17 -6
  260. package/dist/shims/internal/app-router-context.js.map +1 -1
  261. package/dist/shims/link-prefetch.d.ts +9 -1
  262. package/dist/shims/link-prefetch.js +11 -6
  263. package/dist/shims/link-prefetch.js.map +1 -1
  264. package/dist/shims/link.d.ts +12 -2
  265. package/dist/shims/link.js +78 -32
  266. package/dist/shims/link.js.map +1 -1
  267. package/dist/shims/metadata.d.ts +16 -30
  268. package/dist/shims/metadata.js +87 -28
  269. package/dist/shims/metadata.js.map +1 -1
  270. package/dist/shims/navigation.d.ts +158 -17
  271. package/dist/shims/navigation.js +324 -74
  272. package/dist/shims/navigation.js.map +1 -1
  273. package/dist/shims/navigation.react-server.d.ts +3 -2
  274. package/dist/shims/navigation.react-server.js +5 -2
  275. package/dist/shims/navigation.react-server.js.map +1 -1
  276. package/dist/shims/pages-router-runtime.d.ts +7 -0
  277. package/dist/shims/pages-router-runtime.js +16 -0
  278. package/dist/shims/pages-router-runtime.js.map +1 -0
  279. package/dist/shims/router.d.ts +32 -6
  280. package/dist/shims/router.js +197 -242
  281. package/dist/shims/router.js.map +1 -1
  282. package/dist/shims/script.js +110 -32
  283. package/dist/shims/script.js.map +1 -1
  284. package/dist/shims/server.js +2 -1
  285. package/dist/shims/server.js.map +1 -1
  286. package/dist/shims/slot.d.ts +1 -0
  287. package/dist/shims/slot.js +41 -1
  288. package/dist/shims/slot.js.map +1 -1
  289. package/dist/shims/unified-request-context.js +2 -0
  290. package/dist/shims/unified-request-context.js.map +1 -1
  291. package/dist/shims/unrecognized-action-error.d.ts +35 -0
  292. package/dist/shims/unrecognized-action-error.js +41 -0
  293. package/dist/shims/unrecognized-action-error.js.map +1 -0
  294. package/dist/shims/url-utils.d.ts +21 -1
  295. package/dist/shims/url-utils.js +67 -3
  296. package/dist/shims/url-utils.js.map +1 -1
  297. package/dist/utils/asset-prefix.d.ts +69 -0
  298. package/dist/utils/asset-prefix.js +91 -0
  299. package/dist/utils/asset-prefix.js.map +1 -0
  300. package/dist/utils/base-path.d.ts +7 -1
  301. package/dist/utils/base-path.js +10 -1
  302. package/dist/utils/base-path.js.map +1 -1
  303. package/dist/utils/navigation-signal.d.ts +1 -2
  304. package/dist/utils/navigation-signal.js +1 -1
  305. package/dist/utils/navigation-signal.js.map +1 -1
  306. package/dist/utils/sorted-array.d.ts +9 -0
  307. package/dist/utils/sorted-array.js +22 -0
  308. package/dist/utils/sorted-array.js.map +1 -0
  309. package/package.json +3 -3
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fallback-metrics-data.js","names":[],"sources":["../../../src/build/google-fonts/fallback-metrics-data.json"],"sourcesContent":[""],"mappings":""}
@@ -0,0 +1,13 @@
1
+ //#region src/build/google-fonts/fallback-metrics.d.ts
2
+ type AdjustFontFallback = {
3
+ fallbackFont: string;
4
+ ascentOverride: string;
5
+ descentOverride: string;
6
+ lineGapOverride: string;
7
+ sizeAdjust: string;
8
+ };
9
+ declare function getFallbackFontOverrideMetrics(fontFamily: string): AdjustFontFallback | undefined;
10
+ declare function buildFallbackFontFace(family: string, metrics: AdjustFontFallback): string;
11
+ //#endregion
12
+ export { buildFallbackFontFace, getFallbackFontOverrideMetrics };
13
+ //# sourceMappingURL=fallback-metrics.d.ts.map
@@ -0,0 +1,46 @@
1
+ import { escapeCSSString } from "../../shims/font-utils.js";
2
+ import fallback_metrics_data_default from "./fallback-metrics-data.js";
3
+ //#region src/build/google-fonts/fallback-metrics.ts
4
+ const EXPECTED_METRIC_LENGTH = 6;
5
+ const fallbackMetrics = fallback_metrics_data_default;
6
+ function formatName(value) {
7
+ return value.replace(/(?:^\w|[A-Z]|\b\w)/g, (word, index) => index === 0 ? word.toLowerCase() : word.toUpperCase()).replace(/\s+/g, "");
8
+ }
9
+ function formatOverrideValue(value) {
10
+ return Math.abs(value * 100).toFixed(2);
11
+ }
12
+ function getFallbackFontOverrideMetrics(fontFamily) {
13
+ const metric = fallbackMetrics[formatName(fontFamily)];
14
+ if (!metric || metric.length !== EXPECTED_METRIC_LENGTH) return void 0;
15
+ const [serifFlag, ascent, descent, lineGap, unitsPerEm, xWidthAvg] = metric;
16
+ if (unitsPerEm === 0) return void 0;
17
+ const fallbackFont = serifFlag === 1 ? "Times New Roman" : "Arial";
18
+ const fallbackMetric = fallbackMetrics[formatName(fallbackFont)];
19
+ if (!fallbackMetric || fallbackMetric.length !== EXPECTED_METRIC_LENGTH) return void 0;
20
+ const [, , , , fallbackUnitsPerEm, fallbackXWidthAvg] = fallbackMetric;
21
+ if (fallbackUnitsPerEm === 0) return void 0;
22
+ const mainFontAvgWidth = xWidthAvg / unitsPerEm;
23
+ const fallbackFontAvgWidth = fallbackXWidthAvg / fallbackUnitsPerEm;
24
+ const sizeAdjust = xWidthAvg && fallbackFontAvgWidth ? mainFontAvgWidth / fallbackFontAvgWidth : 1;
25
+ return {
26
+ fallbackFont,
27
+ ascentOverride: `${formatOverrideValue(ascent / (unitsPerEm * sizeAdjust))}%`,
28
+ descentOverride: `${formatOverrideValue(descent / (unitsPerEm * sizeAdjust))}%`,
29
+ lineGapOverride: `${formatOverrideValue(lineGap / (unitsPerEm * sizeAdjust))}%`,
30
+ sizeAdjust: `${formatOverrideValue(sizeAdjust)}%`
31
+ };
32
+ }
33
+ function buildFallbackFontFace(family, metrics) {
34
+ return `@font-face {
35
+ font-family: ${`'${escapeCSSString(family)} Fallback'`};
36
+ src: local("${escapeCSSString(metrics.fallbackFont)}");
37
+ ascent-override: ${metrics.ascentOverride};
38
+ descent-override: ${metrics.descentOverride};
39
+ line-gap-override: ${metrics.lineGapOverride};
40
+ size-adjust: ${metrics.sizeAdjust};
41
+ }\n`;
42
+ }
43
+ //#endregion
44
+ export { buildFallbackFontFace, getFallbackFontOverrideMetrics };
45
+
46
+ //# sourceMappingURL=fallback-metrics.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fallback-metrics.js","names":["rawFallbackMetrics"],"sources":["../../../src/build/google-fonts/fallback-metrics.ts"],"sourcesContent":["// Compact fallback metrics derived from Next.js\n// `next/dist/server/capsize-font-metrics.json`.\n//\n// The tuple shape is:\n// [serifFlag, ascent, descent, lineGap, unitsPerEm, xWidthAvg]\n\nimport { escapeCSSString } from \"vinext/shims/font-utils\";\nimport rawFallbackMetrics from \"./fallback-metrics-data.json\" with { type: \"json\" };\n\ntype AdjustFontFallback = {\n fallbackFont: string;\n ascentOverride: string;\n descentOverride: string;\n lineGapOverride: string;\n sizeAdjust: string;\n};\n\nconst EXPECTED_METRIC_LENGTH = 6;\nconst fallbackMetrics: Record<string, number[]> = rawFallbackMetrics;\n\nfunction formatName(value: string): string {\n return value\n .replace(/(?:^\\w|[A-Z]|\\b\\w)/g, (word, index) =>\n index === 0 ? word.toLowerCase() : word.toUpperCase(),\n )\n .replace(/\\s+/g, \"\");\n}\n\nfunction formatOverrideValue(value: number): string {\n return Math.abs(value * 100).toFixed(2);\n}\n\nexport function getFallbackFontOverrideMetrics(fontFamily: string): AdjustFontFallback | undefined {\n const metric = fallbackMetrics[formatName(fontFamily)];\n if (!metric || metric.length !== EXPECTED_METRIC_LENGTH) return undefined;\n\n const [serifFlag, ascent, descent, lineGap, unitsPerEm, xWidthAvg] = metric;\n if (unitsPerEm === 0) return undefined;\n\n const fallbackFont = serifFlag === 1 ? \"Times New Roman\" : \"Arial\";\n const fallbackMetric = fallbackMetrics[formatName(fallbackFont)];\n if (!fallbackMetric || fallbackMetric.length !== EXPECTED_METRIC_LENGTH) return undefined;\n\n const [, , , , fallbackUnitsPerEm, fallbackXWidthAvg] = fallbackMetric;\n if (fallbackUnitsPerEm === 0) return undefined;\n\n const mainFontAvgWidth = xWidthAvg / unitsPerEm;\n const fallbackFontAvgWidth = fallbackXWidthAvg / fallbackUnitsPerEm;\n const sizeAdjust =\n xWidthAvg && fallbackFontAvgWidth ? mainFontAvgWidth / fallbackFontAvgWidth : 1;\n\n return {\n fallbackFont,\n ascentOverride: `${formatOverrideValue(ascent / (unitsPerEm * sizeAdjust))}%`,\n descentOverride: `${formatOverrideValue(descent / (unitsPerEm * sizeAdjust))}%`,\n lineGapOverride: `${formatOverrideValue(lineGap / (unitsPerEm * sizeAdjust))}%`,\n sizeAdjust: `${formatOverrideValue(sizeAdjust)}%`,\n };\n}\n\n// The fallback family name pattern '{family} Fallback' must match the name\n// constructed in createFontLoader() in shims/font-google-base.ts. Keep both\n// sites in sync to prevent silent fallback mismatches.\nexport function buildFallbackFontFace(family: string, metrics: AdjustFontFallback): string {\n const fallbackFamily = `'${escapeCSSString(family)} Fallback'`;\n return `@font-face {\n font-family: ${fallbackFamily};\n src: local(\"${escapeCSSString(metrics.fallbackFont)}\");\n ascent-override: ${metrics.ascentOverride};\n descent-override: ${metrics.descentOverride};\n line-gap-override: ${metrics.lineGapOverride};\n size-adjust: ${metrics.sizeAdjust};\n}\\n`;\n}\n"],"mappings":";;;AAiBA,MAAM,yBAAyB;AAC/B,MAAM,kBAA4CA;AAElD,SAAS,WAAW,OAAuB;CACzC,OAAO,MACJ,QAAQ,wBAAwB,MAAM,UACrC,UAAU,IAAI,KAAK,aAAa,GAAG,KAAK,aAAa,CACtD,CACA,QAAQ,QAAQ,GAAG;;AAGxB,SAAS,oBAAoB,OAAuB;CAClD,OAAO,KAAK,IAAI,QAAQ,IAAI,CAAC,QAAQ,EAAE;;AAGzC,SAAgB,+BAA+B,YAAoD;CACjG,MAAM,SAAS,gBAAgB,WAAW,WAAW;CACrD,IAAI,CAAC,UAAU,OAAO,WAAW,wBAAwB,OAAO,KAAA;CAEhE,MAAM,CAAC,WAAW,QAAQ,SAAS,SAAS,YAAY,aAAa;CACrE,IAAI,eAAe,GAAG,OAAO,KAAA;CAE7B,MAAM,eAAe,cAAc,IAAI,oBAAoB;CAC3D,MAAM,iBAAiB,gBAAgB,WAAW,aAAa;CAC/D,IAAI,CAAC,kBAAkB,eAAe,WAAW,wBAAwB,OAAO,KAAA;CAEhF,MAAM,SAAS,oBAAoB,qBAAqB;CACxD,IAAI,uBAAuB,GAAG,OAAO,KAAA;CAErC,MAAM,mBAAmB,YAAY;CACrC,MAAM,uBAAuB,oBAAoB;CACjD,MAAM,aACJ,aAAa,uBAAuB,mBAAmB,uBAAuB;CAEhF,OAAO;EACL;EACA,gBAAgB,GAAG,oBAAoB,UAAU,aAAa,YAAY,CAAC;EAC3E,iBAAiB,GAAG,oBAAoB,WAAW,aAAa,YAAY,CAAC;EAC7E,iBAAiB,GAAG,oBAAoB,WAAW,aAAa,YAAY,CAAC;EAC7E,YAAY,GAAG,oBAAoB,WAAW,CAAC;EAChD;;AAMH,SAAgB,sBAAsB,QAAgB,SAAqC;CAEzF,OAAO;iBACQ,IAFY,gBAAgB,OAAO,CAAC,YAErB;gBAChB,gBAAgB,QAAQ,aAAa,CAAC;qBACjC,QAAQ,eAAe;sBACtB,QAAQ,gBAAgB;uBACvB,QAAQ,gBAAgB;iBAC9B,QAAQ,WAAW"}
@@ -5,13 +5,24 @@ type PrecompressResult = {
5
5
  totalBrotliBytes: number;
6
6
  };
7
7
  /**
8
- * Precompress all compressible hashed assets under `clientDir/assets/`.
8
+ * Precompress all compressible hashed assets under `clientDir/<assetsDir>/`.
9
9
  *
10
10
  * Writes `.br`, `.gz`, and `.zst` files alongside each original.
11
11
  * Safe to re-run — overwrites existing compressed variants with identical
12
12
  * output, and never compresses `.br`, `.gz`, or `.zst` files themselves.
13
+ *
14
+ * `assetsDir` defaults to `"assets"` (Vite's historical default). When
15
+ * `assetPrefix` is configured the build writes assets to a different
16
+ * directory (e.g. `"cdn/_next/static"` for a path prefix, or `"_next/static"`
17
+ * for an absolute URL prefix); callers should resolve that with
18
+ * `resolveAssetsDir(assetPrefix)` and thread it through. Without this,
19
+ * `assetPrefix` builds would walk an empty `assets/` directory and emit
20
+ * zero compressed variants.
13
21
  */
14
- declare function precompressAssets(clientDir: string, onProgress?: (completed: number, total: number, file: string) => void): Promise<PrecompressResult>;
22
+ declare function precompressAssets(clientDir: string, options?: {
23
+ /** Subdirectory under `clientDir` containing hashed assets. Defaults to `"assets"`. */assetsDir?: string;
24
+ onProgress?: (completed: number, total: number, file: string) => void;
25
+ }): Promise<PrecompressResult>;
15
26
  //#endregion
16
27
  export { precompressAssets };
17
28
  //# sourceMappingURL=precompress.d.ts.map
@@ -56,14 +56,23 @@ async function* walkFiles(dir, base = dir) {
56
56
  }
57
57
  }
58
58
  /**
59
- * Precompress all compressible hashed assets under `clientDir/assets/`.
59
+ * Precompress all compressible hashed assets under `clientDir/<assetsDir>/`.
60
60
  *
61
61
  * Writes `.br`, `.gz`, and `.zst` files alongside each original.
62
62
  * Safe to re-run — overwrites existing compressed variants with identical
63
63
  * output, and never compresses `.br`, `.gz`, or `.zst` files themselves.
64
+ *
65
+ * `assetsDir` defaults to `"assets"` (Vite's historical default). When
66
+ * `assetPrefix` is configured the build writes assets to a different
67
+ * directory (e.g. `"cdn/_next/static"` for a path prefix, or `"_next/static"`
68
+ * for an absolute URL prefix); callers should resolve that with
69
+ * `resolveAssetsDir(assetPrefix)` and thread it through. Without this,
70
+ * `assetPrefix` builds would walk an empty `assets/` directory and emit
71
+ * zero compressed variants.
64
72
  */
65
- async function precompressAssets(clientDir, onProgress) {
66
- const assetsDir = path.join(clientDir, "assets");
73
+ async function precompressAssets(clientDir, options = {}) {
74
+ const { assetsDir: assetsSubdir = "assets", onProgress } = options;
75
+ const assetsDir = path.join(clientDir, assetsSubdir);
67
76
  const result = {
68
77
  filesCompressed: 0,
69
78
  totalOriginalBytes: 0,
@@ -1 +1 @@
1
- {"version":3,"file":"precompress.js","names":[],"sources":["../../src/build/precompress.ts"],"sourcesContent":["/**\n * Build-time precompression for hashed static assets.\n *\n * Generates .br (brotli q5), .gz (gzip l8), and .zst (zstd l8) files\n * alongside compressible assets in dist/client/assets/. Served directly by\n * the production server — no per-request compression needed for immutable\n * build output.\n *\n * Only targets assets/ (hashed, immutable) — public directory files use\n * on-the-fly compression since they may change between deploys.\n */\nimport fsp from \"node:fs/promises\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport zlib from \"node:zlib\";\nimport { promisify } from \"node:util\";\n\nconst brotliCompress = promisify(zlib.brotliCompress);\nconst gzip = promisify(zlib.gzip);\nconst zstdCompress = typeof zlib.zstdCompress === \"function\" ? promisify(zlib.zstdCompress) : null;\n\n/** File extensions worth compressing (text-based, not already compressed). */\nconst COMPRESSIBLE_EXTENSIONS = new Set([\n \".js\",\n \".mjs\",\n \".css\",\n \".html\",\n \".json\",\n \".xml\",\n \".svg\",\n \".txt\",\n \".map\",\n \".wasm\",\n]);\n\n/** Below this size, compression overhead exceeds savings. */\nconst MIN_SIZE = 1024;\n\n/**\n * Past ~8 parallel files, mixed-size asset sets spend more time queueing zlib\n * work than making forward progress. Keep the batch size bounded even on\n * higher-core machines.\n */\nconst CONCURRENCY = Math.min(os.availableParallelism(), 8);\n\ntype PrecompressResult = {\n filesCompressed: number;\n totalOriginalBytes: number;\n /** Sum of brotli-compressed sizes (used for compression ratio reporting). */\n totalBrotliBytes: number;\n};\n\n/**\n * Walk a directory recursively, yielding relative paths for regular files.\n */\nasync function* walkFiles(dir: string, base: string = dir): AsyncGenerator<string> {\n let entries;\n try {\n entries = await fsp.readdir(dir, { withFileTypes: true });\n } catch {\n return; // directory doesn't exist\n }\n for (const entry of entries) {\n const fullPath = path.join(dir, entry.name);\n if (entry.isDirectory()) {\n yield* walkFiles(fullPath, base);\n } else if (entry.isFile()) {\n yield path.relative(base, fullPath);\n }\n }\n}\n\n/**\n * Precompress all compressible hashed assets under `clientDir/assets/`.\n *\n * Writes `.br`, `.gz`, and `.zst` files alongside each original.\n * Safe to re-run — overwrites existing compressed variants with identical\n * output, and never compresses `.br`, `.gz`, or `.zst` files themselves.\n */\nexport async function precompressAssets(\n clientDir: string,\n onProgress?: (completed: number, total: number, file: string) => void,\n): Promise<PrecompressResult> {\n const assetsDir = path.join(clientDir, \"assets\");\n const result: PrecompressResult = {\n filesCompressed: 0,\n totalOriginalBytes: 0,\n totalBrotliBytes: 0,\n };\n\n // Collect compressible file paths, then read + compress in bounded chunks\n // to keep peak memory at O(CONCURRENCY * max_file_size) instead of\n // O(total_assets).\n const filePaths: string[] = [];\n\n for await (const relativePath of walkFiles(assetsDir)) {\n const ext = path.extname(relativePath).toLowerCase();\n\n if (!COMPRESSIBLE_EXTENSIONS.has(ext)) continue;\n // .br/.gz/.zst are intentionally absent from COMPRESSIBLE_EXTENSIONS, so\n // precompressed variants generated by a previous run are never re-compressed.\n\n filePaths.push(path.join(assetsDir, relativePath));\n }\n\n let processed = 0;\n for (let i = 0; i < filePaths.length; i += CONCURRENCY) {\n const chunk = filePaths.slice(i, i + CONCURRENCY);\n await Promise.all(\n chunk.map(async (fullPath) => {\n const content = await fsp.readFile(fullPath);\n // readFile already done before this check — stat()-first would save\n // the read for tiny files but costs an extra syscall per file;\n // sub-1KB hashed assets are rare enough that read-first is cheaper.\n if (content.length < MIN_SIZE) return;\n\n // Compress all variants concurrently within each file\n const compressions: Promise<Buffer>[] = [\n brotliCompress(content, {\n params: { [zlib.constants.BROTLI_PARAM_QUALITY]: 5 },\n }),\n gzip(content, { level: 8 }),\n ];\n if (zstdCompress) {\n compressions.push(\n zstdCompress(content, {\n params: { [zlib.constants.ZSTD_c_compressionLevel]: 8 },\n }),\n );\n }\n\n const results = await Promise.all(compressions);\n const [brContent, gzContent, zstdContent] = results;\n\n const writes = [\n fsp.writeFile(fullPath + \".br\", brContent),\n fsp.writeFile(fullPath + \".gz\", gzContent),\n ];\n if (zstdContent) {\n writes.push(fsp.writeFile(fullPath + \".zst\", zstdContent));\n }\n await Promise.all(writes);\n\n // Increment counters only after all writes succeed, so partial\n // failures (e.g. ENOSPC mid-write) don't inflate the reported totals.\n result.filesCompressed++;\n result.totalOriginalBytes += content.length;\n result.totalBrotliBytes += brContent.length;\n }),\n );\n // Report progress once per chunk to avoid non-deterministic ordering\n // within Promise.all (smaller files complete before larger ones).\n // Progress tracks all files (including skipped ones below MIN_SIZE),\n // which differs from filesCompressed (only files actually compressed).\n processed += chunk.length;\n onProgress?.(processed, filePaths.length, path.basename(chunk[chunk.length - 1]));\n }\n\n return result;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAiBA,MAAM,iBAAiB,UAAU,KAAK,eAAe;AACrD,MAAM,OAAO,UAAU,KAAK,KAAK;AACjC,MAAM,eAAe,OAAO,KAAK,iBAAiB,aAAa,UAAU,KAAK,aAAa,GAAG;;AAG9F,MAAM,0BAA0B,IAAI,IAAI;CACtC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD,CAAC;;AAGF,MAAM,WAAW;;;;;;AAOjB,MAAM,cAAc,KAAK,IAAI,GAAG,sBAAsB,EAAE,EAAE;;;;AAY1D,gBAAgB,UAAU,KAAa,OAAe,KAA6B;CACjF,IAAI;CACJ,IAAI;EACF,UAAU,MAAM,IAAI,QAAQ,KAAK,EAAE,eAAe,MAAM,CAAC;SACnD;EACN;;CAEF,KAAK,MAAM,SAAS,SAAS;EAC3B,MAAM,WAAW,KAAK,KAAK,KAAK,MAAM,KAAK;EAC3C,IAAI,MAAM,aAAa,EACrB,OAAO,UAAU,UAAU,KAAK;OAC3B,IAAI,MAAM,QAAQ,EACvB,MAAM,KAAK,SAAS,MAAM,SAAS;;;;;;;;;;AAYzC,eAAsB,kBACpB,WACA,YAC4B;CAC5B,MAAM,YAAY,KAAK,KAAK,WAAW,SAAS;CAChD,MAAM,SAA4B;EAChC,iBAAiB;EACjB,oBAAoB;EACpB,kBAAkB;EACnB;CAKD,MAAM,YAAsB,EAAE;CAE9B,WAAW,MAAM,gBAAgB,UAAU,UAAU,EAAE;EACrD,MAAM,MAAM,KAAK,QAAQ,aAAa,CAAC,aAAa;EAEpD,IAAI,CAAC,wBAAwB,IAAI,IAAI,EAAE;EAIvC,UAAU,KAAK,KAAK,KAAK,WAAW,aAAa,CAAC;;CAGpD,IAAI,YAAY;CAChB,KAAK,IAAI,IAAI,GAAG,IAAI,UAAU,QAAQ,KAAK,aAAa;EACtD,MAAM,QAAQ,UAAU,MAAM,GAAG,IAAI,YAAY;EACjD,MAAM,QAAQ,IACZ,MAAM,IAAI,OAAO,aAAa;GAC5B,MAAM,UAAU,MAAM,IAAI,SAAS,SAAS;GAI5C,IAAI,QAAQ,SAAS,UAAU;GAG/B,MAAM,eAAkC,CACtC,eAAe,SAAS,EACtB,QAAQ,GAAG,KAAK,UAAU,uBAAuB,GAAG,EACrD,CAAC,EACF,KAAK,SAAS,EAAE,OAAO,GAAG,CAAC,CAC5B;GACD,IAAI,cACF,aAAa,KACX,aAAa,SAAS,EACpB,QAAQ,GAAG,KAAK,UAAU,0BAA0B,GAAG,EACxD,CAAC,CACH;GAIH,MAAM,CAAC,WAAW,WAAW,eAAe,MADtB,QAAQ,IAAI,aAAa;GAG/C,MAAM,SAAS,CACb,IAAI,UAAU,WAAW,OAAO,UAAU,EAC1C,IAAI,UAAU,WAAW,OAAO,UAAU,CAC3C;GACD,IAAI,aACF,OAAO,KAAK,IAAI,UAAU,WAAW,QAAQ,YAAY,CAAC;GAE5D,MAAM,QAAQ,IAAI,OAAO;GAIzB,OAAO;GACP,OAAO,sBAAsB,QAAQ;GACrC,OAAO,oBAAoB,UAAU;IACrC,CACH;EAKD,aAAa,MAAM;EACnB,aAAa,WAAW,UAAU,QAAQ,KAAK,SAAS,MAAM,MAAM,SAAS,GAAG,CAAC;;CAGnF,OAAO"}
1
+ {"version":3,"file":"precompress.js","names":[],"sources":["../../src/build/precompress.ts"],"sourcesContent":["/**\n * Build-time precompression for hashed static assets.\n *\n * Generates .br (brotli q5), .gz (gzip l8), and .zst (zstd l8) files\n * alongside compressible assets in dist/client/assets/. Served directly by\n * the production server — no per-request compression needed for immutable\n * build output.\n *\n * Only targets assets/ (hashed, immutable) — public directory files use\n * on-the-fly compression since they may change between deploys.\n */\nimport fsp from \"node:fs/promises\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport zlib from \"node:zlib\";\nimport { promisify } from \"node:util\";\n\nconst brotliCompress = promisify(zlib.brotliCompress);\nconst gzip = promisify(zlib.gzip);\nconst zstdCompress = typeof zlib.zstdCompress === \"function\" ? promisify(zlib.zstdCompress) : null;\n\n/** File extensions worth compressing (text-based, not already compressed). */\nconst COMPRESSIBLE_EXTENSIONS = new Set([\n \".js\",\n \".mjs\",\n \".css\",\n \".html\",\n \".json\",\n \".xml\",\n \".svg\",\n \".txt\",\n \".map\",\n \".wasm\",\n]);\n\n/** Below this size, compression overhead exceeds savings. */\nconst MIN_SIZE = 1024;\n\n/**\n * Past ~8 parallel files, mixed-size asset sets spend more time queueing zlib\n * work than making forward progress. Keep the batch size bounded even on\n * higher-core machines.\n */\nconst CONCURRENCY = Math.min(os.availableParallelism(), 8);\n\ntype PrecompressResult = {\n filesCompressed: number;\n totalOriginalBytes: number;\n /** Sum of brotli-compressed sizes (used for compression ratio reporting). */\n totalBrotliBytes: number;\n};\n\n/**\n * Walk a directory recursively, yielding relative paths for regular files.\n */\nasync function* walkFiles(dir: string, base: string = dir): AsyncGenerator<string> {\n let entries;\n try {\n entries = await fsp.readdir(dir, { withFileTypes: true });\n } catch {\n return; // directory doesn't exist\n }\n for (const entry of entries) {\n const fullPath = path.join(dir, entry.name);\n if (entry.isDirectory()) {\n yield* walkFiles(fullPath, base);\n } else if (entry.isFile()) {\n yield path.relative(base, fullPath);\n }\n }\n}\n\n/**\n * Precompress all compressible hashed assets under `clientDir/<assetsDir>/`.\n *\n * Writes `.br`, `.gz`, and `.zst` files alongside each original.\n * Safe to re-run — overwrites existing compressed variants with identical\n * output, and never compresses `.br`, `.gz`, or `.zst` files themselves.\n *\n * `assetsDir` defaults to `\"assets\"` (Vite's historical default). When\n * `assetPrefix` is configured the build writes assets to a different\n * directory (e.g. `\"cdn/_next/static\"` for a path prefix, or `\"_next/static\"`\n * for an absolute URL prefix); callers should resolve that with\n * `resolveAssetsDir(assetPrefix)` and thread it through. Without this,\n * `assetPrefix` builds would walk an empty `assets/` directory and emit\n * zero compressed variants.\n */\nexport async function precompressAssets(\n clientDir: string,\n options: {\n /** Subdirectory under `clientDir` containing hashed assets. Defaults to `\"assets\"`. */\n assetsDir?: string;\n onProgress?: (completed: number, total: number, file: string) => void;\n } = {},\n): Promise<PrecompressResult> {\n const { assetsDir: assetsSubdir = \"assets\", onProgress } = options;\n const assetsDir = path.join(clientDir, assetsSubdir);\n const result: PrecompressResult = {\n filesCompressed: 0,\n totalOriginalBytes: 0,\n totalBrotliBytes: 0,\n };\n\n // Collect compressible file paths, then read + compress in bounded chunks\n // to keep peak memory at O(CONCURRENCY * max_file_size) instead of\n // O(total_assets).\n const filePaths: string[] = [];\n\n for await (const relativePath of walkFiles(assetsDir)) {\n const ext = path.extname(relativePath).toLowerCase();\n\n if (!COMPRESSIBLE_EXTENSIONS.has(ext)) continue;\n // .br/.gz/.zst are intentionally absent from COMPRESSIBLE_EXTENSIONS, so\n // precompressed variants generated by a previous run are never re-compressed.\n\n filePaths.push(path.join(assetsDir, relativePath));\n }\n\n let processed = 0;\n for (let i = 0; i < filePaths.length; i += CONCURRENCY) {\n const chunk = filePaths.slice(i, i + CONCURRENCY);\n await Promise.all(\n chunk.map(async (fullPath) => {\n const content = await fsp.readFile(fullPath);\n // readFile already done before this check — stat()-first would save\n // the read for tiny files but costs an extra syscall per file;\n // sub-1KB hashed assets are rare enough that read-first is cheaper.\n if (content.length < MIN_SIZE) return;\n\n // Compress all variants concurrently within each file\n const compressions: Promise<Buffer>[] = [\n brotliCompress(content, {\n params: { [zlib.constants.BROTLI_PARAM_QUALITY]: 5 },\n }),\n gzip(content, { level: 8 }),\n ];\n if (zstdCompress) {\n compressions.push(\n zstdCompress(content, {\n params: { [zlib.constants.ZSTD_c_compressionLevel]: 8 },\n }),\n );\n }\n\n const results = await Promise.all(compressions);\n const [brContent, gzContent, zstdContent] = results;\n\n const writes = [\n fsp.writeFile(fullPath + \".br\", brContent),\n fsp.writeFile(fullPath + \".gz\", gzContent),\n ];\n if (zstdContent) {\n writes.push(fsp.writeFile(fullPath + \".zst\", zstdContent));\n }\n await Promise.all(writes);\n\n // Increment counters only after all writes succeed, so partial\n // failures (e.g. ENOSPC mid-write) don't inflate the reported totals.\n result.filesCompressed++;\n result.totalOriginalBytes += content.length;\n result.totalBrotliBytes += brContent.length;\n }),\n );\n // Report progress once per chunk to avoid non-deterministic ordering\n // within Promise.all (smaller files complete before larger ones).\n // Progress tracks all files (including skipped ones below MIN_SIZE),\n // which differs from filesCompressed (only files actually compressed).\n processed += chunk.length;\n onProgress?.(processed, filePaths.length, path.basename(chunk[chunk.length - 1]));\n }\n\n return result;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAiBA,MAAM,iBAAiB,UAAU,KAAK,eAAe;AACrD,MAAM,OAAO,UAAU,KAAK,KAAK;AACjC,MAAM,eAAe,OAAO,KAAK,iBAAiB,aAAa,UAAU,KAAK,aAAa,GAAG;;AAG9F,MAAM,0BAA0B,IAAI,IAAI;CACtC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD,CAAC;;AAGF,MAAM,WAAW;;;;;;AAOjB,MAAM,cAAc,KAAK,IAAI,GAAG,sBAAsB,EAAE,EAAE;;;;AAY1D,gBAAgB,UAAU,KAAa,OAAe,KAA6B;CACjF,IAAI;CACJ,IAAI;EACF,UAAU,MAAM,IAAI,QAAQ,KAAK,EAAE,eAAe,MAAM,CAAC;SACnD;EACN;;CAEF,KAAK,MAAM,SAAS,SAAS;EAC3B,MAAM,WAAW,KAAK,KAAK,KAAK,MAAM,KAAK;EAC3C,IAAI,MAAM,aAAa,EACrB,OAAO,UAAU,UAAU,KAAK;OAC3B,IAAI,MAAM,QAAQ,EACvB,MAAM,KAAK,SAAS,MAAM,SAAS;;;;;;;;;;;;;;;;;;AAoBzC,eAAsB,kBACpB,WACA,UAII,EAAE,EACsB;CAC5B,MAAM,EAAE,WAAW,eAAe,UAAU,eAAe;CAC3D,MAAM,YAAY,KAAK,KAAK,WAAW,aAAa;CACpD,MAAM,SAA4B;EAChC,iBAAiB;EACjB,oBAAoB;EACpB,kBAAkB;EACnB;CAKD,MAAM,YAAsB,EAAE;CAE9B,WAAW,MAAM,gBAAgB,UAAU,UAAU,EAAE;EACrD,MAAM,MAAM,KAAK,QAAQ,aAAa,CAAC,aAAa;EAEpD,IAAI,CAAC,wBAAwB,IAAI,IAAI,EAAE;EAIvC,UAAU,KAAK,KAAK,KAAK,WAAW,aAAa,CAAC;;CAGpD,IAAI,YAAY;CAChB,KAAK,IAAI,IAAI,GAAG,IAAI,UAAU,QAAQ,KAAK,aAAa;EACtD,MAAM,QAAQ,UAAU,MAAM,GAAG,IAAI,YAAY;EACjD,MAAM,QAAQ,IACZ,MAAM,IAAI,OAAO,aAAa;GAC5B,MAAM,UAAU,MAAM,IAAI,SAAS,SAAS;GAI5C,IAAI,QAAQ,SAAS,UAAU;GAG/B,MAAM,eAAkC,CACtC,eAAe,SAAS,EACtB,QAAQ,GAAG,KAAK,UAAU,uBAAuB,GAAG,EACrD,CAAC,EACF,KAAK,SAAS,EAAE,OAAO,GAAG,CAAC,CAC5B;GACD,IAAI,cACF,aAAa,KACX,aAAa,SAAS,EACpB,QAAQ,GAAG,KAAK,UAAU,0BAA0B,GAAG,EACxD,CAAC,CACH;GAIH,MAAM,CAAC,WAAW,WAAW,eAAe,MADtB,QAAQ,IAAI,aAAa;GAG/C,MAAM,SAAS,CACb,IAAI,UAAU,WAAW,OAAO,UAAU,EAC1C,IAAI,UAAU,WAAW,OAAO,UAAU,CAC3C;GACD,IAAI,aACF,OAAO,KAAK,IAAI,UAAU,WAAW,QAAQ,YAAY,CAAC;GAE5D,MAAM,QAAQ,IAAI,OAAO;GAIzB,OAAO;GACP,OAAO,sBAAsB,QAAQ;GACrC,OAAO,oBAAoB,UAAU;IACrC,CACH;EAKD,aAAa,MAAM;EACnB,aAAa,WAAW,UAAU,QAAQ,KAAK,SAAS,MAAM,MAAM,SAAS,GAAG,CAAC;;CAGnF,OAAO"}
@@ -122,7 +122,7 @@ type PrerenderAppOptionsInternal = PrerenderAppOptions & {
122
122
  * Safe regex usage: safeJsonStringify (used by createRscEmbedTransform) escapes
123
123
  * all '<' and '>' in the embedded JSON, preventing false </script> matches.
124
124
  */
125
- declare function extractRscPayloadFromPrerenderedHtml(html: string): string | null;
125
+ declare function extractRscPayloadFromPrerenderedHtml(html: string): Uint8Array | null;
126
126
  /**
127
127
  * Determine the HTML output file path for a URL.
128
128
  * Respects trailingSlash config.
@@ -1,8 +1,10 @@
1
1
  import { createValidFileMatcher, findFileWithExtensions } from "../routing/file-matcher.js";
2
2
  import { VINEXT_PRERENDER_SECRET_HEADER } from "../server/headers.js";
3
+ import { normalizeStaticPathsEntry } from "../routing/route-pattern.js";
3
4
  import { headersContextFromRequest, runWithHeadersContext } from "../shims/headers.js";
4
5
  import { NoOpCacheHandler, _consumeRequestScopedCacheLife, getCacheHandler, setCacheHandler } from "../shims/cache.js";
5
6
  import { classifyAppRoute, classifyPagesRoute, getAppRouteRenderEntryPath } from "./report.js";
7
+ import { concatUint8Arrays, decodeRscEmbeddedChunk } from "../server/app-rsc-embedded-chunks.js";
6
8
  import { readPrerenderSecret } from "./server-manifest.js";
7
9
  import { startProdServer } from "../server/prod-server.js";
8
10
  import fs from "node:fs";
@@ -61,15 +63,15 @@ function extractRscPayloadFromPrerenderedHtml(html) {
61
63
  sawDone = true;
62
64
  continue;
63
65
  }
64
- if (script.startsWith(RSC_CHUNK_SCRIPT_PREFIX)) chunks.push(parseRscChunkPushArgument(script));
66
+ if (script.startsWith(RSC_CHUNK_SCRIPT_PREFIX)) chunks.push(decodeRscEmbeddedChunk(parseRscChunkPushArgument(script)));
65
67
  }
66
68
  if (chunks.length === 0 && !sawDone) return null;
67
69
  if (chunks.length === 0) throw new Error("[vinext] Malformed prerender RSC embed: done marker present without chunk scripts");
68
70
  if (!sawDone) throw new Error("[vinext] Malformed prerender RSC embed: missing __VINEXT_RSC_DONE__ marker");
69
- return chunks.join("");
71
+ return concatUint8Arrays(chunks);
70
72
  }
71
73
  /**
72
- * Parse the JSON-string argument of a single chunk-push script. The script
74
+ * Parse the JSON argument of a single chunk-push script. The script
73
75
  * shape is exactly `<prefix>(<safeJsonStringify(chunk)>)` because the writer
74
76
  * concatenates those literals — so the body always starts with the full
75
77
  * prefix and ends with `)`. JSON.parse on the slice catches any tampering or
@@ -84,8 +86,9 @@ function parseRscChunkPushArgument(script) {
84
86
  } catch {
85
87
  throw new Error("[vinext] Malformed prerender RSC embed: invalid chunk JSON");
86
88
  }
87
- if (typeof parsed !== "string") throw new Error("[vinext] Malformed prerender RSC embed: chunk payload is not a string");
88
- return parsed;
89
+ if (typeof parsed === "string") return parsed;
90
+ if (Array.isArray(parsed) && parsed.length === 2 && parsed[0] === 3 && typeof parsed[1] === "string") return [parsed[0], parsed[1]];
91
+ throw new Error("[vinext] Malformed prerender RSC embed: unsupported chunk payload");
89
92
  }
90
93
  /**
91
94
  * Run an array of async tasks with bounded concurrency.
@@ -109,8 +112,14 @@ async function runWithConcurrency(items, concurrency, fn) {
109
112
  * Build a URL path from a route pattern and params.
110
113
  * "/posts/:id" + { id: "42" } → "/posts/42"
111
114
  * "/docs/:slug+" + { slug: ["a", "b"] } → "/docs/a/b"
115
+ *
116
+ * Throws a descriptive error rather than a cryptic `Cannot read properties of
117
+ * undefined` if `params` itself is missing or required keys are absent — the
118
+ * caller (prerenderPages / prerenderApp) catches this and surfaces it as a
119
+ * per-route error result.
112
120
  */
113
121
  function buildUrlFromParams(pattern, params) {
122
+ if (params === void 0 || params === null) throw new Error(`[vinext] buildUrlFromParams: params is ${params === null ? "null" : "undefined"} for pattern "${pattern}". Check that getStaticPaths / generateStaticParams returned an object with a "params" key, or pass a string path (see https://nextjs.org/docs/pages/api-reference/functions/get-static-paths).`);
114
123
  const parts = pattern.split("/").filter(Boolean);
115
124
  const result = [];
116
125
  for (const part of parts) if (part.endsWith("+") || part.endsWith("*")) {
@@ -300,14 +309,34 @@ async function prerenderPages({ routes, apiRoutes, pagesDir, outDir, config, mod
300
309
  continue;
301
310
  }
302
311
  const paths = pathsResult?.paths ?? [];
303
- for (const { params } of paths) {
304
- const urlPath = buildUrlFromParams(route.pattern, params);
305
- pagesToRender.push({
306
- route,
307
- urlPath,
308
- params,
309
- revalidate
312
+ let entryError = null;
313
+ for (const item of paths) {
314
+ const normalized = normalizeStaticPathsEntry(item, route.pattern);
315
+ if ("error" in normalized) {
316
+ entryError = normalized.error;
317
+ break;
318
+ }
319
+ const { params } = normalized;
320
+ try {
321
+ const urlPath = buildUrlFromParams(route.pattern, params);
322
+ pagesToRender.push({
323
+ route,
324
+ urlPath,
325
+ params,
326
+ revalidate
327
+ });
328
+ } catch (e) {
329
+ entryError = e.message;
330
+ break;
331
+ }
332
+ }
333
+ if (entryError) {
334
+ results.push({
335
+ route: route.pattern,
336
+ status: "error",
337
+ error: entryError
310
338
  });
339
+ continue;
311
340
  }
312
341
  } else pagesToRender.push({
313
342
  route,
@@ -565,6 +594,7 @@ async function prerenderApp({ routes, outDir, config, mode, rscBundlePath, ...op
565
594
  continue;
566
595
  }
567
596
  for (const params of paramSets) {
597
+ if (params === null || params === void 0) throw new Error(`generateStaticParams() for ${route.pattern} returned an entry with no params object.`);
568
598
  const urlPath = buildUrlFromParams(route.pattern, params);
569
599
  urlsToRender.push({
570
600
  urlPath,
@@ -662,7 +692,7 @@ async function prerenderApp({ routes, outDir, config, mode, rscBundlePath, ...op
662
692
  await rscRes.body?.cancel();
663
693
  throw new Error(`[vinext] prerenderApp: RSC fallback returned ${rscRes.status} for ${urlPath}`);
664
694
  }
665
- rscData = await rscRes.text();
695
+ rscData = new Uint8Array(await rscRes.arrayBuffer());
666
696
  }
667
697
  const outputFiles = [];
668
698
  const htmlOutputPath = getOutputPath(urlPath, config.trailingSlash);
@@ -673,7 +703,7 @@ async function prerenderApp({ routes, outDir, config, mode, rscBundlePath, ...op
673
703
  const rscOutputPath = getRscOutputPath(urlPath);
674
704
  const rscFullPath = path.join(outDir, rscOutputPath);
675
705
  fs.mkdirSync(path.dirname(rscFullPath), { recursive: true });
676
- fs.writeFileSync(rscFullPath, rscData, "utf-8");
706
+ fs.writeFileSync(rscFullPath, rscData);
677
707
  outputFiles.push(rscOutputPath);
678
708
  const renderedCacheControl = resolveRenderedCacheControl(htmlRender.requestCacheLife ?? {}, htmlCacheControl, config.expireTime);
679
709
  const renderedRevalidate = typeof revalidate === "number" ? renderedCacheControl.revalidate === void 0 ? revalidate : Math.min(revalidate, renderedCacheControl.revalidate) : renderedCacheControl.revalidate ?? revalidate;