vinext 0.0.49 → 0.0.50

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 (390) hide show
  1. package/dist/build/client-build-config.js.map +1 -1
  2. package/dist/build/google-fonts/build-url.js.map +1 -1
  3. package/dist/build/google-fonts/get-axes.js.map +1 -1
  4. package/dist/build/google-fonts/sort-variants.js.map +1 -1
  5. package/dist/build/google-fonts/validate.js.map +1 -1
  6. package/dist/build/layout-classification.js.map +1 -1
  7. package/dist/build/nitro-route-rules.js.map +1 -1
  8. package/dist/build/precompress.js.map +1 -1
  9. package/dist/build/prerender.d.ts +17 -1
  10. package/dist/build/prerender.js +77 -16
  11. package/dist/build/prerender.js.map +1 -1
  12. package/dist/build/report.js.map +1 -1
  13. package/dist/build/route-classification-injector.js.map +1 -1
  14. package/dist/build/route-classification-manifest.js.map +1 -1
  15. package/dist/build/run-prerender.js.map +1 -1
  16. package/dist/build/server-manifest.js.map +1 -1
  17. package/dist/build/ssr-manifest.js.map +1 -1
  18. package/dist/build/standalone.js.map +1 -1
  19. package/dist/build/static-export.js.map +1 -1
  20. package/dist/check.js +1 -1
  21. package/dist/check.js.map +1 -1
  22. package/dist/cli-args.js.map +1 -1
  23. package/dist/cli.js +8 -4
  24. package/dist/cli.js.map +1 -1
  25. package/dist/client/instrumentation-client-state.js.map +1 -1
  26. package/dist/client/validate-module-path.js.map +1 -1
  27. package/dist/client/vinext-next-data.d.ts +5 -1
  28. package/dist/client/window-next.d.ts +149 -0
  29. package/dist/client/window-next.js +48 -0
  30. package/dist/client/window-next.js.map +1 -0
  31. package/dist/cloudflare/kv-cache-handler.js.map +1 -1
  32. package/dist/cloudflare/tpr.js +2 -1
  33. package/dist/cloudflare/tpr.js.map +1 -1
  34. package/dist/config/config-matchers.d.ts +3 -1
  35. package/dist/config/config-matchers.js +5 -4
  36. package/dist/config/config-matchers.js.map +1 -1
  37. package/dist/config/dotenv.js.map +1 -1
  38. package/dist/config/next-config.d.ts +6 -3
  39. package/dist/config/next-config.js +13 -2
  40. package/dist/config/next-config.js.map +1 -1
  41. package/dist/deploy.js +13 -5
  42. package/dist/deploy.js.map +1 -1
  43. package/dist/entries/app-browser-entry.d.ts +3 -1
  44. package/dist/entries/app-browser-entry.js +11 -2
  45. package/dist/entries/app-browser-entry.js.map +1 -1
  46. package/dist/entries/app-rsc-entry.js +11 -0
  47. package/dist/entries/app-rsc-entry.js.map +1 -1
  48. package/dist/entries/app-rsc-manifest.js +4 -0
  49. package/dist/entries/app-rsc-manifest.js.map +1 -1
  50. package/dist/entries/app-ssr-entry.js.map +1 -1
  51. package/dist/entries/pages-client-entry.js.map +1 -1
  52. package/dist/entries/pages-entry-helpers.js.map +1 -1
  53. package/dist/entries/pages-server-entry.js +15 -0
  54. package/dist/entries/pages-server-entry.js.map +1 -1
  55. package/dist/entries/runtime-entry-module.js.map +1 -1
  56. package/dist/index.js +76 -18
  57. package/dist/index.js.map +1 -1
  58. package/dist/init.js.map +1 -1
  59. package/dist/plugins/async-hooks-stub.js.map +1 -1
  60. package/dist/plugins/client-reference-dedup.js.map +1 -1
  61. package/dist/plugins/fonts.js.map +1 -1
  62. package/dist/plugins/instrumentation-client.js.map +1 -1
  63. package/dist/plugins/og-assets.js.map +1 -1
  64. package/dist/plugins/optimize-imports.js.map +1 -1
  65. package/dist/plugins/postcss.js.map +1 -1
  66. package/dist/plugins/rsc-client-reference-loaders.d.ts +7 -0
  67. package/dist/plugins/rsc-client-reference-loaders.js +48 -0
  68. package/dist/plugins/rsc-client-reference-loaders.js.map +1 -0
  69. package/dist/plugins/rsc-client-shim-excludes.js.map +1 -1
  70. package/dist/plugins/server-externals-manifest.js.map +1 -1
  71. package/dist/plugins/strip-server-exports.js.map +1 -1
  72. package/dist/routing/app-route-graph.d.ts +48 -5
  73. package/dist/routing/app-route-graph.js +159 -15
  74. package/dist/routing/app-route-graph.js.map +1 -1
  75. package/dist/routing/app-router.js.map +1 -1
  76. package/dist/routing/file-matcher.js.map +1 -1
  77. package/dist/routing/pages-router.js.map +1 -1
  78. package/dist/routing/route-matching.js.map +1 -1
  79. package/dist/routing/route-pattern.js.map +1 -1
  80. package/dist/routing/route-trie.js.map +1 -1
  81. package/dist/routing/route-validation.js.map +1 -1
  82. package/dist/routing/utils.js.map +1 -1
  83. package/dist/server/api-handler.js.map +1 -1
  84. package/dist/server/app-browser-action-result.d.ts +19 -0
  85. package/dist/server/app-browser-action-result.js +18 -0
  86. package/dist/server/app-browser-action-result.js.map +1 -0
  87. package/dist/server/app-browser-entry.js +91 -48
  88. package/dist/server/app-browser-entry.js.map +1 -1
  89. package/dist/server/app-browser-error.js.map +1 -1
  90. package/dist/server/app-browser-hydration.d.ts +19 -0
  91. package/dist/server/app-browser-hydration.js +22 -0
  92. package/dist/server/app-browser-hydration.js.map +1 -0
  93. package/dist/server/app-browser-navigation-controller.d.ts +6 -3
  94. package/dist/server/app-browser-navigation-controller.js +67 -19
  95. package/dist/server/app-browser-navigation-controller.js.map +1 -1
  96. package/dist/server/app-browser-state.d.ts +17 -17
  97. package/dist/server/app-browser-state.js +122 -36
  98. package/dist/server/app-browser-state.js.map +1 -1
  99. package/dist/server/app-browser-stream.d.ts +4 -0
  100. package/dist/server/app-browser-stream.js +24 -2
  101. package/dist/server/app-browser-stream.js.map +1 -1
  102. package/dist/server/app-browser-visible-commit.d.ts +6 -1
  103. package/dist/server/app-browser-visible-commit.js +34 -19
  104. package/dist/server/app-browser-visible-commit.js.map +1 -1
  105. package/dist/server/app-client-reference-preloader.js.map +1 -1
  106. package/dist/server/app-elements-wire.d.ts +6 -1
  107. package/dist/server/app-elements-wire.js +17 -1
  108. package/dist/server/app-elements-wire.js.map +1 -1
  109. package/dist/server/app-elements.d.ts +2 -2
  110. package/dist/server/app-elements.js +2 -2
  111. package/dist/server/app-elements.js.map +1 -1
  112. package/dist/server/app-fallback-renderer.js.map +1 -1
  113. package/dist/server/app-hook-warning-suppression.js.map +1 -1
  114. package/dist/server/app-middleware.d.ts +1 -1
  115. package/dist/server/app-middleware.js +4 -9
  116. package/dist/server/app-middleware.js.map +1 -1
  117. package/dist/server/app-mounted-slots-header.js.map +1 -1
  118. package/dist/server/app-page-boundary-render.d.ts +1 -0
  119. package/dist/server/app-page-boundary-render.js +14 -13
  120. package/dist/server/app-page-boundary-render.js.map +1 -1
  121. package/dist/server/app-page-boundary.d.ts +1 -0
  122. package/dist/server/app-page-boundary.js +7 -5
  123. package/dist/server/app-page-boundary.js.map +1 -1
  124. package/dist/server/app-page-cache.d.ts +10 -3
  125. package/dist/server/app-page-cache.js +42 -23
  126. package/dist/server/app-page-cache.js.map +1 -1
  127. package/dist/server/app-page-dispatch.d.ts +6 -1
  128. package/dist/server/app-page-dispatch.js +21 -7
  129. package/dist/server/app-page-dispatch.js.map +1 -1
  130. package/dist/server/app-page-element-builder.d.ts +3 -1
  131. package/dist/server/app-page-element-builder.js +6 -2
  132. package/dist/server/app-page-element-builder.js.map +1 -1
  133. package/dist/server/app-page-execution.js.map +1 -1
  134. package/dist/server/app-page-head.js +4 -0
  135. package/dist/server/app-page-head.js.map +1 -1
  136. package/dist/server/app-page-method.js.map +1 -1
  137. package/dist/server/app-page-params.js.map +1 -1
  138. package/dist/server/app-page-probe.js.map +1 -1
  139. package/dist/server/app-page-render.d.ts +7 -1
  140. package/dist/server/app-page-render.js +11 -4
  141. package/dist/server/app-page-render.js.map +1 -1
  142. package/dist/server/app-page-request.js +2 -1
  143. package/dist/server/app-page-request.js.map +1 -1
  144. package/dist/server/app-page-response.d.ts +2 -0
  145. package/dist/server/app-page-response.js +15 -5
  146. package/dist/server/app-page-response.js.map +1 -1
  147. package/dist/server/app-page-route-wiring.d.ts +6 -2
  148. package/dist/server/app-page-route-wiring.js +50 -49
  149. package/dist/server/app-page-route-wiring.js.map +1 -1
  150. package/dist/server/app-page-segment-state.d.ts +10 -0
  151. package/dist/server/app-page-segment-state.js +87 -0
  152. package/dist/server/app-page-segment-state.js.map +1 -0
  153. package/dist/server/app-page-stream.d.ts +7 -2
  154. package/dist/server/app-page-stream.js +3 -1
  155. package/dist/server/app-page-stream.js.map +1 -1
  156. package/dist/server/app-post-middleware-context.js.map +1 -1
  157. package/dist/server/app-prerender-endpoints.js.map +1 -1
  158. package/dist/server/app-prerender-static-params.js.map +1 -1
  159. package/dist/server/app-render-dependency.js.map +1 -1
  160. package/dist/server/app-request-context.js.map +1 -1
  161. package/dist/server/app-route-handler-cache.js.map +1 -1
  162. package/dist/server/app-route-handler-dispatch.js +3 -1
  163. package/dist/server/app-route-handler-dispatch.js.map +1 -1
  164. package/dist/server/app-route-handler-execution.js.map +1 -1
  165. package/dist/server/app-route-handler-policy.js +1 -0
  166. package/dist/server/app-route-handler-policy.js.map +1 -1
  167. package/dist/server/app-route-handler-response.js +4 -3
  168. package/dist/server/app-route-handler-response.js.map +1 -1
  169. package/dist/server/app-route-handler-runtime.js.map +1 -1
  170. package/dist/server/app-router-entry.js +6 -2
  171. package/dist/server/app-router-entry.js.map +1 -1
  172. package/dist/server/app-rsc-cache-busting.d.ts +5 -2
  173. package/dist/server/app-rsc-cache-busting.js +40 -19
  174. package/dist/server/app-rsc-cache-busting.js.map +1 -1
  175. package/dist/server/app-rsc-error-handler.js.map +1 -1
  176. package/dist/server/app-rsc-errors.js.map +1 -1
  177. package/dist/server/app-rsc-handler.d.ts +10 -1
  178. package/dist/server/app-rsc-handler.js +51 -17
  179. package/dist/server/app-rsc-handler.js.map +1 -1
  180. package/dist/server/app-rsc-render-mode.d.ts +11 -0
  181. package/dist/server/app-rsc-render-mode.js +21 -0
  182. package/dist/server/app-rsc-render-mode.js.map +1 -0
  183. package/dist/server/app-rsc-request-normalization.d.ts +4 -1
  184. package/dist/server/app-rsc-request-normalization.js +7 -2
  185. package/dist/server/app-rsc-request-normalization.js.map +1 -1
  186. package/dist/server/app-rsc-response-finalizer.d.ts +2 -1
  187. package/dist/server/app-rsc-response-finalizer.js +6 -1
  188. package/dist/server/app-rsc-response-finalizer.js.map +1 -1
  189. package/dist/server/app-rsc-route-matching.js.map +1 -1
  190. package/dist/server/app-segment-config.js.map +1 -1
  191. package/dist/server/app-server-action-execution.d.ts +16 -2
  192. package/dist/server/app-server-action-execution.js +79 -23
  193. package/dist/server/app-server-action-execution.js.map +1 -1
  194. package/dist/server/app-ssr-entry.d.ts +6 -0
  195. package/dist/server/app-ssr-entry.js +10 -4
  196. package/dist/server/app-ssr-entry.js.map +1 -1
  197. package/dist/server/app-ssr-stream.js.map +1 -1
  198. package/dist/server/app-static-generation.js.map +1 -1
  199. package/dist/server/artifact-compatibility.js.map +1 -1
  200. package/dist/server/cache-control.js +1 -0
  201. package/dist/server/cache-control.js.map +1 -1
  202. package/dist/server/cache-proof.js.map +1 -1
  203. package/dist/server/csp.js.map +1 -1
  204. package/dist/server/dev-error-overlay-store.js.map +1 -1
  205. package/dist/server/dev-error-overlay.js +5 -0
  206. package/dist/server/dev-error-overlay.js.map +1 -1
  207. package/dist/server/dev-module-runner.js.map +1 -1
  208. package/dist/server/dev-origin-check.js.map +1 -1
  209. package/dist/server/dev-route-files.js.map +1 -1
  210. package/dist/server/dev-server.js +8 -5
  211. package/dist/server/dev-server.js.map +1 -1
  212. package/dist/server/file-based-metadata.js.map +1 -1
  213. package/dist/server/headers.d.ts +79 -0
  214. package/dist/server/headers.js +101 -0
  215. package/dist/server/headers.js.map +1 -0
  216. package/dist/server/html.js.map +1 -1
  217. package/dist/server/http-error-responses.js.map +1 -1
  218. package/dist/server/image-optimization.d.ts +11 -1
  219. package/dist/server/image-optimization.js.map +1 -1
  220. package/dist/server/implicit-tags.js +2 -1
  221. package/dist/server/implicit-tags.js.map +1 -1
  222. package/dist/server/instrumentation-runtime.js.map +1 -1
  223. package/dist/server/instrumentation.js.map +1 -1
  224. package/dist/server/isr-cache.d.ts +10 -1
  225. package/dist/server/isr-cache.js +12 -3
  226. package/dist/server/isr-cache.js.map +1 -1
  227. package/dist/server/metadata-route-build-data.js.map +1 -1
  228. package/dist/server/metadata-route-response.js.map +1 -1
  229. package/dist/server/metadata-routes.js.map +1 -1
  230. package/dist/server/middleware-matcher.js.map +1 -1
  231. package/dist/server/middleware-request-headers.d.ts +4 -1
  232. package/dist/server/middleware-request-headers.js +15 -8
  233. package/dist/server/middleware-request-headers.js.map +1 -1
  234. package/dist/server/middleware-response-headers.d.ts +2 -1
  235. package/dist/server/middleware-response-headers.js +1 -1
  236. package/dist/server/middleware-response-headers.js.map +1 -1
  237. package/dist/server/middleware-runtime.d.ts +1 -0
  238. package/dist/server/middleware-runtime.js +6 -3
  239. package/dist/server/middleware-runtime.js.map +1 -1
  240. package/dist/server/middleware.js.map +1 -1
  241. package/dist/server/navigation-planner.d.ts +119 -0
  242. package/dist/server/navigation-planner.js +171 -0
  243. package/dist/server/navigation-planner.js.map +1 -0
  244. package/dist/server/navigation-trace.d.ts +12 -2
  245. package/dist/server/navigation-trace.js +13 -1
  246. package/dist/server/navigation-trace.js.map +1 -1
  247. package/dist/server/next-error-digest.d.ts +3 -2
  248. package/dist/server/next-error-digest.js +4 -2
  249. package/dist/server/next-error-digest.js.map +1 -1
  250. package/dist/server/normalize-path.js.map +1 -1
  251. package/dist/server/pages-api-route.js.map +1 -1
  252. package/dist/server/pages-i18n.js.map +1 -1
  253. package/dist/server/pages-media-type.js.map +1 -1
  254. package/dist/server/pages-node-compat.js.map +1 -1
  255. package/dist/server/pages-page-data.js +5 -2
  256. package/dist/server/pages-page-data.js.map +1 -1
  257. package/dist/server/pages-page-response.js +3 -2
  258. package/dist/server/pages-page-response.js.map +1 -1
  259. package/dist/server/prerender-work-unit-setup.js +1 -1
  260. package/dist/server/prerender-work-unit-setup.js.map +1 -1
  261. package/dist/server/prod-server.js +35 -13
  262. package/dist/server/prod-server.js.map +1 -1
  263. package/dist/server/request-log.js.map +1 -1
  264. package/dist/server/request-pipeline.d.ts +1 -13
  265. package/dist/server/request-pipeline.js +3 -25
  266. package/dist/server/request-pipeline.js.map +1 -1
  267. package/dist/server/rsc-stream-hints.js.map +1 -1
  268. package/dist/server/seed-cache.js.map +1 -1
  269. package/dist/server/server-action-not-found.js +3 -3
  270. package/dist/server/server-action-not-found.js.map +1 -1
  271. package/dist/server/socket-error-backstop.js.map +1 -1
  272. package/dist/server/static-file-cache.js.map +1 -1
  273. package/dist/server/worker-utils.d.ts +0 -7
  274. package/dist/server/worker-utils.js +3 -2
  275. package/dist/server/worker-utils.js.map +1 -1
  276. package/dist/shims/amp.js.map +1 -1
  277. package/dist/shims/app.d.ts +37 -4
  278. package/dist/shims/app.js +50 -1
  279. package/dist/shims/app.js.map +1 -0
  280. package/dist/shims/cache-for-request.js.map +1 -1
  281. package/dist/shims/cache-runtime.js +20 -8
  282. package/dist/shims/cache-runtime.js.map +1 -1
  283. package/dist/shims/cache.d.ts +15 -3
  284. package/dist/shims/cache.js +99 -15
  285. package/dist/shims/cache.js.map +1 -1
  286. package/dist/shims/client-hook-error.js.map +1 -1
  287. package/dist/shims/compat-router.js.map +1 -1
  288. package/dist/shims/config.js.map +1 -1
  289. package/dist/shims/constants.js.map +1 -1
  290. package/dist/shims/document.js.map +1 -1
  291. package/dist/shims/dynamic.d.ts +18 -10
  292. package/dist/shims/dynamic.js +107 -51
  293. package/dist/shims/dynamic.js.map +1 -1
  294. package/dist/shims/error-boundary.d.ts +35 -6
  295. package/dist/shims/error-boundary.js +118 -33
  296. package/dist/shims/error-boundary.js.map +1 -1
  297. package/dist/shims/error.js.map +1 -1
  298. package/dist/shims/fetch-cache.d.ts +22 -1
  299. package/dist/shims/fetch-cache.js +124 -13
  300. package/dist/shims/fetch-cache.js.map +1 -1
  301. package/dist/shims/font-google-base.js.map +1 -1
  302. package/dist/shims/font-local.js.map +1 -1
  303. package/dist/shims/form.js +3 -1
  304. package/dist/shims/form.js.map +1 -1
  305. package/dist/shims/head-state.js.map +1 -1
  306. package/dist/shims/head.d.ts +3 -1
  307. package/dist/shims/head.js +28 -16
  308. package/dist/shims/head.js.map +1 -1
  309. package/dist/shims/headers.d.ts +4 -2
  310. package/dist/shims/headers.js +24 -7
  311. package/dist/shims/headers.js.map +1 -1
  312. package/dist/shims/i18n-context.js.map +1 -1
  313. package/dist/shims/i18n-state.js.map +1 -1
  314. package/dist/shims/image-config.d.ts +14 -1
  315. package/dist/shims/image-config.js +24 -1
  316. package/dist/shims/image-config.js.map +1 -1
  317. package/dist/shims/image.js +15 -2
  318. package/dist/shims/image.js.map +1 -1
  319. package/dist/shims/internal/als-registry.js.map +1 -1
  320. package/dist/shims/internal/app-router-context.d.ts +1 -0
  321. package/dist/shims/internal/app-router-context.js.map +1 -1
  322. package/dist/shims/internal/cookie-serialize.js.map +1 -1
  323. package/dist/shims/internal/make-hanging-promise.d.ts +1 -1
  324. package/dist/shims/internal/make-hanging-promise.js +1 -1
  325. package/dist/shims/internal/make-hanging-promise.js.map +1 -1
  326. package/dist/shims/internal/parse-cookie-header.js.map +1 -1
  327. package/dist/shims/internal/utils.js.map +1 -1
  328. package/dist/shims/internal/work-unit-async-storage.js +2 -2
  329. package/dist/shims/internal/work-unit-async-storage.js.map +1 -1
  330. package/dist/shims/layout-segment-context.js.map +1 -1
  331. package/dist/shims/legacy-image.js.map +1 -1
  332. package/dist/shims/link-prefetch.d.ts +34 -0
  333. package/dist/shims/link-prefetch.js +40 -0
  334. package/dist/shims/link-prefetch.js.map +1 -0
  335. package/dist/shims/link.d.ts +27 -4
  336. package/dist/shims/link.js +91 -27
  337. package/dist/shims/link.js.map +1 -1
  338. package/dist/shims/metadata.js.map +1 -1
  339. package/dist/shims/navigation-state.js.map +1 -1
  340. package/dist/shims/navigation.d.ts +22 -1
  341. package/dist/shims/navigation.js +30 -15
  342. package/dist/shims/navigation.js.map +1 -1
  343. package/dist/shims/navigation.react-server.js.map +1 -1
  344. package/dist/shims/offline.js.map +1 -1
  345. package/dist/shims/readonly-url-search-params.js.map +1 -1
  346. package/dist/shims/request-context.js.map +1 -1
  347. package/dist/shims/root-params.js.map +1 -1
  348. package/dist/shims/router-state.js.map +1 -1
  349. package/dist/shims/router.d.ts +38 -2
  350. package/dist/shims/router.js +45 -17
  351. package/dist/shims/router.js.map +1 -1
  352. package/dist/shims/script-nonce-context.js.map +1 -1
  353. package/dist/shims/script.js.map +1 -1
  354. package/dist/shims/server.js +10 -14
  355. package/dist/shims/server.js.map +1 -1
  356. package/dist/shims/slot.d.ts +6 -1
  357. package/dist/shims/slot.js +20 -7
  358. package/dist/shims/slot.js.map +1 -1
  359. package/dist/shims/thenable-params.js.map +1 -1
  360. package/dist/shims/unified-request-context.js +3 -0
  361. package/dist/shims/unified-request-context.js.map +1 -1
  362. package/dist/shims/url-safety.js.map +1 -1
  363. package/dist/shims/url-utils.d.ts +2 -1
  364. package/dist/shims/url-utils.js +10 -1
  365. package/dist/shims/url-utils.js.map +1 -1
  366. package/dist/shims/use-merged-ref.js.map +1 -1
  367. package/dist/shims/web-vitals.d.ts +4 -21
  368. package/dist/shims/web-vitals.js +19 -6
  369. package/dist/shims/web-vitals.js.map +1 -1
  370. package/dist/utils/base-path.js.map +1 -1
  371. package/dist/utils/cache-control-metadata.js.map +1 -1
  372. package/dist/utils/domain-locale.js.map +1 -1
  373. package/dist/utils/encode-cache-tag.d.ts +31 -0
  374. package/dist/utils/encode-cache-tag.js +38 -0
  375. package/dist/utils/encode-cache-tag.js.map +1 -0
  376. package/dist/utils/error-cause.js.map +1 -1
  377. package/dist/utils/hash.js.map +1 -1
  378. package/dist/utils/lazy-chunks.js.map +1 -1
  379. package/dist/utils/manifest-paths.js.map +1 -1
  380. package/dist/utils/mdx-scan.js.map +1 -1
  381. package/dist/utils/navigation-signal.d.ts +6 -0
  382. package/dist/utils/navigation-signal.js +14 -0
  383. package/dist/utils/navigation-signal.js.map +1 -0
  384. package/dist/utils/project.js.map +1 -1
  385. package/dist/utils/public-routes.js.map +1 -1
  386. package/dist/utils/query.js.map +1 -1
  387. package/dist/utils/safe-json-file.js.map +1 -1
  388. package/dist/utils/text-stream.js.map +1 -1
  389. package/dist/utils/vinext-root.js.map +1 -1
  390. package/package.json +6 -4
@@ -1 +1 @@
1
- {"version":3,"file":"app-ssr-entry.js","names":["createReactElement"],"sources":["../../src/server/app-ssr-entry.ts"],"sourcesContent":["/// <reference types=\"@vitejs/plugin-rsc/types\" />\n\nimport type { ReactNode } from \"react\";\nimport { Fragment, createElement as createReactElement, use } from \"react\";\nimport { createFromReadableStream } from \"@vitejs/plugin-rsc/ssr\";\nimport { renderToReadableStream, renderToStaticMarkup } from \"react-dom/server.edge\";\nimport clientReferences from \"virtual:vite-rsc/client-references\";\nimport type { NavigationContext } from \"vinext/shims/navigation\";\nimport {\n ServerInsertedHTMLContext,\n clearServerInsertedHTML,\n renderServerInsertedHTML,\n setNavigationContext,\n useServerInsertedHTML,\n} from \"vinext/shims/navigation\";\nimport { runWithNavigationContext } from \"vinext/shims/navigation-state\";\nimport { isOpenRedirectShaped } from \"./request-pipeline.js\";\nimport { notFoundResponse } from \"./http-error-responses.js\";\nimport { withScriptNonce } from \"vinext/shims/script-nonce-context\";\nimport {\n createInlineScriptTag,\n createNonceAttribute,\n escapeHtmlAttr,\n safeJsonStringify,\n} from \"./html.js\";\nimport { createRscEmbedTransform, createTickBufferedTransform } from \"./app-ssr-stream.js\";\nimport { deferUntilStreamConsumed } from \"./app-page-stream.js\";\nimport { AppElementsWire, type AppWireElements } from \"./app-elements.js\";\nimport { ElementsContext, Slot } from \"vinext/shims/slot\";\nimport { createClientReferencePreloader } from \"./app-client-reference-preloader.js\";\n\nexport type FontPreload = {\n href: string;\n type: string;\n};\n\nexport type FontData = {\n links?: string[];\n styles?: string[];\n preloads?: FontPreload[];\n};\n\nconst clientReferencePreloader = createClientReferencePreloader({\n getReferences() {\n return clientReferences;\n },\n getClientRequire() {\n return globalThis.__vite_rsc_client_require__;\n },\n onPreloadError(id, error) {\n if (process.env.NODE_ENV !== \"production\") {\n console.warn(\"[vinext] failed to preload client ref:\", id, error);\n }\n },\n});\n\nfunction ssrErrorDigest(input: string): string {\n let hash = 5381;\n for (let i = input.length - 1; i >= 0; i--) {\n hash = (hash * 33) ^ input.charCodeAt(i);\n }\n return (hash >>> 0).toString();\n}\n\nfunction getErrorMessage(error: unknown): string {\n if (error instanceof Error) return error.message;\n if (typeof error === \"string\") return error;\n return Object.prototype.toString.call(error);\n}\n\nfunction renderInsertedHtml(insertedElements: readonly unknown[]): string {\n let insertedHTML = \"\";\n\n for (const element of insertedElements) {\n try {\n insertedHTML += renderToStaticMarkup(\n createReactElement(Fragment, null, element as ReactNode),\n );\n } catch {\n // Ignore individual callback failures so the rest of the page can render.\n }\n }\n\n return insertedHTML;\n}\n\nfunction renderFontHtml(fontData?: FontData, nonce?: string): string {\n if (!fontData) return \"\";\n\n let fontHTML = \"\";\n const nonceAttr = createNonceAttribute(nonce);\n\n for (const url of fontData.links ?? []) {\n fontHTML += `<link rel=\"stylesheet\"${nonceAttr} href=\"${escapeHtmlAttr(url)}\" />\\n`;\n }\n\n for (const preload of fontData.preloads ?? []) {\n fontHTML += `<link rel=\"preload\"${nonceAttr} href=\"${escapeHtmlAttr(preload.href)}\" as=\"font\" type=\"${escapeHtmlAttr(preload.type)}\" crossorigin />\\n`;\n }\n\n if (fontData.styles && fontData.styles.length > 0) {\n fontHTML += `<style data-vinext-fonts${nonceAttr}>${fontData.styles.join(\"\\n\")}</style>\\n`;\n }\n\n return fontHTML;\n}\n\nfunction extractModulePreloadHtml(bootstrapScriptContent?: string, nonce?: string): string {\n if (!bootstrapScriptContent) return \"\";\n\n const match = bootstrapScriptContent.match(/import\\(\"([^\"]+)\"\\)/);\n if (!match?.[1]) return \"\";\n\n return `<link rel=\"modulepreload\"${createNonceAttribute(nonce)} href=\"${escapeHtmlAttr(match[1])}\" />\\n`;\n}\n\nfunction buildHeadInjectionHtml(\n navContext: NavigationContext | null,\n bootstrapScriptContent: string | undefined,\n insertedHTML: string,\n fontHTML: string,\n scriptNonce?: string,\n): string {\n const paramsScript = createInlineScriptTag(\n \"self.__VINEXT_RSC_PARAMS__=\" + safeJsonStringify(navContext?.params ?? {}),\n scriptNonce,\n );\n const navPayload = {\n pathname: navContext?.pathname ?? \"/\",\n searchParams: navContext?.searchParams ? [...navContext.searchParams.entries()] : [],\n };\n const navScript = createInlineScriptTag(\n \"self.__VINEXT_RSC_NAV__=\" + safeJsonStringify(navPayload),\n scriptNonce,\n );\n\n return (\n paramsScript +\n navScript +\n extractModulePreloadHtml(bootstrapScriptContent, scriptNonce) +\n insertedHTML +\n fontHTML\n );\n}\n\nexport async function handleSsr(\n rscStream: ReadableStream<Uint8Array>,\n navContext: NavigationContext | null,\n fontData?: FontData,\n options?: {\n scriptNonce?: string;\n /** Pre-split side stream for embed+capture fusion. When provided,\n * rscStream is fed directly to createFromReadableStream (no internal tee).\n * The embed transform accumulates raw bytes. */\n sideStream?: ReadableStream<Uint8Array>;\n /** Out-parameter: filled with accumulated raw RSC bytes when sideStream is consumed. */\n capturedRscDataRef?: { value: Promise<ArrayBuffer> | null };\n },\n): Promise<ReadableStream<Uint8Array>> {\n return runWithNavigationContext(async () => {\n await clientReferencePreloader.preload();\n\n if (navContext) {\n setNavigationContext(navContext);\n }\n\n clearServerInsertedHTML();\n\n const cleanup = (): void => {\n setNavigationContext(null);\n clearServerInsertedHTML();\n };\n\n try {\n // Fused tee path (#981): caller pre-split the stream. No internal tee needed.\n // sideStream carries both the embed transform and raw byte accumulation.\n // rscStream is used directly for createFromReadableStream (SSR).\n let ssrStream: ReadableStream<Uint8Array>;\n let rscEmbed;\n\n if (options?.sideStream) {\n ssrStream = rscStream;\n rscEmbed = createRscEmbedTransform(options.sideStream, options?.scriptNonce);\n if (options.capturedRscDataRef) {\n options.capturedRscDataRef.value = rscEmbed.getRawBuffer();\n }\n } else {\n const [s1, s2] = rscStream.tee();\n ssrStream = s1;\n rscEmbed = createRscEmbedTransform(s2, options?.scriptNonce);\n }\n\n let flightRoot: PromiseLike<AppWireElements> | null = null;\n\n function VinextFlightRoot(): ReactNode {\n if (!flightRoot) {\n flightRoot = createFromReadableStream<AppWireElements>(ssrStream);\n }\n const wireElements = use(flightRoot);\n const elements = AppElementsWire.decode(wireElements);\n const metadata = AppElementsWire.readMetadata(elements);\n return createReactElement(\n ElementsContext.Provider,\n { value: elements },\n createReactElement(Slot, { id: metadata.routeId }),\n );\n }\n\n const root = createReactElement(VinextFlightRoot);\n const ssrTree = ServerInsertedHTMLContext\n ? createReactElement(\n ServerInsertedHTMLContext.Provider,\n { value: useServerInsertedHTML },\n root,\n )\n : root;\n const ssrRoot = withScriptNonce(ssrTree, options?.scriptNonce);\n\n const bootstrapScriptContent = await import.meta.viteRsc.loadBootstrapScriptContent(\"index\");\n\n const htmlStream = await renderToReadableStream(ssrRoot, {\n bootstrapScriptContent,\n nonce: options?.scriptNonce,\n onError(error) {\n if (error && typeof error === \"object\" && \"digest\" in error) {\n return String(error.digest);\n }\n\n if (process.env.NODE_ENV === \"production\" && error) {\n const message = getErrorMessage(error);\n const stack = error instanceof Error ? (error.stack ?? \"\") : \"\";\n return ssrErrorDigest(message + stack);\n }\n\n return undefined;\n },\n });\n\n const fontHTML = renderFontHtml(fontData, options?.scriptNonce);\n let didInjectHeadHTML = false;\n const getInsertedHTML = (): string => {\n const insertedHTML = renderInsertedHtml(renderServerInsertedHTML());\n if (didInjectHeadHTML) return insertedHTML;\n\n didInjectHeadHTML = true;\n return buildHeadInjectionHtml(\n navContext,\n bootstrapScriptContent,\n insertedHTML,\n fontHTML,\n options?.scriptNonce,\n );\n };\n\n return deferUntilStreamConsumed(\n htmlStream.pipeThrough(createTickBufferedTransform(rscEmbed, getInsertedHTML)),\n cleanup,\n );\n } catch (error) {\n cleanup();\n throw error;\n }\n }) as Promise<ReadableStream<Uint8Array>>;\n}\n\nexport default {\n async fetch(request: Request): Promise<Response> {\n const url = new URL(request.url);\n // Block protocol-relative URL open redirects (including percent-encoded\n // variants like /%5Cevil.com/). See request-pipeline.ts for details.\n if (isOpenRedirectShaped(url.pathname)) {\n return notFoundResponse();\n }\n\n const rscModule = await import.meta.viteRsc.loadModule<{\n default(request: Request): Promise<Response | string | null | undefined>;\n }>(\"rsc\", \"index\");\n const result = await rscModule.default(request);\n\n if (result instanceof Response) {\n return result;\n }\n\n if (result == null) {\n return notFoundResponse();\n }\n\n return new Response(String(result), { status: 200 });\n },\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"app-ssr-entry.js","names":["createReactElement"],"sources":["../../src/server/app-ssr-entry.ts"],"sourcesContent":["/// <reference types=\"@vitejs/plugin-rsc/types\" />\n\nimport type { ReactNode } from \"react\";\nimport type { ReactFormState } from \"react-dom/client\";\nimport { Fragment, createElement as createReactElement, use } from \"react\";\nimport { createFromReadableStream } from \"@vitejs/plugin-rsc/ssr\";\nimport { renderToReadableStream, renderToStaticMarkup } from \"react-dom/server.edge\";\nimport clientReferences from \"virtual:vite-rsc/client-references\";\nimport type { NavigationContext } from \"vinext/shims/navigation\";\nimport {\n ServerInsertedHTMLContext,\n clearServerInsertedHTML,\n renderServerInsertedHTML,\n setNavigationContext,\n useServerInsertedHTML,\n} from \"vinext/shims/navigation\";\nimport { runWithNavigationContext } from \"vinext/shims/navigation-state\";\nimport { isOpenRedirectShaped } from \"./request-pipeline.js\";\nimport { notFoundResponse } from \"./http-error-responses.js\";\nimport { withScriptNonce } from \"vinext/shims/script-nonce-context\";\nimport {\n createInlineScriptTag,\n createNonceAttribute,\n escapeHtmlAttr,\n safeJsonStringify,\n} from \"./html.js\";\nimport { createRscEmbedTransform, createTickBufferedTransform } from \"./app-ssr-stream.js\";\nimport { deferUntilStreamConsumed } from \"./app-page-stream.js\";\nimport { AppElementsWire, type AppWireElements } from \"./app-elements.js\";\nimport { ElementsContext, Slot } from \"vinext/shims/slot\";\nimport { createClientReferencePreloader } from \"./app-client-reference-preloader.js\";\nimport { RSC_FORM_STATE_GLOBAL } from \"./app-browser-hydration.js\";\n\nexport type FontPreload = {\n href: string;\n type: string;\n};\n\nexport type FontData = {\n links?: string[];\n styles?: string[];\n preloads?: FontPreload[];\n};\n\nconst clientReferencePreloader = createClientReferencePreloader({\n getReferences() {\n return clientReferences;\n },\n getClientRequire() {\n return globalThis.__vite_rsc_client_require__;\n },\n onPreloadError(id, error) {\n if (process.env.NODE_ENV !== \"production\") {\n console.warn(\"[vinext] failed to preload client ref:\", id, error);\n }\n },\n});\n\nfunction ssrErrorDigest(input: string): string {\n let hash = 5381;\n for (let i = input.length - 1; i >= 0; i--) {\n hash = (hash * 33) ^ input.charCodeAt(i);\n }\n return (hash >>> 0).toString();\n}\n\nfunction getErrorMessage(error: unknown): string {\n if (error instanceof Error) return error.message;\n if (typeof error === \"string\") return error;\n return Object.prototype.toString.call(error);\n}\n\nfunction renderInsertedHtml(insertedElements: readonly unknown[]): string {\n let insertedHTML = \"\";\n\n for (const element of insertedElements) {\n try {\n insertedHTML += renderToStaticMarkup(\n createReactElement(Fragment, null, element as ReactNode),\n );\n } catch {\n // Ignore individual callback failures so the rest of the page can render.\n }\n }\n\n return insertedHTML;\n}\n\nfunction renderFontHtml(fontData?: FontData, nonce?: string): string {\n if (!fontData) return \"\";\n\n let fontHTML = \"\";\n const nonceAttr = createNonceAttribute(nonce);\n\n for (const url of fontData.links ?? []) {\n fontHTML += `<link rel=\"stylesheet\"${nonceAttr} href=\"${escapeHtmlAttr(url)}\" />\\n`;\n }\n\n for (const preload of fontData.preloads ?? []) {\n fontHTML += `<link rel=\"preload\"${nonceAttr} href=\"${escapeHtmlAttr(preload.href)}\" as=\"font\" type=\"${escapeHtmlAttr(preload.type)}\" crossorigin />\\n`;\n }\n\n if (fontData.styles && fontData.styles.length > 0) {\n fontHTML += `<style data-vinext-fonts${nonceAttr}>${fontData.styles.join(\"\\n\")}</style>\\n`;\n }\n\n return fontHTML;\n}\n\nfunction extractModulePreloadHtml(bootstrapScriptContent?: string, nonce?: string): string {\n if (!bootstrapScriptContent) return \"\";\n\n const match = bootstrapScriptContent.match(/import\\(\"([^\"]+)\"\\)/);\n if (!match?.[1]) return \"\";\n\n return `<link rel=\"modulepreload\"${createNonceAttribute(nonce)} href=\"${escapeHtmlAttr(match[1])}\" />\\n`;\n}\n\nfunction buildHeadInjectionHtml(\n navContext: NavigationContext | null,\n bootstrapScriptContent: string | undefined,\n formState: ReactFormState | null,\n insertedHTML: string,\n fontHTML: string,\n scriptNonce?: string,\n): string {\n const paramsScript = createInlineScriptTag(\n \"self.__VINEXT_RSC_PARAMS__=\" + safeJsonStringify(navContext?.params ?? {}),\n scriptNonce,\n );\n const navPayload = {\n pathname: navContext?.pathname ?? \"/\",\n searchParams: navContext?.searchParams ? [...navContext.searchParams.entries()] : [],\n };\n const navScript = createInlineScriptTag(\n \"self.__VINEXT_RSC_NAV__=\" + safeJsonStringify(navPayload),\n scriptNonce,\n );\n const formStateScript =\n formState === null\n ? \"\"\n : createInlineScriptTag(\n \"self[\" + safeJsonStringify(RSC_FORM_STATE_GLOBAL) + \"]=\" + safeJsonStringify(formState),\n scriptNonce,\n );\n\n return (\n paramsScript +\n navScript +\n formStateScript +\n extractModulePreloadHtml(bootstrapScriptContent, scriptNonce) +\n insertedHTML +\n fontHTML\n );\n}\n\nexport async function handleSsr(\n rscStream: ReadableStream<Uint8Array>,\n navContext: NavigationContext | null,\n fontData?: FontData,\n options?: {\n scriptNonce?: string;\n /** Pre-split side stream for embed+capture fusion. When provided,\n * rscStream is fed directly to createFromReadableStream (no internal tee).\n * The embed transform accumulates raw bytes. */\n sideStream?: ReadableStream<Uint8Array>;\n /** Out-parameter: filled with accumulated raw RSC bytes when sideStream is consumed. */\n capturedRscDataRef?: { value: Promise<ArrayBuffer> | null };\n formState?: ReactFormState | null;\n /** When true, wait for the full React tree (including Suspense boundaries)\n * to resolve before returning the HTML stream. Used for static prerender\n * and ISR cache writes to avoid caching fallback content. */\n waitForAllReady?: boolean;\n },\n): Promise<ReadableStream<Uint8Array>> {\n return runWithNavigationContext(async () => {\n await clientReferencePreloader.preload();\n\n if (navContext) {\n setNavigationContext(navContext);\n }\n\n clearServerInsertedHTML();\n\n const cleanup = (): void => {\n setNavigationContext(null);\n clearServerInsertedHTML();\n };\n\n try {\n // Fused tee path (#981): caller pre-split the stream. No internal tee needed.\n // sideStream carries both the embed transform and raw byte accumulation.\n // rscStream is used directly for createFromReadableStream (SSR).\n let ssrStream: ReadableStream<Uint8Array>;\n let rscEmbed;\n\n if (options?.sideStream) {\n ssrStream = rscStream;\n rscEmbed = createRscEmbedTransform(options.sideStream, options?.scriptNonce);\n if (options.capturedRscDataRef) {\n options.capturedRscDataRef.value = rscEmbed.getRawBuffer();\n }\n } else {\n const [s1, s2] = rscStream.tee();\n ssrStream = s1;\n rscEmbed = createRscEmbedTransform(s2, options?.scriptNonce);\n }\n\n let flightRoot: PromiseLike<AppWireElements> | null = null;\n\n function VinextFlightRoot(): ReactNode {\n if (!flightRoot) {\n flightRoot = createFromReadableStream<AppWireElements>(ssrStream);\n }\n const wireElements = use(flightRoot);\n const elements = AppElementsWire.decode(wireElements);\n const metadata = AppElementsWire.readMetadata(elements);\n return createReactElement(\n ElementsContext.Provider,\n { value: elements },\n createReactElement(Slot, { id: metadata.routeId }),\n );\n }\n\n const root = createReactElement(VinextFlightRoot);\n const ssrTree = ServerInsertedHTMLContext\n ? createReactElement(\n ServerInsertedHTMLContext.Provider,\n { value: useServerInsertedHTML },\n root,\n )\n : root;\n const ssrRoot = withScriptNonce(ssrTree, options?.scriptNonce);\n\n const bootstrapScriptContent = await import.meta.viteRsc.loadBootstrapScriptContent(\"index\");\n\n const htmlStream = await renderToReadableStream(ssrRoot, {\n bootstrapScriptContent,\n formState: options?.formState ?? null,\n nonce: options?.scriptNonce,\n onError(error) {\n if (error && typeof error === \"object\" && \"digest\" in error) {\n return String(error.digest);\n }\n\n if (process.env.NODE_ENV === \"production\" && error) {\n const message = getErrorMessage(error);\n const stack = error instanceof Error ? (error.stack ?? \"\") : \"\";\n return ssrErrorDigest(message + stack);\n }\n\n return undefined;\n },\n });\n\n // When producing static output (prerender / ISR cache writes), wait for\n // the full React tree to resolve before emitting bytes. This prevents\n // Suspense fallback content from being serialized to the cache.\n // Matches Next.js waitForAllReady forkpoint in renderToNodeFizzStream.\n if (options?.waitForAllReady === true) {\n await htmlStream.allReady;\n }\n\n const fontHTML = renderFontHtml(fontData, options?.scriptNonce);\n let didInjectHeadHTML = false;\n const getInsertedHTML = (): string => {\n const insertedHTML = renderInsertedHtml(renderServerInsertedHTML());\n if (didInjectHeadHTML) return insertedHTML;\n\n didInjectHeadHTML = true;\n return buildHeadInjectionHtml(\n navContext,\n bootstrapScriptContent,\n options?.formState ?? null,\n insertedHTML,\n fontHTML,\n options?.scriptNonce,\n );\n };\n\n return deferUntilStreamConsumed(\n htmlStream.pipeThrough(createTickBufferedTransform(rscEmbed, getInsertedHTML)),\n cleanup,\n );\n } catch (error) {\n cleanup();\n throw error;\n }\n }) as Promise<ReadableStream<Uint8Array>>;\n}\n\nexport default {\n async fetch(request: Request): Promise<Response> {\n const url = new URL(request.url);\n // Block protocol-relative URL open redirects (including percent-encoded\n // variants like /%5Cevil.com/). See request-pipeline.ts for details.\n if (isOpenRedirectShaped(url.pathname)) {\n return notFoundResponse();\n }\n\n const rscModule = await import.meta.viteRsc.loadModule<{\n default(request: Request): Promise<Response | string | null | undefined>;\n }>(\"rsc\", \"index\");\n const result = await rscModule.default(request);\n\n if (result instanceof Response) {\n return result;\n }\n\n if (result == null) {\n return notFoundResponse();\n }\n\n return new Response(String(result), { status: 200 });\n },\n};\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"app-ssr-stream.js","names":[],"sources":["../../src/server/app-ssr-stream.ts"],"sourcesContent":["import { createInlineScriptTag, safeJsonStringify } from \"./html.js\";\n\ntype RscEmbedTransform = {\n flush(): string;\n finalize(): Promise<string>;\n /** Resolves when all raw bytes from the embed stream have been read. */\n getRawBuffer(): Promise<ArrayBuffer>;\n};\n\ntype HtmlInsertion = string | (() => string);\n\n/**\n * Fix invalid preload \"as\" values in RSC Flight hint lines before they reach\n * the client. React Flight emits HL hints with as=\"stylesheet\" for CSS, but\n * the HTML spec requires as=\"style\" for <link rel=\"preload\">.\n */\nexport function fixFlightHints(text: string): string {\n return text.replace(/(\\d*:HL\\[.*?),\"stylesheet\"(\\]|,)/g, '$1,\"style\"$2');\n}\n\n/**\n * Create a helper that progressively embeds RSC chunks as inline <script> tags.\n * The browser entry turns the embedded text chunks back into Uint8Array data.\n */\nexport function createRscEmbedTransform(\n embedStream: ReadableStream<Uint8Array>,\n scriptNonce?: string,\n): RscEmbedTransform {\n const reader = embedStream.getReader();\n const decoder = new TextDecoder();\n let pendingChunks: string[] = [];\n const rawChunks: Uint8Array[] = [];\n let reading = false;\n\n async function pumpReader(): Promise<void> {\n if (reading) return;\n reading = true;\n try {\n while (true) {\n const result = await reader.read();\n if (result.done) break;\n // Accumulate raw bytes BEFORE fixFlightHints so the cache stores\n // unmodified RSC data. The embed script path below applies fixes.\n rawChunks.push(result.value);\n const text = decoder.decode(result.value, { stream: true });\n // The RSC entry already fixes HL hints at the source. Keep this second\n // pass as defense in depth for any embed stream that bypasses that\n // wrapper; the rewrite is idempotent, so double-application is safe.\n pendingChunks.push(fixFlightHints(text));\n }\n } catch (error) {\n if (process.env.NODE_ENV !== \"production\") {\n console.warn(\"[vinext] RSC embed stream read error:\", error);\n }\n throw error;\n } finally {\n reading = false;\n }\n }\n\n const pumpPromise = pumpReader();\n\n return {\n flush(): string {\n if (pendingChunks.length === 0) return \"\";\n\n const chunks = pendingChunks;\n pendingChunks = [];\n\n let scripts = \"\";\n for (const chunk of chunks) {\n scripts += createInlineScriptTag(\n \"self.__VINEXT_RSC_CHUNKS__=self.__VINEXT_RSC_CHUNKS__||[];self.__VINEXT_RSC_CHUNKS__.push(\" +\n safeJsonStringify(chunk) +\n \")\",\n scriptNonce,\n );\n }\n return scripts;\n },\n\n async finalize(): Promise<string> {\n await pumpPromise;\n let scripts = this.flush();\n scripts += createInlineScriptTag(\"self.__VINEXT_RSC_DONE__=true\", scriptNonce);\n return scripts;\n },\n\n async getRawBuffer(): Promise<ArrayBuffer> {\n await pumpPromise;\n let totalLength = 0;\n for (const chunk of rawChunks) {\n totalLength += chunk.byteLength;\n }\n const buffer = new Uint8Array(totalLength);\n let offset = 0;\n for (const chunk of rawChunks) {\n buffer.set(chunk, offset);\n offset += chunk.byteLength;\n }\n rawChunks.length = 0;\n return buffer.buffer;\n },\n };\n}\n\n/**\n * Fix invalid preload \"as\" values in server-rendered HTML.\n * React Fizz emits <link rel=\"preload\" as=\"stylesheet\"> for CSS, but the\n * HTML spec requires as=\"style\" for <link rel=\"preload\">.\n */\nexport function fixPreloadAs(html: string): string {\n return html.replace(/<link(?=[^>]*\\srel=\"preload\")[^>]*>/g, (tag) =>\n tag.replace(' as=\"stylesheet\"', ' as=\"style\"'),\n );\n}\n\n/**\n * Create the tick-buffered HTML transform that injects RSC scripts between\n * React Fizz flush cycles without corrupting split HTML chunks.\n */\nexport function createTickBufferedTransform(\n rscEmbed: RscEmbedTransform,\n injectHTML: HtmlInsertion = \"\",\n): TransformStream<Uint8Array, Uint8Array> {\n const decoder = new TextDecoder();\n const encoder = new TextEncoder();\n const insertsPerFlush = typeof injectHTML === \"function\";\n let injected = false;\n let buffered: string[] = [];\n let timeoutId: ReturnType<typeof setTimeout> | null = null;\n const readInsertion = (): string =>\n typeof injectHTML === \"function\" ? injectHTML() : injectHTML;\n const emitInsertion = (controller: TransformStreamDefaultController<Uint8Array>): void => {\n const insertion = readInsertion();\n if (insertion) {\n controller.enqueue(encoder.encode(insertion));\n }\n };\n\n const flushBuffered = (controller: TransformStreamDefaultController<Uint8Array>): void => {\n if (buffered.length === 0) return;\n\n if (injected && insertsPerFlush) {\n // Emit newly collected server-inserted HTML before the next Fizz HTML\n // batch so CSS-in-JS styles precede the elements they style.\n emitInsertion(controller);\n }\n\n for (const chunk of buffered) {\n if (!injected) {\n const headEnd = chunk.indexOf(\"</head>\");\n if (headEnd !== -1) {\n const before = chunk.slice(0, headEnd);\n const after = chunk.slice(headEnd);\n controller.enqueue(encoder.encode(before + readInsertion() + after));\n injected = true;\n continue;\n }\n }\n controller.enqueue(encoder.encode(chunk));\n }\n buffered = [];\n };\n\n return new TransformStream<Uint8Array, Uint8Array>({\n transform(chunk, controller) {\n buffered.push(fixPreloadAs(decoder.decode(chunk, { stream: true })));\n\n if (timeoutId !== null) return;\n\n timeoutId = setTimeout(() => {\n try {\n flushBuffered(controller);\n\n const rscScripts = rscEmbed.flush();\n if (rscScripts) {\n controller.enqueue(encoder.encode(rscScripts));\n }\n } catch {\n // Stream was cancelled between when the timeout was registered and\n // when it fired (e.g. client disconnected, health-check cancelled\n // the response body). Ignore — the stream is already closed.\n }\n\n timeoutId = null;\n }, 0);\n },\n\n async flush(controller) {\n if (timeoutId !== null) {\n clearTimeout(timeoutId);\n timeoutId = null;\n }\n\n flushBuffered(controller);\n\n if (!injected) {\n emitInsertion(controller);\n injected = true;\n } else if (insertsPerFlush) {\n emitInsertion(controller);\n }\n\n const finalScripts = await rscEmbed.finalize();\n if (finalScripts) {\n controller.enqueue(encoder.encode(finalScripts));\n }\n },\n });\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"app-ssr-stream.js","names":[],"sources":["../../src/server/app-ssr-stream.ts"],"sourcesContent":["import { createInlineScriptTag, safeJsonStringify } from \"./html.js\";\n\ntype RscEmbedTransform = {\n flush(): string;\n finalize(): Promise<string>;\n /** Resolves when all raw bytes from the embed stream have been read. */\n getRawBuffer(): Promise<ArrayBuffer>;\n};\n\ntype HtmlInsertion = string | (() => string);\n\n/**\n * Fix invalid preload \"as\" values in RSC Flight hint lines before they reach\n * the client. React Flight emits HL hints with as=\"stylesheet\" for CSS, but\n * the HTML spec requires as=\"style\" for <link rel=\"preload\">.\n */\nexport function fixFlightHints(text: string): string {\n return text.replace(/(\\d*:HL\\[.*?),\"stylesheet\"(\\]|,)/g, '$1,\"style\"$2');\n}\n\n/**\n * Create a helper that progressively embeds RSC chunks as inline <script> tags.\n * The browser entry turns the embedded text chunks back into Uint8Array data.\n */\nexport function createRscEmbedTransform(\n embedStream: ReadableStream<Uint8Array>,\n scriptNonce?: string,\n): RscEmbedTransform {\n const reader = embedStream.getReader();\n const decoder = new TextDecoder();\n let pendingChunks: string[] = [];\n const rawChunks: Uint8Array[] = [];\n let reading = false;\n\n async function pumpReader(): Promise<void> {\n if (reading) return;\n reading = true;\n try {\n while (true) {\n const result = await reader.read();\n if (result.done) break;\n // Accumulate raw bytes BEFORE fixFlightHints so the cache stores\n // unmodified RSC data. The embed script path below applies fixes.\n rawChunks.push(result.value);\n const text = decoder.decode(result.value, { stream: true });\n // The RSC entry already fixes HL hints at the source. Keep this second\n // pass as defense in depth for any embed stream that bypasses that\n // wrapper; the rewrite is idempotent, so double-application is safe.\n pendingChunks.push(fixFlightHints(text));\n }\n } catch (error) {\n if (process.env.NODE_ENV !== \"production\") {\n console.warn(\"[vinext] RSC embed stream read error:\", error);\n }\n throw error;\n } finally {\n reading = false;\n }\n }\n\n const pumpPromise = pumpReader();\n\n return {\n flush(): string {\n if (pendingChunks.length === 0) return \"\";\n\n const chunks = pendingChunks;\n pendingChunks = [];\n\n let scripts = \"\";\n for (const chunk of chunks) {\n scripts += createInlineScriptTag(\n \"self.__VINEXT_RSC_CHUNKS__=self.__VINEXT_RSC_CHUNKS__||[];self.__VINEXT_RSC_CHUNKS__.push(\" +\n safeJsonStringify(chunk) +\n \")\",\n scriptNonce,\n );\n }\n return scripts;\n },\n\n async finalize(): Promise<string> {\n await pumpPromise;\n let scripts = this.flush();\n scripts += createInlineScriptTag(\"self.__VINEXT_RSC_DONE__=true\", scriptNonce);\n return scripts;\n },\n\n async getRawBuffer(): Promise<ArrayBuffer> {\n await pumpPromise;\n let totalLength = 0;\n for (const chunk of rawChunks) {\n totalLength += chunk.byteLength;\n }\n const buffer = new Uint8Array(totalLength);\n let offset = 0;\n for (const chunk of rawChunks) {\n buffer.set(chunk, offset);\n offset += chunk.byteLength;\n }\n rawChunks.length = 0;\n return buffer.buffer;\n },\n };\n}\n\n/**\n * Fix invalid preload \"as\" values in server-rendered HTML.\n * React Fizz emits <link rel=\"preload\" as=\"stylesheet\"> for CSS, but the\n * HTML spec requires as=\"style\" for <link rel=\"preload\">.\n */\nexport function fixPreloadAs(html: string): string {\n return html.replace(/<link(?=[^>]*\\srel=\"preload\")[^>]*>/g, (tag) =>\n tag.replace(' as=\"stylesheet\"', ' as=\"style\"'),\n );\n}\n\n/**\n * Create the tick-buffered HTML transform that injects RSC scripts between\n * React Fizz flush cycles without corrupting split HTML chunks.\n */\nexport function createTickBufferedTransform(\n rscEmbed: RscEmbedTransform,\n injectHTML: HtmlInsertion = \"\",\n): TransformStream<Uint8Array, Uint8Array> {\n const decoder = new TextDecoder();\n const encoder = new TextEncoder();\n const insertsPerFlush = typeof injectHTML === \"function\";\n let injected = false;\n let buffered: string[] = [];\n let timeoutId: ReturnType<typeof setTimeout> | null = null;\n const readInsertion = (): string =>\n typeof injectHTML === \"function\" ? injectHTML() : injectHTML;\n const emitInsertion = (controller: TransformStreamDefaultController<Uint8Array>): void => {\n const insertion = readInsertion();\n if (insertion) {\n controller.enqueue(encoder.encode(insertion));\n }\n };\n\n const flushBuffered = (controller: TransformStreamDefaultController<Uint8Array>): void => {\n if (buffered.length === 0) return;\n\n if (injected && insertsPerFlush) {\n // Emit newly collected server-inserted HTML before the next Fizz HTML\n // batch so CSS-in-JS styles precede the elements they style.\n emitInsertion(controller);\n }\n\n for (const chunk of buffered) {\n if (!injected) {\n const headEnd = chunk.indexOf(\"</head>\");\n if (headEnd !== -1) {\n const before = chunk.slice(0, headEnd);\n const after = chunk.slice(headEnd);\n controller.enqueue(encoder.encode(before + readInsertion() + after));\n injected = true;\n continue;\n }\n }\n controller.enqueue(encoder.encode(chunk));\n }\n buffered = [];\n };\n\n return new TransformStream<Uint8Array, Uint8Array>({\n transform(chunk, controller) {\n buffered.push(fixPreloadAs(decoder.decode(chunk, { stream: true })));\n\n if (timeoutId !== null) return;\n\n timeoutId = setTimeout(() => {\n try {\n flushBuffered(controller);\n\n const rscScripts = rscEmbed.flush();\n if (rscScripts) {\n controller.enqueue(encoder.encode(rscScripts));\n }\n } catch {\n // Stream was cancelled between when the timeout was registered and\n // when it fired (e.g. client disconnected, health-check cancelled\n // the response body). Ignore — the stream is already closed.\n }\n\n timeoutId = null;\n }, 0);\n },\n\n async flush(controller) {\n if (timeoutId !== null) {\n clearTimeout(timeoutId);\n timeoutId = null;\n }\n\n flushBuffered(controller);\n\n if (!injected) {\n emitInsertion(controller);\n injected = true;\n } else if (insertsPerFlush) {\n emitInsertion(controller);\n }\n\n const finalScripts = await rscEmbed.finalize();\n if (finalScripts) {\n controller.enqueue(encoder.encode(finalScripts));\n }\n },\n });\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"app-static-generation.js","names":[],"sources":["../../src/server/app-static-generation.ts"],"sourcesContent":["import type { HeadersContext } from \"vinext/shims/headers\";\n\ntype AppStaticGenerationRouteKind = \"page\" | \"route\";\n\ntype CreateStaticGenerationHeadersContextOptions = {\n dynamicConfig?: string;\n routeKind: AppStaticGenerationRouteKind;\n routePattern?: string;\n};\n\nexport function getAppPageStaticGenerationErrorMessage(): string {\n return (\n 'Page with `dynamic = \"error\"` used a dynamic API. ' +\n \"This page was expected to be fully static, but headers(), cookies(), \" +\n \"or searchParams was accessed. Remove the dynamic API usage or change \" +\n 'the dynamic config to \"auto\" or \"force-dynamic\".'\n );\n}\n\nexport function getAppRouteStaticGenerationErrorMessage(\n routePattern?: string,\n expression?: string,\n): string {\n const route = routePattern ?? \"unknown route\";\n const dynamicExpression = expression ?? \"a dynamic request API\";\n return (\n `Route ${route} with \\`dynamic = \"error\"\\` couldn't be rendered statically ` +\n `because it used ${dynamicExpression}. ` +\n \"See more info here: https://nextjs.org/docs/app/building-your-application/rendering/static-and-dynamic#dynamic-rendering\"\n );\n}\n\nexport function createStaticGenerationHeadersContext(\n options: CreateStaticGenerationHeadersContextOptions,\n): HeadersContext {\n const context: HeadersContext = {\n headers: new Headers(),\n cookies: new Map(),\n };\n\n if (options.dynamicConfig === \"force-static\") {\n context.forceStatic = true;\n }\n\n if (options.dynamicConfig === \"error\") {\n context.accessError = new Error(\n options.routeKind === \"route\"\n ? getAppRouteStaticGenerationErrorMessage(options.routePattern)\n : getAppPageStaticGenerationErrorMessage(),\n );\n }\n\n return context;\n}\n"],"mappings":";AAUA,SAAgB,yCAAiD;AAC/D,QACE;;AAOJ,SAAgB,wCACd,cACA,YACQ;AAGR,QACE,SAHY,gBAAgB,gBAGb,8EAFS,cAAc,wBAGD;;AAKzC,SAAgB,qCACd,SACgB;CAChB,MAAM,UAA0B;EAC9B,SAAS,IAAI,SAAS;EACtB,yBAAS,IAAI,KAAK;EACnB;AAED,KAAI,QAAQ,kBAAkB,eAC5B,SAAQ,cAAc;AAGxB,KAAI,QAAQ,kBAAkB,QAC5B,SAAQ,cAAc,IAAI,MACxB,QAAQ,cAAc,UAClB,wCAAwC,QAAQ,aAAa,GAC7D,wCAAwC,CAC7C;AAGH,QAAO"}
1
+ {"version":3,"file":"app-static-generation.js","names":[],"sources":["../../src/server/app-static-generation.ts"],"sourcesContent":["import type { HeadersContext } from \"vinext/shims/headers\";\n\ntype AppStaticGenerationRouteKind = \"page\" | \"route\";\n\ntype CreateStaticGenerationHeadersContextOptions = {\n dynamicConfig?: string;\n routeKind: AppStaticGenerationRouteKind;\n routePattern?: string;\n};\n\nexport function getAppPageStaticGenerationErrorMessage(): string {\n return (\n 'Page with `dynamic = \"error\"` used a dynamic API. ' +\n \"This page was expected to be fully static, but headers(), cookies(), \" +\n \"or searchParams was accessed. Remove the dynamic API usage or change \" +\n 'the dynamic config to \"auto\" or \"force-dynamic\".'\n );\n}\n\nexport function getAppRouteStaticGenerationErrorMessage(\n routePattern?: string,\n expression?: string,\n): string {\n const route = routePattern ?? \"unknown route\";\n const dynamicExpression = expression ?? \"a dynamic request API\";\n return (\n `Route ${route} with \\`dynamic = \"error\"\\` couldn't be rendered statically ` +\n `because it used ${dynamicExpression}. ` +\n \"See more info here: https://nextjs.org/docs/app/building-your-application/rendering/static-and-dynamic#dynamic-rendering\"\n );\n}\n\nexport function createStaticGenerationHeadersContext(\n options: CreateStaticGenerationHeadersContextOptions,\n): HeadersContext {\n const context: HeadersContext = {\n headers: new Headers(),\n cookies: new Map(),\n };\n\n if (options.dynamicConfig === \"force-static\") {\n context.forceStatic = true;\n }\n\n if (options.dynamicConfig === \"error\") {\n context.accessError = new Error(\n options.routeKind === \"route\"\n ? getAppRouteStaticGenerationErrorMessage(options.routePattern)\n : getAppPageStaticGenerationErrorMessage(),\n );\n }\n\n return context;\n}\n"],"mappings":";AAUA,SAAgB,yCAAiD;CAC/D,OACE;;AAOJ,SAAgB,wCACd,cACA,YACQ;CAGR,OACE,SAHY,gBAAgB,gBAGb,8EAFS,cAAc,wBAGD;;AAKzC,SAAgB,qCACd,SACgB;CAChB,MAAM,UAA0B;EAC9B,SAAS,IAAI,SAAS;EACtB,yBAAS,IAAI,KAAK;EACnB;CAED,IAAI,QAAQ,kBAAkB,gBAC5B,QAAQ,cAAc;CAGxB,IAAI,QAAQ,kBAAkB,SAC5B,QAAQ,cAAc,IAAI,MACxB,QAAQ,cAAc,UAClB,wCAAwC,QAAQ,aAAa,GAC7D,wCAAwC,CAC7C;CAGH,OAAO"}
@@ -1 +1 @@
1
- {"version":3,"file":"artifact-compatibility.js","names":[],"sources":["../../src/server/artifact-compatibility.ts"],"sourcesContent":["import { fnv1a64 } from \"../utils/hash.js\";\n\nexport const ARTIFACT_COMPATIBILITY_SCHEMA_VERSION = 1;\n\n// These versions describe separate protocol layers. For example, a future\n// rolling deploy can bump the flat AppElements row shape while keeping the\n// envelope object and serialized RSC transport version stable.\nexport const APP_ELEMENTS_SCHEMA_VERSION = 1;\nexport const RSC_PAYLOAD_SCHEMA_VERSION = 1;\n\nexport type ArtifactCompatibilityEnvelope = Readonly<{\n schemaVersion: typeof ARTIFACT_COMPATIBILITY_SCHEMA_VERSION;\n graphVersion: string | null;\n deploymentVersion: string | null;\n appElementsSchemaVersion: typeof APP_ELEMENTS_SCHEMA_VERSION;\n rscPayloadSchemaVersion: typeof RSC_PAYLOAD_SCHEMA_VERSION;\n rootBoundaryId: string | null;\n renderEpoch: string | null;\n}>;\n\ntype ArtifactCompatibilityEnvelopeInput = Readonly<{\n graphVersion?: string | null;\n deploymentVersion?: string | null;\n rootBoundaryId?: string | null;\n renderEpoch?: string | null;\n}>;\n\ntype ArtifactCompatibilityFallback = \"renderFresh\";\n\ntype ArtifactCompatibilityUnknownReason =\n | \"graphVersionUnknown\"\n | \"deploymentVersionUnknown\"\n | \"rootBoundaryIdUnknown\"\n | \"renderEpochUnknown\";\n\ntype ArtifactCompatibilityIncompatibleReason =\n | \"appElementsSchemaVersionMismatch\"\n | \"deploymentVersionMismatch\"\n | \"graphVersionMismatch\"\n | \"renderEpochMismatch\"\n | \"rootBoundaryIdMismatch\"\n | \"rscPayloadSchemaVersionMismatch\"\n | \"schemaVersionMismatch\";\n\ntype ArtifactCompatibilityDecision = Readonly<\n | { kind: \"compatible\" }\n | {\n kind: \"unknown\";\n fallback: ArtifactCompatibilityFallback;\n reason: ArtifactCompatibilityUnknownReason;\n }\n | {\n kind: \"incompatible\";\n fallback: ArtifactCompatibilityFallback;\n reason: ArtifactCompatibilityIncompatibleReason;\n }\n>;\n\ntype ArtifactCompatibilityGraphVersionInput = Readonly<{\n routePattern: string;\n rootBoundaryId: string | null;\n}>;\n\nexport function createArtifactCompatibilityEnvelope(\n input: ArtifactCompatibilityEnvelopeInput = {},\n): ArtifactCompatibilityEnvelope {\n return {\n schemaVersion: ARTIFACT_COMPATIBILITY_SCHEMA_VERSION,\n graphVersion: input.graphVersion ?? null,\n deploymentVersion: input.deploymentVersion ?? null,\n appElementsSchemaVersion: APP_ELEMENTS_SCHEMA_VERSION,\n rscPayloadSchemaVersion: RSC_PAYLOAD_SCHEMA_VERSION,\n rootBoundaryId: input.rootBoundaryId ?? null,\n renderEpoch: input.renderEpoch ?? null,\n };\n}\n\nexport function createArtifactCompatibilityGraphVersion(\n input: ArtifactCompatibilityGraphVersionInput,\n): string {\n const fingerprint = fnv1a64(JSON.stringify([input.routePattern, input.rootBoundaryId]));\n return `app-route-graph:${fingerprint}`;\n}\n\nfunction isRecord(value: unknown): value is Readonly<Record<string, unknown>> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction isStringOrNull(value: unknown): value is string | null {\n return typeof value === \"string\" || value === null;\n}\n\nfunction hasCurrentSchemaVersions(record: Readonly<Record<string, unknown>>): boolean {\n return (\n record.schemaVersion === ARTIFACT_COMPATIBILITY_SCHEMA_VERSION &&\n record.appElementsSchemaVersion === APP_ELEMENTS_SCHEMA_VERSION &&\n record.rscPayloadSchemaVersion === RSC_PAYLOAD_SCHEMA_VERSION\n );\n}\n\nexport function parseArtifactCompatibilityEnvelope(\n value: unknown,\n): ArtifactCompatibilityEnvelope | null {\n if (!isRecord(value)) return null;\n // The Wave01 skeleton intentionally collapses version mismatch and malformed\n // metadata into \"not current\". Cache/skip callers must split those cases\n // before treating unknown compatibility as anything other than a miss/reject.\n if (!hasCurrentSchemaVersions(value)) return null;\n if (!isStringOrNull(value.graphVersion)) return null;\n if (!isStringOrNull(value.deploymentVersion)) return null;\n if (!isStringOrNull(value.rootBoundaryId)) return null;\n if (!isStringOrNull(value.renderEpoch)) return null;\n\n // This parser intentionally returns a normalized current-version proof. A\n // future-compatible reader should introduce a separate parsed type instead of\n // widening this Wave01 envelope after the current-version checks above.\n return {\n schemaVersion: ARTIFACT_COMPATIBILITY_SCHEMA_VERSION,\n graphVersion: value.graphVersion,\n deploymentVersion: value.deploymentVersion,\n appElementsSchemaVersion: APP_ELEMENTS_SCHEMA_VERSION,\n rscPayloadSchemaVersion: RSC_PAYLOAD_SCHEMA_VERSION,\n rootBoundaryId: value.rootBoundaryId,\n renderEpoch: value.renderEpoch,\n };\n}\n\nfunction incompatible(\n reason: ArtifactCompatibilityIncompatibleReason,\n): ArtifactCompatibilityDecision {\n return { kind: \"incompatible\", fallback: \"renderFresh\", reason };\n}\n\nfunction unknown(reason: ArtifactCompatibilityUnknownReason): ArtifactCompatibilityDecision {\n return { kind: \"unknown\", fallback: \"renderFresh\", reason };\n}\n\nfunction compareKnownField(\n currentValue: string | null,\n candidateValue: string | null,\n unknownReason: ArtifactCompatibilityUnknownReason,\n mismatchReason: ArtifactCompatibilityIncompatibleReason,\n): ArtifactCompatibilityDecision | null {\n if (currentValue === null || candidateValue === null) {\n return unknown(unknownReason);\n }\n if (currentValue !== candidateValue) {\n return incompatible(mismatchReason);\n }\n return null;\n}\n\nexport function evaluateArtifactCompatibility(\n current: ArtifactCompatibilityEnvelope,\n candidate: ArtifactCompatibilityEnvelope,\n): ArtifactCompatibilityDecision {\n // Pre-positioned for #726-COMPAT-04/05, where cache and visited-response\n // reuse paths will compare the current render proof with a candidate payload.\n if (current.schemaVersion !== candidate.schemaVersion) {\n return incompatible(\"schemaVersionMismatch\");\n }\n if (current.appElementsSchemaVersion !== candidate.appElementsSchemaVersion) {\n return incompatible(\"appElementsSchemaVersionMismatch\");\n }\n if (current.rscPayloadSchemaVersion !== candidate.rscPayloadSchemaVersion) {\n return incompatible(\"rscPayloadSchemaVersionMismatch\");\n }\n\n const graphDecision = compareKnownField(\n current.graphVersion,\n candidate.graphVersion,\n \"graphVersionUnknown\",\n \"graphVersionMismatch\",\n );\n if (graphDecision) return graphDecision;\n\n const deploymentDecision = compareKnownField(\n current.deploymentVersion,\n candidate.deploymentVersion,\n \"deploymentVersionUnknown\",\n \"deploymentVersionMismatch\",\n );\n if (deploymentDecision) return deploymentDecision;\n\n const rootBoundaryDecision = compareKnownField(\n current.rootBoundaryId,\n candidate.rootBoundaryId,\n \"rootBoundaryIdUnknown\",\n \"rootBoundaryIdMismatch\",\n );\n if (rootBoundaryDecision) return rootBoundaryDecision;\n\n const renderEpochDecision = compareKnownField(\n current.renderEpoch,\n candidate.renderEpoch,\n \"renderEpochUnknown\",\n \"renderEpochMismatch\",\n );\n if (renderEpochDecision) return renderEpochDecision;\n\n return { kind: \"compatible\" };\n}\n"],"mappings":";;AAEA,MAAa,wCAAwC;AAKrD,MAAa,8BAA8B;AAC3C,MAAa,6BAA6B;AAuD1C,SAAgB,oCACd,QAA4C,EAAE,EACf;AAC/B,QAAO;EACL,eAAA;EACA,cAAc,MAAM,gBAAgB;EACpC,mBAAmB,MAAM,qBAAqB;EAC9C,0BAAA;EACA,yBAAA;EACA,gBAAgB,MAAM,kBAAkB;EACxC,aAAa,MAAM,eAAe;EACnC;;AAGH,SAAgB,wCACd,OACQ;AAER,QAAO,mBADa,QAAQ,KAAK,UAAU,CAAC,MAAM,cAAc,MAAM,eAAe,CAAC,CAAC;;AAIzF,SAAS,SAAS,OAA4D;AAC5E,QAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,MAAM;;AAG7E,SAAS,eAAe,OAAwC;AAC9D,QAAO,OAAO,UAAU,YAAY,UAAU;;AAGhD,SAAS,yBAAyB,QAAoD;AACpF,QACE,OAAO,kBAAA,KACP,OAAO,6BAAA,KACP,OAAO,4BAAA;;AAIX,SAAgB,mCACd,OACsC;AACtC,KAAI,CAAC,SAAS,MAAM,CAAE,QAAO;AAI7B,KAAI,CAAC,yBAAyB,MAAM,CAAE,QAAO;AAC7C,KAAI,CAAC,eAAe,MAAM,aAAa,CAAE,QAAO;AAChD,KAAI,CAAC,eAAe,MAAM,kBAAkB,CAAE,QAAO;AACrD,KAAI,CAAC,eAAe,MAAM,eAAe,CAAE,QAAO;AAClD,KAAI,CAAC,eAAe,MAAM,YAAY,CAAE,QAAO;AAK/C,QAAO;EACL,eAAA;EACA,cAAc,MAAM;EACpB,mBAAmB,MAAM;EACzB,0BAAA;EACA,yBAAA;EACA,gBAAgB,MAAM;EACtB,aAAa,MAAM;EACpB;;AAGH,SAAS,aACP,QAC+B;AAC/B,QAAO;EAAE,MAAM;EAAgB,UAAU;EAAe;EAAQ;;AAGlE,SAAS,QAAQ,QAA2E;AAC1F,QAAO;EAAE,MAAM;EAAW,UAAU;EAAe;EAAQ;;AAG7D,SAAS,kBACP,cACA,gBACA,eACA,gBACsC;AACtC,KAAI,iBAAiB,QAAQ,mBAAmB,KAC9C,QAAO,QAAQ,cAAc;AAE/B,KAAI,iBAAiB,eACnB,QAAO,aAAa,eAAe;AAErC,QAAO;;AAGT,SAAgB,8BACd,SACA,WAC+B;AAG/B,KAAI,QAAQ,kBAAkB,UAAU,cACtC,QAAO,aAAa,wBAAwB;AAE9C,KAAI,QAAQ,6BAA6B,UAAU,yBACjD,QAAO,aAAa,mCAAmC;AAEzD,KAAI,QAAQ,4BAA4B,UAAU,wBAChD,QAAO,aAAa,kCAAkC;CAGxD,MAAM,gBAAgB,kBACpB,QAAQ,cACR,UAAU,cACV,uBACA,uBACD;AACD,KAAI,cAAe,QAAO;CAE1B,MAAM,qBAAqB,kBACzB,QAAQ,mBACR,UAAU,mBACV,4BACA,4BACD;AACD,KAAI,mBAAoB,QAAO;CAE/B,MAAM,uBAAuB,kBAC3B,QAAQ,gBACR,UAAU,gBACV,yBACA,yBACD;AACD,KAAI,qBAAsB,QAAO;CAEjC,MAAM,sBAAsB,kBAC1B,QAAQ,aACR,UAAU,aACV,sBACA,sBACD;AACD,KAAI,oBAAqB,QAAO;AAEhC,QAAO,EAAE,MAAM,cAAc"}
1
+ {"version":3,"file":"artifact-compatibility.js","names":[],"sources":["../../src/server/artifact-compatibility.ts"],"sourcesContent":["import { fnv1a64 } from \"../utils/hash.js\";\n\nexport const ARTIFACT_COMPATIBILITY_SCHEMA_VERSION = 1;\n\n// These versions describe separate protocol layers. For example, a future\n// rolling deploy can bump the flat AppElements row shape while keeping the\n// envelope object and serialized RSC transport version stable.\nexport const APP_ELEMENTS_SCHEMA_VERSION = 1;\nexport const RSC_PAYLOAD_SCHEMA_VERSION = 1;\n\nexport type ArtifactCompatibilityEnvelope = Readonly<{\n schemaVersion: typeof ARTIFACT_COMPATIBILITY_SCHEMA_VERSION;\n graphVersion: string | null;\n deploymentVersion: string | null;\n appElementsSchemaVersion: typeof APP_ELEMENTS_SCHEMA_VERSION;\n rscPayloadSchemaVersion: typeof RSC_PAYLOAD_SCHEMA_VERSION;\n rootBoundaryId: string | null;\n renderEpoch: string | null;\n}>;\n\ntype ArtifactCompatibilityEnvelopeInput = Readonly<{\n graphVersion?: string | null;\n deploymentVersion?: string | null;\n rootBoundaryId?: string | null;\n renderEpoch?: string | null;\n}>;\n\ntype ArtifactCompatibilityFallback = \"renderFresh\";\n\ntype ArtifactCompatibilityUnknownReason =\n | \"graphVersionUnknown\"\n | \"deploymentVersionUnknown\"\n | \"rootBoundaryIdUnknown\"\n | \"renderEpochUnknown\";\n\ntype ArtifactCompatibilityIncompatibleReason =\n | \"appElementsSchemaVersionMismatch\"\n | \"deploymentVersionMismatch\"\n | \"graphVersionMismatch\"\n | \"renderEpochMismatch\"\n | \"rootBoundaryIdMismatch\"\n | \"rscPayloadSchemaVersionMismatch\"\n | \"schemaVersionMismatch\";\n\ntype ArtifactCompatibilityDecision = Readonly<\n | { kind: \"compatible\" }\n | {\n kind: \"unknown\";\n fallback: ArtifactCompatibilityFallback;\n reason: ArtifactCompatibilityUnknownReason;\n }\n | {\n kind: \"incompatible\";\n fallback: ArtifactCompatibilityFallback;\n reason: ArtifactCompatibilityIncompatibleReason;\n }\n>;\n\ntype ArtifactCompatibilityGraphVersionInput = Readonly<{\n routePattern: string;\n rootBoundaryId: string | null;\n}>;\n\nexport function createArtifactCompatibilityEnvelope(\n input: ArtifactCompatibilityEnvelopeInput = {},\n): ArtifactCompatibilityEnvelope {\n return {\n schemaVersion: ARTIFACT_COMPATIBILITY_SCHEMA_VERSION,\n graphVersion: input.graphVersion ?? null,\n deploymentVersion: input.deploymentVersion ?? null,\n appElementsSchemaVersion: APP_ELEMENTS_SCHEMA_VERSION,\n rscPayloadSchemaVersion: RSC_PAYLOAD_SCHEMA_VERSION,\n rootBoundaryId: input.rootBoundaryId ?? null,\n renderEpoch: input.renderEpoch ?? null,\n };\n}\n\nexport function createArtifactCompatibilityGraphVersion(\n input: ArtifactCompatibilityGraphVersionInput,\n): string {\n const fingerprint = fnv1a64(JSON.stringify([input.routePattern, input.rootBoundaryId]));\n return `app-route-graph:${fingerprint}`;\n}\n\nfunction isRecord(value: unknown): value is Readonly<Record<string, unknown>> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction isStringOrNull(value: unknown): value is string | null {\n return typeof value === \"string\" || value === null;\n}\n\nfunction hasCurrentSchemaVersions(record: Readonly<Record<string, unknown>>): boolean {\n return (\n record.schemaVersion === ARTIFACT_COMPATIBILITY_SCHEMA_VERSION &&\n record.appElementsSchemaVersion === APP_ELEMENTS_SCHEMA_VERSION &&\n record.rscPayloadSchemaVersion === RSC_PAYLOAD_SCHEMA_VERSION\n );\n}\n\nexport function parseArtifactCompatibilityEnvelope(\n value: unknown,\n): ArtifactCompatibilityEnvelope | null {\n if (!isRecord(value)) return null;\n // The Wave01 skeleton intentionally collapses version mismatch and malformed\n // metadata into \"not current\". Cache/skip callers must split those cases\n // before treating unknown compatibility as anything other than a miss/reject.\n if (!hasCurrentSchemaVersions(value)) return null;\n if (!isStringOrNull(value.graphVersion)) return null;\n if (!isStringOrNull(value.deploymentVersion)) return null;\n if (!isStringOrNull(value.rootBoundaryId)) return null;\n if (!isStringOrNull(value.renderEpoch)) return null;\n\n // This parser intentionally returns a normalized current-version proof. A\n // future-compatible reader should introduce a separate parsed type instead of\n // widening this Wave01 envelope after the current-version checks above.\n return {\n schemaVersion: ARTIFACT_COMPATIBILITY_SCHEMA_VERSION,\n graphVersion: value.graphVersion,\n deploymentVersion: value.deploymentVersion,\n appElementsSchemaVersion: APP_ELEMENTS_SCHEMA_VERSION,\n rscPayloadSchemaVersion: RSC_PAYLOAD_SCHEMA_VERSION,\n rootBoundaryId: value.rootBoundaryId,\n renderEpoch: value.renderEpoch,\n };\n}\n\nfunction incompatible(\n reason: ArtifactCompatibilityIncompatibleReason,\n): ArtifactCompatibilityDecision {\n return { kind: \"incompatible\", fallback: \"renderFresh\", reason };\n}\n\nfunction unknown(reason: ArtifactCompatibilityUnknownReason): ArtifactCompatibilityDecision {\n return { kind: \"unknown\", fallback: \"renderFresh\", reason };\n}\n\nfunction compareKnownField(\n currentValue: string | null,\n candidateValue: string | null,\n unknownReason: ArtifactCompatibilityUnknownReason,\n mismatchReason: ArtifactCompatibilityIncompatibleReason,\n): ArtifactCompatibilityDecision | null {\n if (currentValue === null || candidateValue === null) {\n return unknown(unknownReason);\n }\n if (currentValue !== candidateValue) {\n return incompatible(mismatchReason);\n }\n return null;\n}\n\nexport function evaluateArtifactCompatibility(\n current: ArtifactCompatibilityEnvelope,\n candidate: ArtifactCompatibilityEnvelope,\n): ArtifactCompatibilityDecision {\n // Pre-positioned for #726-COMPAT-04/05, where cache and visited-response\n // reuse paths will compare the current render proof with a candidate payload.\n if (current.schemaVersion !== candidate.schemaVersion) {\n return incompatible(\"schemaVersionMismatch\");\n }\n if (current.appElementsSchemaVersion !== candidate.appElementsSchemaVersion) {\n return incompatible(\"appElementsSchemaVersionMismatch\");\n }\n if (current.rscPayloadSchemaVersion !== candidate.rscPayloadSchemaVersion) {\n return incompatible(\"rscPayloadSchemaVersionMismatch\");\n }\n\n const graphDecision = compareKnownField(\n current.graphVersion,\n candidate.graphVersion,\n \"graphVersionUnknown\",\n \"graphVersionMismatch\",\n );\n if (graphDecision) return graphDecision;\n\n const deploymentDecision = compareKnownField(\n current.deploymentVersion,\n candidate.deploymentVersion,\n \"deploymentVersionUnknown\",\n \"deploymentVersionMismatch\",\n );\n if (deploymentDecision) return deploymentDecision;\n\n const rootBoundaryDecision = compareKnownField(\n current.rootBoundaryId,\n candidate.rootBoundaryId,\n \"rootBoundaryIdUnknown\",\n \"rootBoundaryIdMismatch\",\n );\n if (rootBoundaryDecision) return rootBoundaryDecision;\n\n const renderEpochDecision = compareKnownField(\n current.renderEpoch,\n candidate.renderEpoch,\n \"renderEpochUnknown\",\n \"renderEpochMismatch\",\n );\n if (renderEpochDecision) return renderEpochDecision;\n\n return { kind: \"compatible\" };\n}\n"],"mappings":";;AAEA,MAAa,wCAAwC;AAKrD,MAAa,8BAA8B;AAC3C,MAAa,6BAA6B;AAuD1C,SAAgB,oCACd,QAA4C,EAAE,EACf;CAC/B,OAAO;EACL,eAAA;EACA,cAAc,MAAM,gBAAgB;EACpC,mBAAmB,MAAM,qBAAqB;EAC9C,0BAAA;EACA,yBAAA;EACA,gBAAgB,MAAM,kBAAkB;EACxC,aAAa,MAAM,eAAe;EACnC;;AAGH,SAAgB,wCACd,OACQ;CAER,OAAO,mBADa,QAAQ,KAAK,UAAU,CAAC,MAAM,cAAc,MAAM,eAAe,CAAC,CACjD;;AAGvC,SAAS,SAAS,OAA4D;CAC5E,OAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,MAAM;;AAG7E,SAAS,eAAe,OAAwC;CAC9D,OAAO,OAAO,UAAU,YAAY,UAAU;;AAGhD,SAAS,yBAAyB,QAAoD;CACpF,OACE,OAAO,kBAAA,KACP,OAAO,6BAAA,KACP,OAAO,4BAAA;;AAIX,SAAgB,mCACd,OACsC;CACtC,IAAI,CAAC,SAAS,MAAM,EAAE,OAAO;CAI7B,IAAI,CAAC,yBAAyB,MAAM,EAAE,OAAO;CAC7C,IAAI,CAAC,eAAe,MAAM,aAAa,EAAE,OAAO;CAChD,IAAI,CAAC,eAAe,MAAM,kBAAkB,EAAE,OAAO;CACrD,IAAI,CAAC,eAAe,MAAM,eAAe,EAAE,OAAO;CAClD,IAAI,CAAC,eAAe,MAAM,YAAY,EAAE,OAAO;CAK/C,OAAO;EACL,eAAA;EACA,cAAc,MAAM;EACpB,mBAAmB,MAAM;EACzB,0BAAA;EACA,yBAAA;EACA,gBAAgB,MAAM;EACtB,aAAa,MAAM;EACpB;;AAGH,SAAS,aACP,QAC+B;CAC/B,OAAO;EAAE,MAAM;EAAgB,UAAU;EAAe;EAAQ;;AAGlE,SAAS,QAAQ,QAA2E;CAC1F,OAAO;EAAE,MAAM;EAAW,UAAU;EAAe;EAAQ;;AAG7D,SAAS,kBACP,cACA,gBACA,eACA,gBACsC;CACtC,IAAI,iBAAiB,QAAQ,mBAAmB,MAC9C,OAAO,QAAQ,cAAc;CAE/B,IAAI,iBAAiB,gBACnB,OAAO,aAAa,eAAe;CAErC,OAAO;;AAGT,SAAgB,8BACd,SACA,WAC+B;CAG/B,IAAI,QAAQ,kBAAkB,UAAU,eACtC,OAAO,aAAa,wBAAwB;CAE9C,IAAI,QAAQ,6BAA6B,UAAU,0BACjD,OAAO,aAAa,mCAAmC;CAEzD,IAAI,QAAQ,4BAA4B,UAAU,yBAChD,OAAO,aAAa,kCAAkC;CAGxD,MAAM,gBAAgB,kBACpB,QAAQ,cACR,UAAU,cACV,uBACA,uBACD;CACD,IAAI,eAAe,OAAO;CAE1B,MAAM,qBAAqB,kBACzB,QAAQ,mBACR,UAAU,mBACV,4BACA,4BACD;CACD,IAAI,oBAAoB,OAAO;CAE/B,MAAM,uBAAuB,kBAC3B,QAAQ,gBACR,UAAU,gBACV,yBACA,yBACD;CACD,IAAI,sBAAsB,OAAO;CAEjC,MAAM,sBAAsB,kBAC1B,QAAQ,aACR,UAAU,aACV,sBACA,sBACD;CACD,IAAI,qBAAqB,OAAO;CAEhC,OAAO,EAAE,MAAM,cAAc"}
@@ -24,6 +24,7 @@ function buildRevalidateCacheControl(revalidateSeconds, expireSeconds) {
24
24
  * fallback so older cache entries are not treated as newly fresh downstream.
25
25
  */
26
26
  function buildCachedRevalidateCacheControl(cacheState, revalidateSeconds, expireSeconds) {
27
+ if (revalidateSeconds === Infinity) return STATIC_CACHE_CONTROL;
27
28
  if (cacheState === "STALE" && expireSeconds === void 0) return STALE_REVALIDATE_CACHE_CONTROL;
28
29
  return buildRevalidateCacheControl(revalidateSeconds, expireSeconds);
29
30
  }
@@ -1 +1 @@
1
- {"version":3,"file":"cache-control.js","names":[],"sources":["../../src/server/cache-control.ts"],"sourcesContent":["export const NEVER_CACHE_CONTROL = \"private, no-cache, no-store, max-age=0, must-revalidate\";\n\nexport const STATIC_CACHE_CONTROL = \"s-maxage=31536000, stale-while-revalidate\";\n\nconst STALE_REVALIDATE_CACHE_CONTROL = \"s-maxage=0, stale-while-revalidate\";\n\nexport const NO_STORE_CACHE_CONTROL = \"no-store, must-revalidate\";\n\n/**\n * Matches Next.js's `getCacheControlHeader` stale window semantics while\n * preserving vinext's legacy unbounded SWR header when no expire ceiling is\n * available yet.\n *\n * Next.js source:\n * https://github.com/vercel/next.js/blob/canary/packages/next/src/server/lib/cache-control.ts\n */\nexport function buildRevalidateCacheControl(\n revalidateSeconds: number,\n expireSeconds?: number,\n): string {\n if (expireSeconds === undefined) {\n return `s-maxage=${revalidateSeconds}, stale-while-revalidate`;\n }\n\n // `expire <= revalidate` is a zero-width stale window: downstream caches\n // should refetch after s-maxage instead of serving stale.\n if (revalidateSeconds >= expireSeconds) {\n return `s-maxage=${revalidateSeconds}`;\n }\n\n return `s-maxage=${revalidateSeconds}, stale-while-revalidate=${\n expireSeconds - revalidateSeconds\n }`;\n}\n\n/**\n * Builds Cache-Control for ISR cache reads. HIT responses and STALE responses\n * with stored expire metadata use the same route policy because Next.js derives\n * this header from cache-control metadata, not from the cache hit/stale state.\n * STALE entries without expire metadata keep vinext's legacy `s-maxage=0`\n * fallback so older cache entries are not treated as newly fresh downstream.\n */\nexport function buildCachedRevalidateCacheControl(\n cacheState: \"HIT\" | \"STALE\",\n revalidateSeconds: number,\n expireSeconds?: number,\n): string {\n // When expire is known, match Next.js and emit the route policy even for\n // vinext-served STALE entries. The hard-expire gate has already decided the\n // stale payload is still usable, and downstream caches should see the same\n // finite SWR window Next.js would emit from cacheControl metadata.\n if (cacheState === \"STALE\" && expireSeconds === undefined) {\n return STALE_REVALIDATE_CACHE_CONTROL;\n }\n\n return buildRevalidateCacheControl(revalidateSeconds, expireSeconds);\n}\n"],"mappings":";AAAA,MAAa,sBAAsB;AAEnC,MAAa,uBAAuB;AAEpC,MAAM,iCAAiC;AAEvC,MAAa,yBAAyB;;;;;;;;;AAUtC,SAAgB,4BACd,mBACA,eACQ;AACR,KAAI,kBAAkB,KAAA,EACpB,QAAO,YAAY,kBAAkB;AAKvC,KAAI,qBAAqB,cACvB,QAAO,YAAY;AAGrB,QAAO,YAAY,kBAAkB,2BACnC,gBAAgB;;;;;;;;;AAWpB,SAAgB,kCACd,YACA,mBACA,eACQ;AAKR,KAAI,eAAe,WAAW,kBAAkB,KAAA,EAC9C,QAAO;AAGT,QAAO,4BAA4B,mBAAmB,cAAc"}
1
+ {"version":3,"file":"cache-control.js","names":[],"sources":["../../src/server/cache-control.ts"],"sourcesContent":["export const NEVER_CACHE_CONTROL = \"private, no-cache, no-store, max-age=0, must-revalidate\";\n\nexport const STATIC_CACHE_CONTROL = \"s-maxage=31536000, stale-while-revalidate\";\n\nconst STALE_REVALIDATE_CACHE_CONTROL = \"s-maxage=0, stale-while-revalidate\";\n\nexport const NO_STORE_CACHE_CONTROL = \"no-store, must-revalidate\";\n\n/**\n * Matches Next.js's `getCacheControlHeader` stale window semantics while\n * preserving vinext's legacy unbounded SWR header when no expire ceiling is\n * available yet.\n *\n * Next.js source:\n * https://github.com/vercel/next.js/blob/canary/packages/next/src/server/lib/cache-control.ts\n */\nexport function buildRevalidateCacheControl(\n revalidateSeconds: number,\n expireSeconds?: number,\n): string {\n if (expireSeconds === undefined) {\n return `s-maxage=${revalidateSeconds}, stale-while-revalidate`;\n }\n\n // `expire <= revalidate` is a zero-width stale window: downstream caches\n // should refetch after s-maxage instead of serving stale.\n if (revalidateSeconds >= expireSeconds) {\n return `s-maxage=${revalidateSeconds}`;\n }\n\n return `s-maxage=${revalidateSeconds}, stale-while-revalidate=${\n expireSeconds - revalidateSeconds\n }`;\n}\n\n/**\n * Builds Cache-Control for ISR cache reads. HIT responses and STALE responses\n * with stored expire metadata use the same route policy because Next.js derives\n * this header from cache-control metadata, not from the cache hit/stale state.\n * STALE entries without expire metadata keep vinext's legacy `s-maxage=0`\n * fallback so older cache entries are not treated as newly fresh downstream.\n */\nexport function buildCachedRevalidateCacheControl(\n cacheState: \"HIT\" | \"STALE\",\n revalidateSeconds: number,\n expireSeconds?: number,\n): string {\n if (revalidateSeconds === Infinity) {\n return STATIC_CACHE_CONTROL;\n }\n\n // When expire is known, match Next.js and emit the route policy even for\n // vinext-served STALE entries. The hard-expire gate has already decided the\n // stale payload is still usable, and downstream caches should see the same\n // finite SWR window Next.js would emit from cacheControl metadata.\n if (cacheState === \"STALE\" && expireSeconds === undefined) {\n return STALE_REVALIDATE_CACHE_CONTROL;\n }\n\n return buildRevalidateCacheControl(revalidateSeconds, expireSeconds);\n}\n"],"mappings":";AAAA,MAAa,sBAAsB;AAEnC,MAAa,uBAAuB;AAEpC,MAAM,iCAAiC;AAEvC,MAAa,yBAAyB;;;;;;;;;AAUtC,SAAgB,4BACd,mBACA,eACQ;CACR,IAAI,kBAAkB,KAAA,GACpB,OAAO,YAAY,kBAAkB;CAKvC,IAAI,qBAAqB,eACvB,OAAO,YAAY;CAGrB,OAAO,YAAY,kBAAkB,2BACnC,gBAAgB;;;;;;;;;AAWpB,SAAgB,kCACd,YACA,mBACA,eACQ;CACR,IAAI,sBAAsB,UACxB,OAAO;CAOT,IAAI,eAAe,WAAW,kBAAkB,KAAA,GAC9C,OAAO;CAGT,OAAO,4BAA4B,mBAAmB,cAAc"}
@@ -1 +1 @@
1
- {"version":3,"file":"cache-proof.js","names":[],"sources":["../../src/server/cache-proof.ts"],"sourcesContent":["import type { AppRouteSemanticIds } from \"../routing/app-route-graph.js\";\nimport { fnv1a64 } from \"../utils/hash.js\";\n\nexport const CACHE_PROOF_MODEL_SCHEMA_VERSION = 0;\nexport type CacheProofModelSchemaVersion = 0;\n\nexport type CacheProofRejectionCode =\n | \"CP_MODEL_DISABLED\"\n | \"CP_DIMENSION_COUNT_EXCEEDED\"\n | \"CP_DIMENSION_NAME_MISSING\"\n | \"CP_DIMENSION_NAME_TOO_LONG\"\n | \"CP_DIMENSION_VALUE_COUNT_EXCEEDED\"\n | \"CP_DIMENSION_VALUE_TOO_LONG\"\n | \"CP_DIMENSION_VALUES_MISSING\"\n | \"CP_ENCODED_VARIANT_TOO_LONG\"\n | \"CP_INVALID_VARIANT_BUDGET\"\n | \"CP_ROUTE_VARIANT_CEILING_EXCEEDED\"\n | \"CP_UNSAFE_PUBLIC_DIMENSION\"\n | \"CP_BOUNDARY_OUTCOME_MISMATCH\"\n | \"CP_BOUNDARY_OUTCOME_UNKNOWN\";\n\nexport type CacheProofTraceFieldValue = string | number | boolean | null | readonly string[];\n\nexport type CacheProofTraceFields = Readonly<Record<string, CacheProofTraceFieldValue>>;\n\nexport type CacheProofBreakerFallbackMode = \"renderFresh\" | \"privateUncacheable\";\nexport type CacheProofFallbackScope = \"affectedOutput\" | \"route\";\n\nexport type CacheProofBreakerFallback = Readonly<{\n kind: \"breakerFallback\";\n code: CacheProofRejectionCode;\n mode: CacheProofBreakerFallbackMode;\n scope: CacheProofFallbackScope;\n fields: CacheProofTraceFields;\n}>;\n\nexport type CacheVariantBudget = Readonly<{\n maxDimensionCount: number;\n maxDimensionNameLength: number;\n maxDimensionValueLength: number;\n maxEncodedLength: number;\n maxValuesPerDimension: number;\n maxVariantsPerRoute: number;\n}>;\n\nexport const DEFAULT_CACHE_VARIANT_BUDGET = {\n maxDimensionCount: 8,\n maxDimensionNameLength: 64,\n maxDimensionValueLength: 256,\n maxEncodedLength: 1024,\n maxValuesPerDimension: 8,\n maxVariantsPerRoute: 64,\n} satisfies CacheVariantBudget;\n\nexport type CacheVariantDimensionSource =\n | \"auth\"\n | \"cookie\"\n | \"custom\"\n | \"draft-mode\"\n | \"header\"\n | \"interception\"\n | \"mounted-slots\"\n | \"params\"\n | \"route\"\n | \"search\"\n | \"session\";\n\nexport type CacheVariantDimensionPrivacy = \"internal\" | \"private\" | \"public\";\n\nexport type CacheVariantDimensionInput = Readonly<{\n name: string;\n privacy: CacheVariantDimensionPrivacy;\n source: CacheVariantDimensionSource;\n values: readonly string[];\n}>;\n\nexport type CacheVariantDimension = Readonly<{\n encoded: string;\n name: string;\n privacy: CacheVariantDimensionPrivacy;\n source: CacheVariantDimensionSource;\n valueCount: number;\n valueHashes: readonly string[];\n}>;\n\nexport type CacheProofOutputScope =\n | Readonly<{\n kind: \"app-html\";\n renderEpoch: string | null;\n rootBoundaryId: string | null;\n routeId: string;\n }>\n | Readonly<{\n kind: \"app-rsc\";\n mountedSlotsFingerprint: string | null;\n renderEpoch: string | null;\n rootBoundaryId: string | null;\n routeId: string;\n }>\n | Readonly<{\n kind: \"layout\";\n layoutId: string;\n rootBoundaryId: string | null;\n routeId: string;\n }>\n | Readonly<{\n kind: \"page\";\n pageId: string;\n rootBoundaryId: string | null;\n routeId: string;\n }>\n | Readonly<{\n kind: \"route-handler\";\n routeHandlerId: string;\n routeId: string;\n }>\n | Readonly<{\n kind: \"slot\";\n rootBoundaryId: string | null;\n routeId: string;\n slotId: string;\n }>\n | Readonly<{\n kind: \"template\";\n rootBoundaryId: string | null;\n routeId: string;\n templateId: string;\n }>;\n\nexport type CacheVariant = Readonly<{\n budget: CacheVariantBudget;\n cacheKey: string;\n dimensions: readonly CacheVariantDimension[];\n encodedLength: number;\n output: CacheProofOutputScope;\n schemaVersion: CacheProofModelSchemaVersion;\n}>;\n\nexport type BuildCacheVariantInput = Readonly<{\n budget: CacheVariantBudget;\n dimensions: readonly CacheVariantDimensionInput[];\n existingVariantCount: number;\n output: CacheProofOutputScope;\n}>;\n\nexport type BuildCacheVariantResult =\n | Readonly<{ kind: \"variant\"; variant: CacheVariant }>\n | Readonly<{ kind: \"breakerFallback\"; fallback: CacheProofBreakerFallback }>;\n\nexport type AppRouteCacheProofGraphScopeInput = Readonly<{\n ids: AppRouteSemanticIds;\n}>;\n\nexport type AppRouteCacheProofGraphScope = Readonly<{\n layoutIds: readonly string[];\n pageId: string | null;\n routeHandlerId: string | null;\n routeId: string;\n slotIds: readonly string[];\n templateIds: readonly string[];\n}>;\n\nexport type BoundaryOutcome =\n | Readonly<{ kind: \"error\"; digest?: string }>\n | Readonly<{ kind: \"forbidden\" }>\n | Readonly<{ kind: \"globalError\"; digest?: string }>\n | Readonly<{ kind: \"notFound\" }>\n | Readonly<{ kind: \"redirect\"; location: string; status: number }>\n | Readonly<{ kind: \"success\" }>\n | Readonly<{ kind: \"unauthorized\" }>\n | Readonly<{ kind: \"unknown\" }>;\n\nexport type BoundaryOutcomeCompatibility =\n | Readonly<{\n kind: \"compatible\";\n outcome: BoundaryOutcome;\n reason: \"CP_BOUNDARY_OUTCOME_MATCH\";\n }>\n | Readonly<{\n candidate: BoundaryOutcome;\n expected: BoundaryOutcome;\n fallback: CacheProofBreakerFallback;\n kind: \"incompatible\";\n }>;\n\nexport type RenderObservationCompleteness = \"complete\" | \"partial\" | \"unknown\";\nexport type RenderCacheability = \"private\" | \"public\" | \"uncacheable\" | \"unknown\";\nexport type RenderRequestApiKind =\n | \"connection\"\n | \"cookies\"\n | \"draftMode\"\n | \"headers\"\n | \"params\"\n | \"searchParams\";\nexport type RenderRequestApiStatus = \"notObserved\" | \"observed\" | \"unknown\";\n\nexport type RenderRequestApiObservation = Readonly<{\n kind: RenderRequestApiKind;\n status: RenderRequestApiStatus;\n}>;\n\nexport type RenderObservation = Readonly<{\n boundaryOutcome: BoundaryOutcome;\n cacheTags: readonly string[];\n cacheability: RenderCacheability;\n completeness: RenderObservationCompleteness;\n dynamicFetches: readonly string[];\n output: CacheProofOutputScope;\n pathTags: readonly string[];\n requestApis: readonly RenderRequestApiObservation[];\n schemaVersion: CacheProofModelSchemaVersion;\n}>;\n\nexport type BuildRenderObservationInput = Readonly<{\n boundaryOutcome: BoundaryOutcome;\n cacheTags: readonly string[];\n cacheability: RenderCacheability;\n completeness: RenderObservationCompleteness;\n dynamicFetches: readonly string[];\n output: CacheProofOutputScope;\n pathTags: readonly string[];\n requestApis: readonly RenderRequestApiObservation[];\n}>;\n\nexport type DisabledCacheProofDecision = Readonly<{\n canReuse: false;\n fallback: CacheProofBreakerFallback;\n kind: \"disabled\";\n observation: RenderObservation;\n variant: CacheVariant;\n}>;\n\nexport type CreateDisabledCacheProofDecisionInput = Readonly<{\n observation: RenderObservation;\n variant: CacheVariant;\n}>;\n\nconst PUBLIC_UNSAFE_DIMENSION_SOURCES: ReadonlySet<CacheVariantDimensionSource> = new Set([\n \"auth\",\n \"cookie\",\n \"draft-mode\",\n \"header\",\n \"session\",\n]);\n\ntype CacheVariantDimensionAccumulator = {\n name: string;\n privacy: CacheVariantDimensionPrivacy;\n source: CacheVariantDimensionSource;\n values: string[];\n};\n\ntype DimensionAccumulatorByName = Map<string, CacheVariantDimensionAccumulator>;\ntype DimensionAccumulatorByPrivacy = Map<CacheVariantDimensionPrivacy, DimensionAccumulatorByName>;\ntype DimensionAccumulatorBySource = Map<CacheVariantDimensionSource, DimensionAccumulatorByPrivacy>;\n\nfunction buildBreakerFallback(\n code: CacheProofRejectionCode,\n fields: CacheProofTraceFields = {},\n mode: CacheProofBreakerFallbackMode = \"renderFresh\",\n scope: CacheProofFallbackScope = \"affectedOutput\",\n): CacheProofBreakerFallback {\n return {\n kind: \"breakerFallback\",\n code,\n mode,\n scope,\n fields,\n };\n}\n\nfunction sortedUnique(values: readonly string[]): string[] {\n return [...new Set(values)].sort();\n}\n\nfunction normalizeDimensionName(name: string): string {\n return name.trim().toLowerCase();\n}\n\nfunction redactValue(value: string): string {\n return `h:${fnv1a64(value)}`;\n}\n\nfunction sortedUniqueRedacted(values: readonly string[]): string[] {\n return sortedUnique(sortedUnique(values).map(redactValue));\n}\n\nfunction encodeParts(parts: readonly unknown[]): string {\n return JSON.stringify(parts);\n}\n\nfunction compareDimensions(a: CacheVariantDimension, b: CacheVariantDimension): number {\n return (\n a.source.localeCompare(b.source) ||\n a.name.localeCompare(b.name) ||\n a.privacy.localeCompare(b.privacy)\n );\n}\n\nfunction encodeNullable(value: string | null): string | null {\n return value;\n}\n\nfunction assertNever(value: never): never {\n throw new Error(`Unhandled cache proof variant: ${String(value)}`);\n}\n\nfunction encodeOutputScope(output: CacheProofOutputScope): string {\n switch (output.kind) {\n case \"app-html\":\n return encodeParts([\n output.kind,\n output.routeId,\n encodeNullable(output.rootBoundaryId),\n encodeNullable(output.renderEpoch),\n ]);\n case \"app-rsc\":\n return encodeParts([\n output.kind,\n output.routeId,\n encodeNullable(output.rootBoundaryId),\n encodeNullable(output.renderEpoch),\n encodeNullable(output.mountedSlotsFingerprint),\n ]);\n case \"layout\":\n return encodeParts([\n output.kind,\n output.routeId,\n output.layoutId,\n encodeNullable(output.rootBoundaryId),\n ]);\n case \"page\":\n return encodeParts([\n output.kind,\n output.routeId,\n output.pageId,\n encodeNullable(output.rootBoundaryId),\n ]);\n case \"route-handler\":\n return encodeParts([output.kind, output.routeId, output.routeHandlerId]);\n case \"slot\":\n return encodeParts([\n output.kind,\n output.routeId,\n output.slotId,\n encodeNullable(output.rootBoundaryId),\n ]);\n case \"template\":\n return encodeParts([\n output.kind,\n output.routeId,\n output.templateId,\n encodeNullable(output.rootBoundaryId),\n ]);\n default:\n return assertNever(output);\n }\n}\n\nfunction validateBudgetNumber(name: string, value: number): CacheProofBreakerFallback | null {\n if (Number.isInteger(value) && value >= 0) return null;\n return buildBreakerFallback(\"CP_INVALID_VARIANT_BUDGET\", {\n budgetField: name,\n });\n}\n\nfunction validateBudget(budget: CacheVariantBudget): CacheProofBreakerFallback | null {\n return (\n validateBudgetNumber(\"maxDimensionCount\", budget.maxDimensionCount) ??\n validateBudgetNumber(\"maxDimensionNameLength\", budget.maxDimensionNameLength) ??\n validateBudgetNumber(\"maxDimensionValueLength\", budget.maxDimensionValueLength) ??\n validateBudgetNumber(\"maxEncodedLength\", budget.maxEncodedLength) ??\n validateBudgetNumber(\"maxValuesPerDimension\", budget.maxValuesPerDimension) ??\n validateBudgetNumber(\"maxVariantsPerRoute\", budget.maxVariantsPerRoute)\n );\n}\n\nfunction buildDimension(\n input: CacheVariantDimensionInput,\n budget: CacheVariantBudget,\n): CacheVariantDimension | CacheProofBreakerFallback {\n const name = normalizeDimensionName(input.name);\n if (name.length === 0) {\n return buildBreakerFallback(\"CP_DIMENSION_NAME_MISSING\", {\n source: input.source,\n });\n }\n if (name.length > budget.maxDimensionNameLength) {\n return buildBreakerFallback(\"CP_DIMENSION_NAME_TOO_LONG\", {\n maxLength: budget.maxDimensionNameLength,\n nameHash: redactValue(name),\n source: input.source,\n });\n }\n if (input.privacy === \"public\" && PUBLIC_UNSAFE_DIMENSION_SOURCES.has(input.source)) {\n return buildBreakerFallback(\n \"CP_UNSAFE_PUBLIC_DIMENSION\",\n {\n name,\n source: input.source,\n },\n \"privateUncacheable\",\n );\n }\n\n const values = sortedUnique(input.values);\n if (values.length === 0) {\n return buildBreakerFallback(\"CP_DIMENSION_VALUES_MISSING\", {\n name,\n source: input.source,\n });\n }\n if (values.length > budget.maxValuesPerDimension) {\n return buildBreakerFallback(\"CP_DIMENSION_VALUE_COUNT_EXCEEDED\", {\n maxValues: budget.maxValuesPerDimension,\n name,\n source: input.source,\n valueCount: values.length,\n });\n }\n for (const value of values) {\n if (value.length > budget.maxDimensionValueLength) {\n return buildBreakerFallback(\"CP_DIMENSION_VALUE_TOO_LONG\", {\n maxLength: budget.maxDimensionValueLength,\n name,\n source: input.source,\n valueHash: redactValue(value),\n });\n }\n }\n\n const valueHashes = values.map(redactValue);\n const encoded = encodeParts([input.source, input.privacy, name, valueHashes]);\n\n return {\n encoded,\n name,\n privacy: input.privacy,\n source: input.source,\n valueCount: valueHashes.length,\n valueHashes,\n };\n}\n\nfunction isCacheProofBreakerFallback(\n value: CacheVariantDimension | CacheProofBreakerFallback,\n): value is CacheProofBreakerFallback {\n return \"code\" in value;\n}\n\nfunction getDimensionBucket(\n bySource: DimensionAccumulatorBySource,\n source: CacheVariantDimensionSource,\n privacy: CacheVariantDimensionPrivacy,\n): DimensionAccumulatorByName {\n const existingByPrivacy = bySource.get(source);\n const byPrivacy = existingByPrivacy ?? new Map();\n if (!existingByPrivacy) {\n bySource.set(source, byPrivacy);\n }\n\n const existingByName = byPrivacy.get(privacy);\n const byName = existingByName ?? new Map();\n if (!existingByName) {\n byPrivacy.set(privacy, byName);\n }\n\n return byName;\n}\n\nfunction mergeDimensionInputs(\n dimensions: readonly CacheVariantDimensionInput[],\n): CacheVariantDimensionInput[] {\n const bySource: DimensionAccumulatorBySource = new Map();\n const orderedDimensions: CacheVariantDimensionAccumulator[] = [];\n\n for (const dimension of dimensions) {\n const name = normalizeDimensionName(dimension.name);\n const bucket = getDimensionBucket(bySource, dimension.source, dimension.privacy);\n const existing = bucket.get(name);\n if (existing) {\n existing.values.push(...dimension.values);\n continue;\n }\n const accumulator = {\n name,\n privacy: dimension.privacy,\n source: dimension.source,\n values: [...dimension.values],\n };\n bucket.set(name, accumulator);\n orderedDimensions.push(accumulator);\n }\n\n return orderedDimensions;\n}\n\nexport function createAppRouteCacheProofGraphScope(\n route: AppRouteCacheProofGraphScopeInput,\n): AppRouteCacheProofGraphScope {\n return {\n routeId: route.ids.route,\n pageId: route.ids.page,\n routeHandlerId: route.ids.routeHandler,\n layoutIds: [...route.ids.layouts],\n templateIds: [...route.ids.templates],\n slotIds: sortedUnique(Object.values(route.ids.slots)),\n };\n}\n\nexport function buildCacheVariant(input: BuildCacheVariantInput): BuildCacheVariantResult {\n const budgetFallback = validateBudget(input.budget);\n if (budgetFallback) {\n return {\n kind: \"breakerFallback\",\n fallback: budgetFallback,\n };\n }\n if (input.existingVariantCount >= input.budget.maxVariantsPerRoute) {\n return {\n kind: \"breakerFallback\",\n fallback: buildBreakerFallback(\n \"CP_ROUTE_VARIANT_CEILING_EXCEEDED\",\n {\n existingVariantCount: input.existingVariantCount,\n maxVariantsPerRoute: input.budget.maxVariantsPerRoute,\n routeId: input.output.routeId,\n },\n \"privateUncacheable\",\n \"route\",\n ),\n };\n }\n const dimensionInputs = mergeDimensionInputs(input.dimensions);\n if (dimensionInputs.length > input.budget.maxDimensionCount) {\n return {\n kind: \"breakerFallback\",\n fallback: buildBreakerFallback(\"CP_DIMENSION_COUNT_EXCEEDED\", {\n dimensionCount: dimensionInputs.length,\n maxDimensionCount: input.budget.maxDimensionCount,\n routeId: input.output.routeId,\n }),\n };\n }\n\n const dimensions: CacheVariantDimension[] = [];\n for (const dimensionInput of dimensionInputs) {\n const dimension = buildDimension(dimensionInput, input.budget);\n if (isCacheProofBreakerFallback(dimension)) {\n return {\n kind: \"breakerFallback\",\n fallback: dimension,\n };\n }\n dimensions.push(dimension);\n }\n dimensions.sort(compareDimensions);\n\n const encoded = [\n `schema:${CACHE_PROOF_MODEL_SCHEMA_VERSION}`,\n encodeOutputScope(input.output),\n ...dimensions.map((dimension) => dimension.encoded),\n ].join(\"|\");\n\n if (encoded.length > input.budget.maxEncodedLength) {\n return {\n kind: \"breakerFallback\",\n fallback: buildBreakerFallback(\"CP_ENCODED_VARIANT_TOO_LONG\", {\n encodedHash: redactValue(encoded),\n encodedLength: encoded.length,\n maxEncodedLength: input.budget.maxEncodedLength,\n routeId: input.output.routeId,\n }),\n };\n }\n\n return {\n kind: \"variant\",\n variant: {\n schemaVersion: CACHE_PROOF_MODEL_SCHEMA_VERSION,\n cacheKey: `cp0:${fnv1a64(encoded)}`,\n output: input.output,\n dimensions,\n encodedLength: encoded.length,\n budget: { ...input.budget },\n },\n };\n}\n\nfunction boundaryOutcomesMatch(expected: BoundaryOutcome, candidate: BoundaryOutcome): boolean {\n switch (expected.kind) {\n case \"error\":\n return candidate.kind === \"error\" && (expected.digest ?? \"\") === (candidate.digest ?? \"\");\n case \"forbidden\":\n return candidate.kind === \"forbidden\";\n case \"globalError\":\n return (\n candidate.kind === \"globalError\" && (expected.digest ?? \"\") === (candidate.digest ?? \"\")\n );\n case \"notFound\":\n return candidate.kind === \"notFound\";\n case \"redirect\":\n return (\n candidate.kind === \"redirect\" &&\n expected.status === candidate.status &&\n expected.location === candidate.location\n );\n case \"success\":\n return candidate.kind === \"success\";\n case \"unauthorized\":\n return candidate.kind === \"unauthorized\";\n case \"unknown\":\n return false;\n default:\n return assertNever(expected);\n }\n}\n\nexport function buildBoundaryOutcomeCompatibility(input: {\n candidate: BoundaryOutcome;\n expected: BoundaryOutcome;\n}): BoundaryOutcomeCompatibility {\n if (input.expected.kind === \"unknown\" || input.candidate.kind === \"unknown\") {\n return {\n kind: \"incompatible\",\n expected: input.expected,\n candidate: input.candidate,\n fallback: buildBreakerFallback(\"CP_BOUNDARY_OUTCOME_UNKNOWN\", {\n candidateKind: input.candidate.kind,\n expectedKind: input.expected.kind,\n }),\n };\n }\n\n if (boundaryOutcomesMatch(input.expected, input.candidate)) {\n return {\n kind: \"compatible\",\n outcome: input.candidate,\n reason: \"CP_BOUNDARY_OUTCOME_MATCH\",\n };\n }\n\n return {\n kind: \"incompatible\",\n expected: input.expected,\n candidate: input.candidate,\n fallback: buildBreakerFallback(\"CP_BOUNDARY_OUTCOME_MISMATCH\", {\n candidateKind: input.candidate.kind,\n expectedKind: input.expected.kind,\n }),\n };\n}\n\nfunction requestApiStatusRank(status: RenderRequestApiStatus): number {\n switch (status) {\n case \"notObserved\":\n return 0;\n case \"unknown\":\n return 1;\n case \"observed\":\n return 2;\n default:\n return assertNever(status);\n }\n}\n\nfunction normalizeRequestApiObservations(\n observations: readonly RenderRequestApiObservation[],\n): RenderRequestApiObservation[] {\n const byKind = new Map<RenderRequestApiKind, RenderRequestApiStatus>();\n for (const observation of observations) {\n const current = byKind.get(observation.kind);\n if (\n current === undefined ||\n requestApiStatusRank(observation.status) > requestApiStatusRank(current)\n ) {\n byKind.set(observation.kind, observation.status);\n }\n }\n\n return [...byKind.entries()]\n .sort(([left], [right]) => left.localeCompare(right))\n .map(([kind, status]) => ({ kind, status }));\n}\n\nexport function buildRenderObservation(input: BuildRenderObservationInput): RenderObservation {\n return {\n schemaVersion: CACHE_PROOF_MODEL_SCHEMA_VERSION,\n output: input.output,\n completeness: input.completeness,\n boundaryOutcome: input.boundaryOutcome,\n requestApis: normalizeRequestApiObservations(input.requestApis),\n dynamicFetches: sortedUniqueRedacted(input.dynamicFetches),\n cacheTags: sortedUnique(input.cacheTags),\n pathTags: sortedUnique(input.pathTags),\n cacheability: input.cacheability,\n };\n}\n\nexport function hasCompleteNegativeRequestApiProof(\n observation: RenderObservation,\n requiredApis: readonly RenderRequestApiKind[],\n): boolean {\n if (observation.completeness !== \"complete\") return false;\n\n const statuses = new Map<RenderRequestApiKind, RenderRequestApiStatus>();\n for (const requestApi of observation.requestApis) {\n statuses.set(requestApi.kind, requestApi.status);\n }\n\n for (const api of requiredApis) {\n if (statuses.get(api) !== \"notObserved\") return false;\n }\n return true;\n}\n\nexport function createDisabledCacheProofDecision(\n input: CreateDisabledCacheProofDecisionInput,\n): DisabledCacheProofDecision {\n return {\n kind: \"disabled\",\n canReuse: false,\n variant: input.variant,\n observation: input.observation,\n fallback: buildBreakerFallback(\"CP_MODEL_DISABLED\"),\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"cache-proof.js","names":[],"sources":["../../src/server/cache-proof.ts"],"sourcesContent":["import type { AppRouteSemanticIds } from \"../routing/app-route-graph.js\";\nimport { fnv1a64 } from \"../utils/hash.js\";\n\nexport const CACHE_PROOF_MODEL_SCHEMA_VERSION = 0;\nexport type CacheProofModelSchemaVersion = 0;\n\nexport type CacheProofRejectionCode =\n | \"CP_MODEL_DISABLED\"\n | \"CP_DIMENSION_COUNT_EXCEEDED\"\n | \"CP_DIMENSION_NAME_MISSING\"\n | \"CP_DIMENSION_NAME_TOO_LONG\"\n | \"CP_DIMENSION_VALUE_COUNT_EXCEEDED\"\n | \"CP_DIMENSION_VALUE_TOO_LONG\"\n | \"CP_DIMENSION_VALUES_MISSING\"\n | \"CP_ENCODED_VARIANT_TOO_LONG\"\n | \"CP_INVALID_VARIANT_BUDGET\"\n | \"CP_ROUTE_VARIANT_CEILING_EXCEEDED\"\n | \"CP_UNSAFE_PUBLIC_DIMENSION\"\n | \"CP_BOUNDARY_OUTCOME_MISMATCH\"\n | \"CP_BOUNDARY_OUTCOME_UNKNOWN\";\n\nexport type CacheProofTraceFieldValue = string | number | boolean | null | readonly string[];\n\nexport type CacheProofTraceFields = Readonly<Record<string, CacheProofTraceFieldValue>>;\n\nexport type CacheProofBreakerFallbackMode = \"renderFresh\" | \"privateUncacheable\";\nexport type CacheProofFallbackScope = \"affectedOutput\" | \"route\";\n\nexport type CacheProofBreakerFallback = Readonly<{\n kind: \"breakerFallback\";\n code: CacheProofRejectionCode;\n mode: CacheProofBreakerFallbackMode;\n scope: CacheProofFallbackScope;\n fields: CacheProofTraceFields;\n}>;\n\nexport type CacheVariantBudget = Readonly<{\n maxDimensionCount: number;\n maxDimensionNameLength: number;\n maxDimensionValueLength: number;\n maxEncodedLength: number;\n maxValuesPerDimension: number;\n maxVariantsPerRoute: number;\n}>;\n\nexport const DEFAULT_CACHE_VARIANT_BUDGET = {\n maxDimensionCount: 8,\n maxDimensionNameLength: 64,\n maxDimensionValueLength: 256,\n maxEncodedLength: 1024,\n maxValuesPerDimension: 8,\n maxVariantsPerRoute: 64,\n} satisfies CacheVariantBudget;\n\nexport type CacheVariantDimensionSource =\n | \"auth\"\n | \"cookie\"\n | \"custom\"\n | \"draft-mode\"\n | \"header\"\n | \"interception\"\n | \"mounted-slots\"\n | \"params\"\n | \"route\"\n | \"search\"\n | \"session\";\n\nexport type CacheVariantDimensionPrivacy = \"internal\" | \"private\" | \"public\";\n\nexport type CacheVariantDimensionInput = Readonly<{\n name: string;\n privacy: CacheVariantDimensionPrivacy;\n source: CacheVariantDimensionSource;\n values: readonly string[];\n}>;\n\nexport type CacheVariantDimension = Readonly<{\n encoded: string;\n name: string;\n privacy: CacheVariantDimensionPrivacy;\n source: CacheVariantDimensionSource;\n valueCount: number;\n valueHashes: readonly string[];\n}>;\n\nexport type CacheProofOutputScope =\n | Readonly<{\n kind: \"app-html\";\n renderEpoch: string | null;\n rootBoundaryId: string | null;\n routeId: string;\n }>\n | Readonly<{\n kind: \"app-rsc\";\n mountedSlotsFingerprint: string | null;\n renderEpoch: string | null;\n rootBoundaryId: string | null;\n routeId: string;\n }>\n | Readonly<{\n kind: \"layout\";\n layoutId: string;\n rootBoundaryId: string | null;\n routeId: string;\n }>\n | Readonly<{\n kind: \"page\";\n pageId: string;\n rootBoundaryId: string | null;\n routeId: string;\n }>\n | Readonly<{\n kind: \"route-handler\";\n routeHandlerId: string;\n routeId: string;\n }>\n | Readonly<{\n kind: \"slot\";\n rootBoundaryId: string | null;\n routeId: string;\n slotId: string;\n }>\n | Readonly<{\n kind: \"template\";\n rootBoundaryId: string | null;\n routeId: string;\n templateId: string;\n }>;\n\nexport type CacheVariant = Readonly<{\n budget: CacheVariantBudget;\n cacheKey: string;\n dimensions: readonly CacheVariantDimension[];\n encodedLength: number;\n output: CacheProofOutputScope;\n schemaVersion: CacheProofModelSchemaVersion;\n}>;\n\nexport type BuildCacheVariantInput = Readonly<{\n budget: CacheVariantBudget;\n dimensions: readonly CacheVariantDimensionInput[];\n existingVariantCount: number;\n output: CacheProofOutputScope;\n}>;\n\nexport type BuildCacheVariantResult =\n | Readonly<{ kind: \"variant\"; variant: CacheVariant }>\n | Readonly<{ kind: \"breakerFallback\"; fallback: CacheProofBreakerFallback }>;\n\nexport type AppRouteCacheProofGraphScopeInput = Readonly<{\n ids: AppRouteSemanticIds;\n}>;\n\nexport type AppRouteCacheProofGraphScope = Readonly<{\n layoutIds: readonly string[];\n pageId: string | null;\n routeHandlerId: string | null;\n routeId: string;\n slotIds: readonly string[];\n templateIds: readonly string[];\n}>;\n\nexport type BoundaryOutcome =\n | Readonly<{ kind: \"error\"; digest?: string }>\n | Readonly<{ kind: \"forbidden\" }>\n | Readonly<{ kind: \"globalError\"; digest?: string }>\n | Readonly<{ kind: \"notFound\" }>\n | Readonly<{ kind: \"redirect\"; location: string; status: number }>\n | Readonly<{ kind: \"success\" }>\n | Readonly<{ kind: \"unauthorized\" }>\n | Readonly<{ kind: \"unknown\" }>;\n\nexport type BoundaryOutcomeCompatibility =\n | Readonly<{\n kind: \"compatible\";\n outcome: BoundaryOutcome;\n reason: \"CP_BOUNDARY_OUTCOME_MATCH\";\n }>\n | Readonly<{\n candidate: BoundaryOutcome;\n expected: BoundaryOutcome;\n fallback: CacheProofBreakerFallback;\n kind: \"incompatible\";\n }>;\n\nexport type RenderObservationCompleteness = \"complete\" | \"partial\" | \"unknown\";\nexport type RenderCacheability = \"private\" | \"public\" | \"uncacheable\" | \"unknown\";\nexport type RenderRequestApiKind =\n | \"connection\"\n | \"cookies\"\n | \"draftMode\"\n | \"headers\"\n | \"params\"\n | \"searchParams\";\nexport type RenderRequestApiStatus = \"notObserved\" | \"observed\" | \"unknown\";\n\nexport type RenderRequestApiObservation = Readonly<{\n kind: RenderRequestApiKind;\n status: RenderRequestApiStatus;\n}>;\n\nexport type RenderObservation = Readonly<{\n boundaryOutcome: BoundaryOutcome;\n cacheTags: readonly string[];\n cacheability: RenderCacheability;\n completeness: RenderObservationCompleteness;\n dynamicFetches: readonly string[];\n output: CacheProofOutputScope;\n pathTags: readonly string[];\n requestApis: readonly RenderRequestApiObservation[];\n schemaVersion: CacheProofModelSchemaVersion;\n}>;\n\nexport type BuildRenderObservationInput = Readonly<{\n boundaryOutcome: BoundaryOutcome;\n cacheTags: readonly string[];\n cacheability: RenderCacheability;\n completeness: RenderObservationCompleteness;\n dynamicFetches: readonly string[];\n output: CacheProofOutputScope;\n pathTags: readonly string[];\n requestApis: readonly RenderRequestApiObservation[];\n}>;\n\nexport type DisabledCacheProofDecision = Readonly<{\n canReuse: false;\n fallback: CacheProofBreakerFallback;\n kind: \"disabled\";\n observation: RenderObservation;\n variant: CacheVariant;\n}>;\n\nexport type CreateDisabledCacheProofDecisionInput = Readonly<{\n observation: RenderObservation;\n variant: CacheVariant;\n}>;\n\nconst PUBLIC_UNSAFE_DIMENSION_SOURCES: ReadonlySet<CacheVariantDimensionSource> = new Set([\n \"auth\",\n \"cookie\",\n \"draft-mode\",\n \"header\",\n \"session\",\n]);\n\ntype CacheVariantDimensionAccumulator = {\n name: string;\n privacy: CacheVariantDimensionPrivacy;\n source: CacheVariantDimensionSource;\n values: string[];\n};\n\ntype DimensionAccumulatorByName = Map<string, CacheVariantDimensionAccumulator>;\ntype DimensionAccumulatorByPrivacy = Map<CacheVariantDimensionPrivacy, DimensionAccumulatorByName>;\ntype DimensionAccumulatorBySource = Map<CacheVariantDimensionSource, DimensionAccumulatorByPrivacy>;\n\nfunction buildBreakerFallback(\n code: CacheProofRejectionCode,\n fields: CacheProofTraceFields = {},\n mode: CacheProofBreakerFallbackMode = \"renderFresh\",\n scope: CacheProofFallbackScope = \"affectedOutput\",\n): CacheProofBreakerFallback {\n return {\n kind: \"breakerFallback\",\n code,\n mode,\n scope,\n fields,\n };\n}\n\nfunction sortedUnique(values: readonly string[]): string[] {\n return [...new Set(values)].sort();\n}\n\nfunction normalizeDimensionName(name: string): string {\n return name.trim().toLowerCase();\n}\n\nfunction redactValue(value: string): string {\n return `h:${fnv1a64(value)}`;\n}\n\nfunction sortedUniqueRedacted(values: readonly string[]): string[] {\n return sortedUnique(sortedUnique(values).map(redactValue));\n}\n\nfunction encodeParts(parts: readonly unknown[]): string {\n return JSON.stringify(parts);\n}\n\nfunction compareDimensions(a: CacheVariantDimension, b: CacheVariantDimension): number {\n return (\n a.source.localeCompare(b.source) ||\n a.name.localeCompare(b.name) ||\n a.privacy.localeCompare(b.privacy)\n );\n}\n\nfunction encodeNullable(value: string | null): string | null {\n return value;\n}\n\nfunction assertNever(value: never): never {\n throw new Error(`Unhandled cache proof variant: ${String(value)}`);\n}\n\nfunction encodeOutputScope(output: CacheProofOutputScope): string {\n switch (output.kind) {\n case \"app-html\":\n return encodeParts([\n output.kind,\n output.routeId,\n encodeNullable(output.rootBoundaryId),\n encodeNullable(output.renderEpoch),\n ]);\n case \"app-rsc\":\n return encodeParts([\n output.kind,\n output.routeId,\n encodeNullable(output.rootBoundaryId),\n encodeNullable(output.renderEpoch),\n encodeNullable(output.mountedSlotsFingerprint),\n ]);\n case \"layout\":\n return encodeParts([\n output.kind,\n output.routeId,\n output.layoutId,\n encodeNullable(output.rootBoundaryId),\n ]);\n case \"page\":\n return encodeParts([\n output.kind,\n output.routeId,\n output.pageId,\n encodeNullable(output.rootBoundaryId),\n ]);\n case \"route-handler\":\n return encodeParts([output.kind, output.routeId, output.routeHandlerId]);\n case \"slot\":\n return encodeParts([\n output.kind,\n output.routeId,\n output.slotId,\n encodeNullable(output.rootBoundaryId),\n ]);\n case \"template\":\n return encodeParts([\n output.kind,\n output.routeId,\n output.templateId,\n encodeNullable(output.rootBoundaryId),\n ]);\n default:\n return assertNever(output);\n }\n}\n\nfunction validateBudgetNumber(name: string, value: number): CacheProofBreakerFallback | null {\n if (Number.isInteger(value) && value >= 0) return null;\n return buildBreakerFallback(\"CP_INVALID_VARIANT_BUDGET\", {\n budgetField: name,\n });\n}\n\nfunction validateBudget(budget: CacheVariantBudget): CacheProofBreakerFallback | null {\n return (\n validateBudgetNumber(\"maxDimensionCount\", budget.maxDimensionCount) ??\n validateBudgetNumber(\"maxDimensionNameLength\", budget.maxDimensionNameLength) ??\n validateBudgetNumber(\"maxDimensionValueLength\", budget.maxDimensionValueLength) ??\n validateBudgetNumber(\"maxEncodedLength\", budget.maxEncodedLength) ??\n validateBudgetNumber(\"maxValuesPerDimension\", budget.maxValuesPerDimension) ??\n validateBudgetNumber(\"maxVariantsPerRoute\", budget.maxVariantsPerRoute)\n );\n}\n\nfunction buildDimension(\n input: CacheVariantDimensionInput,\n budget: CacheVariantBudget,\n): CacheVariantDimension | CacheProofBreakerFallback {\n const name = normalizeDimensionName(input.name);\n if (name.length === 0) {\n return buildBreakerFallback(\"CP_DIMENSION_NAME_MISSING\", {\n source: input.source,\n });\n }\n if (name.length > budget.maxDimensionNameLength) {\n return buildBreakerFallback(\"CP_DIMENSION_NAME_TOO_LONG\", {\n maxLength: budget.maxDimensionNameLength,\n nameHash: redactValue(name),\n source: input.source,\n });\n }\n if (input.privacy === \"public\" && PUBLIC_UNSAFE_DIMENSION_SOURCES.has(input.source)) {\n return buildBreakerFallback(\n \"CP_UNSAFE_PUBLIC_DIMENSION\",\n {\n name,\n source: input.source,\n },\n \"privateUncacheable\",\n );\n }\n\n const values = sortedUnique(input.values);\n if (values.length === 0) {\n return buildBreakerFallback(\"CP_DIMENSION_VALUES_MISSING\", {\n name,\n source: input.source,\n });\n }\n if (values.length > budget.maxValuesPerDimension) {\n return buildBreakerFallback(\"CP_DIMENSION_VALUE_COUNT_EXCEEDED\", {\n maxValues: budget.maxValuesPerDimension,\n name,\n source: input.source,\n valueCount: values.length,\n });\n }\n for (const value of values) {\n if (value.length > budget.maxDimensionValueLength) {\n return buildBreakerFallback(\"CP_DIMENSION_VALUE_TOO_LONG\", {\n maxLength: budget.maxDimensionValueLength,\n name,\n source: input.source,\n valueHash: redactValue(value),\n });\n }\n }\n\n const valueHashes = values.map(redactValue);\n const encoded = encodeParts([input.source, input.privacy, name, valueHashes]);\n\n return {\n encoded,\n name,\n privacy: input.privacy,\n source: input.source,\n valueCount: valueHashes.length,\n valueHashes,\n };\n}\n\nfunction isCacheProofBreakerFallback(\n value: CacheVariantDimension | CacheProofBreakerFallback,\n): value is CacheProofBreakerFallback {\n return \"code\" in value;\n}\n\nfunction getDimensionBucket(\n bySource: DimensionAccumulatorBySource,\n source: CacheVariantDimensionSource,\n privacy: CacheVariantDimensionPrivacy,\n): DimensionAccumulatorByName {\n const existingByPrivacy = bySource.get(source);\n const byPrivacy = existingByPrivacy ?? new Map();\n if (!existingByPrivacy) {\n bySource.set(source, byPrivacy);\n }\n\n const existingByName = byPrivacy.get(privacy);\n const byName = existingByName ?? new Map();\n if (!existingByName) {\n byPrivacy.set(privacy, byName);\n }\n\n return byName;\n}\n\nfunction mergeDimensionInputs(\n dimensions: readonly CacheVariantDimensionInput[],\n): CacheVariantDimensionInput[] {\n const bySource: DimensionAccumulatorBySource = new Map();\n const orderedDimensions: CacheVariantDimensionAccumulator[] = [];\n\n for (const dimension of dimensions) {\n const name = normalizeDimensionName(dimension.name);\n const bucket = getDimensionBucket(bySource, dimension.source, dimension.privacy);\n const existing = bucket.get(name);\n if (existing) {\n existing.values.push(...dimension.values);\n continue;\n }\n const accumulator = {\n name,\n privacy: dimension.privacy,\n source: dimension.source,\n values: [...dimension.values],\n };\n bucket.set(name, accumulator);\n orderedDimensions.push(accumulator);\n }\n\n return orderedDimensions;\n}\n\nexport function createAppRouteCacheProofGraphScope(\n route: AppRouteCacheProofGraphScopeInput,\n): AppRouteCacheProofGraphScope {\n return {\n routeId: route.ids.route,\n pageId: route.ids.page,\n routeHandlerId: route.ids.routeHandler,\n layoutIds: [...route.ids.layouts],\n templateIds: [...route.ids.templates],\n slotIds: sortedUnique(Object.values(route.ids.slots)),\n };\n}\n\nexport function buildCacheVariant(input: BuildCacheVariantInput): BuildCacheVariantResult {\n const budgetFallback = validateBudget(input.budget);\n if (budgetFallback) {\n return {\n kind: \"breakerFallback\",\n fallback: budgetFallback,\n };\n }\n if (input.existingVariantCount >= input.budget.maxVariantsPerRoute) {\n return {\n kind: \"breakerFallback\",\n fallback: buildBreakerFallback(\n \"CP_ROUTE_VARIANT_CEILING_EXCEEDED\",\n {\n existingVariantCount: input.existingVariantCount,\n maxVariantsPerRoute: input.budget.maxVariantsPerRoute,\n routeId: input.output.routeId,\n },\n \"privateUncacheable\",\n \"route\",\n ),\n };\n }\n const dimensionInputs = mergeDimensionInputs(input.dimensions);\n if (dimensionInputs.length > input.budget.maxDimensionCount) {\n return {\n kind: \"breakerFallback\",\n fallback: buildBreakerFallback(\"CP_DIMENSION_COUNT_EXCEEDED\", {\n dimensionCount: dimensionInputs.length,\n maxDimensionCount: input.budget.maxDimensionCount,\n routeId: input.output.routeId,\n }),\n };\n }\n\n const dimensions: CacheVariantDimension[] = [];\n for (const dimensionInput of dimensionInputs) {\n const dimension = buildDimension(dimensionInput, input.budget);\n if (isCacheProofBreakerFallback(dimension)) {\n return {\n kind: \"breakerFallback\",\n fallback: dimension,\n };\n }\n dimensions.push(dimension);\n }\n dimensions.sort(compareDimensions);\n\n const encoded = [\n `schema:${CACHE_PROOF_MODEL_SCHEMA_VERSION}`,\n encodeOutputScope(input.output),\n ...dimensions.map((dimension) => dimension.encoded),\n ].join(\"|\");\n\n if (encoded.length > input.budget.maxEncodedLength) {\n return {\n kind: \"breakerFallback\",\n fallback: buildBreakerFallback(\"CP_ENCODED_VARIANT_TOO_LONG\", {\n encodedHash: redactValue(encoded),\n encodedLength: encoded.length,\n maxEncodedLength: input.budget.maxEncodedLength,\n routeId: input.output.routeId,\n }),\n };\n }\n\n return {\n kind: \"variant\",\n variant: {\n schemaVersion: CACHE_PROOF_MODEL_SCHEMA_VERSION,\n cacheKey: `cp0:${fnv1a64(encoded)}`,\n output: input.output,\n dimensions,\n encodedLength: encoded.length,\n budget: { ...input.budget },\n },\n };\n}\n\nfunction boundaryOutcomesMatch(expected: BoundaryOutcome, candidate: BoundaryOutcome): boolean {\n switch (expected.kind) {\n case \"error\":\n return candidate.kind === \"error\" && (expected.digest ?? \"\") === (candidate.digest ?? \"\");\n case \"forbidden\":\n return candidate.kind === \"forbidden\";\n case \"globalError\":\n return (\n candidate.kind === \"globalError\" && (expected.digest ?? \"\") === (candidate.digest ?? \"\")\n );\n case \"notFound\":\n return candidate.kind === \"notFound\";\n case \"redirect\":\n return (\n candidate.kind === \"redirect\" &&\n expected.status === candidate.status &&\n expected.location === candidate.location\n );\n case \"success\":\n return candidate.kind === \"success\";\n case \"unauthorized\":\n return candidate.kind === \"unauthorized\";\n case \"unknown\":\n return false;\n default:\n return assertNever(expected);\n }\n}\n\nexport function buildBoundaryOutcomeCompatibility(input: {\n candidate: BoundaryOutcome;\n expected: BoundaryOutcome;\n}): BoundaryOutcomeCompatibility {\n if (input.expected.kind === \"unknown\" || input.candidate.kind === \"unknown\") {\n return {\n kind: \"incompatible\",\n expected: input.expected,\n candidate: input.candidate,\n fallback: buildBreakerFallback(\"CP_BOUNDARY_OUTCOME_UNKNOWN\", {\n candidateKind: input.candidate.kind,\n expectedKind: input.expected.kind,\n }),\n };\n }\n\n if (boundaryOutcomesMatch(input.expected, input.candidate)) {\n return {\n kind: \"compatible\",\n outcome: input.candidate,\n reason: \"CP_BOUNDARY_OUTCOME_MATCH\",\n };\n }\n\n return {\n kind: \"incompatible\",\n expected: input.expected,\n candidate: input.candidate,\n fallback: buildBreakerFallback(\"CP_BOUNDARY_OUTCOME_MISMATCH\", {\n candidateKind: input.candidate.kind,\n expectedKind: input.expected.kind,\n }),\n };\n}\n\nfunction requestApiStatusRank(status: RenderRequestApiStatus): number {\n switch (status) {\n case \"notObserved\":\n return 0;\n case \"unknown\":\n return 1;\n case \"observed\":\n return 2;\n default:\n return assertNever(status);\n }\n}\n\nfunction normalizeRequestApiObservations(\n observations: readonly RenderRequestApiObservation[],\n): RenderRequestApiObservation[] {\n const byKind = new Map<RenderRequestApiKind, RenderRequestApiStatus>();\n for (const observation of observations) {\n const current = byKind.get(observation.kind);\n if (\n current === undefined ||\n requestApiStatusRank(observation.status) > requestApiStatusRank(current)\n ) {\n byKind.set(observation.kind, observation.status);\n }\n }\n\n return [...byKind.entries()]\n .sort(([left], [right]) => left.localeCompare(right))\n .map(([kind, status]) => ({ kind, status }));\n}\n\nexport function buildRenderObservation(input: BuildRenderObservationInput): RenderObservation {\n return {\n schemaVersion: CACHE_PROOF_MODEL_SCHEMA_VERSION,\n output: input.output,\n completeness: input.completeness,\n boundaryOutcome: input.boundaryOutcome,\n requestApis: normalizeRequestApiObservations(input.requestApis),\n dynamicFetches: sortedUniqueRedacted(input.dynamicFetches),\n cacheTags: sortedUnique(input.cacheTags),\n pathTags: sortedUnique(input.pathTags),\n cacheability: input.cacheability,\n };\n}\n\nexport function hasCompleteNegativeRequestApiProof(\n observation: RenderObservation,\n requiredApis: readonly RenderRequestApiKind[],\n): boolean {\n if (observation.completeness !== \"complete\") return false;\n\n const statuses = new Map<RenderRequestApiKind, RenderRequestApiStatus>();\n for (const requestApi of observation.requestApis) {\n statuses.set(requestApi.kind, requestApi.status);\n }\n\n for (const api of requiredApis) {\n if (statuses.get(api) !== \"notObserved\") return false;\n }\n return true;\n}\n\nexport function createDisabledCacheProofDecision(\n input: CreateDisabledCacheProofDecisionInput,\n): DisabledCacheProofDecision {\n return {\n kind: \"disabled\",\n canReuse: false,\n variant: input.variant,\n observation: input.observation,\n fallback: buildBreakerFallback(\"CP_MODEL_DISABLED\"),\n };\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"csp.js","names":[],"sources":["../../src/server/csp.ts"],"sourcesContent":["import type { IncomingHttpHeaders, OutgoingHttpHeaders } from \"node:http\";\n\nconst ESCAPE_REGEX = /[&><\\u2028\\u2029]/;\ntype NodeHeaders = IncomingHttpHeaders | OutgoingHttpHeaders;\n\nfunction matchesDirectiveName(directive: string, name: string): boolean {\n return directive === name || directive.startsWith(`${name} `);\n}\n\nfunction getNodeHeaderValue(\n headers: NodeHeaders | null | undefined,\n key: \"content-security-policy\" | \"content-security-policy-report-only\",\n): string | undefined {\n const value = headers?.[key];\n if (Array.isArray(value)) {\n return value.join(\", \");\n }\n if (value == null) {\n return undefined;\n }\n return String(value);\n}\n\nexport function getScriptNonceFromHeader(cspHeaderValue: string): string | undefined {\n const directives = cspHeaderValue.split(\";\").map((directive) => directive.trim());\n\n const directive =\n directives.find((value) => matchesDirectiveName(value, \"script-src\")) ??\n directives.find((value) => matchesDirectiveName(value, \"default-src\"));\n\n if (!directive) {\n return undefined;\n }\n\n const nonce = directive\n .split(\" \")\n .slice(1)\n .map((source) => source.trim())\n .find((source) => source.startsWith(\"'nonce-\") && source.length > 8 && source.endsWith(\"'\"))\n ?.slice(7, -1);\n\n if (!nonce) {\n return undefined;\n }\n\n if (ESCAPE_REGEX.test(nonce)) {\n throw new Error(\n \"Nonce value from Content-Security-Policy contained HTML escape characters.\\nLearn more: https://nextjs.org/docs/messages/nonce-contained-invalid-characters\",\n );\n }\n\n return nonce;\n}\n\nexport function getScriptNonceFromHeaders(headers: Headers | null | undefined): string | undefined {\n const csp =\n headers?.get(\"content-security-policy\") ?? headers?.get(\"content-security-policy-report-only\");\n\n if (!csp) {\n return undefined;\n }\n\n return getScriptNonceFromHeader(csp);\n}\n\nfunction getScriptNonceFromNodeHeaders(\n headers: NodeHeaders | null | undefined,\n): string | undefined {\n const csp =\n getNodeHeaderValue(headers, \"content-security-policy\") ??\n getNodeHeaderValue(headers, \"content-security-policy-report-only\");\n\n if (!csp) {\n return undefined;\n }\n\n return getScriptNonceFromHeader(csp);\n}\n\nexport function getScriptNonceFromNodeHeaderSources(\n ...headersList: readonly (NodeHeaders | null | undefined)[]\n): string | undefined {\n for (const headers of headersList) {\n const nonce = getScriptNonceFromNodeHeaders(headers);\n if (nonce) {\n return nonce;\n }\n }\n\n return undefined;\n}\n\nexport function getScriptNonceFromHeaderSources(\n ...headersList: readonly (Headers | null | undefined)[]\n): string | undefined {\n for (const headers of headersList) {\n const nonce = getScriptNonceFromHeaders(headers);\n if (nonce) {\n return nonce;\n }\n }\n\n return undefined;\n}\n"],"mappings":";AAEA,MAAM,eAAe;AAGrB,SAAS,qBAAqB,WAAmB,MAAuB;AACtE,QAAO,cAAc,QAAQ,UAAU,WAAW,GAAG,KAAK,GAAG;;AAG/D,SAAS,mBACP,SACA,KACoB;CACpB,MAAM,QAAQ,UAAU;AACxB,KAAI,MAAM,QAAQ,MAAM,CACtB,QAAO,MAAM,KAAK,KAAK;AAEzB,KAAI,SAAS,KACX;AAEF,QAAO,OAAO,MAAM;;AAGtB,SAAgB,yBAAyB,gBAA4C;CACnF,MAAM,aAAa,eAAe,MAAM,IAAI,CAAC,KAAK,cAAc,UAAU,MAAM,CAAC;CAEjF,MAAM,YACJ,WAAW,MAAM,UAAU,qBAAqB,OAAO,aAAa,CAAC,IACrE,WAAW,MAAM,UAAU,qBAAqB,OAAO,cAAc,CAAC;AAExE,KAAI,CAAC,UACH;CAGF,MAAM,QAAQ,UACX,MAAM,IAAI,CACV,MAAM,EAAE,CACR,KAAK,WAAW,OAAO,MAAM,CAAC,CAC9B,MAAM,WAAW,OAAO,WAAW,UAAU,IAAI,OAAO,SAAS,KAAK,OAAO,SAAS,IAAI,CAAC,EAC1F,MAAM,GAAG,GAAG;AAEhB,KAAI,CAAC,MACH;AAGF,KAAI,aAAa,KAAK,MAAM,CAC1B,OAAM,IAAI,MACR,8JACD;AAGH,QAAO;;AAGT,SAAgB,0BAA0B,SAAyD;CACjG,MAAM,MACJ,SAAS,IAAI,0BAA0B,IAAI,SAAS,IAAI,sCAAsC;AAEhG,KAAI,CAAC,IACH;AAGF,QAAO,yBAAyB,IAAI;;AAGtC,SAAS,8BACP,SACoB;CACpB,MAAM,MACJ,mBAAmB,SAAS,0BAA0B,IACtD,mBAAmB,SAAS,sCAAsC;AAEpE,KAAI,CAAC,IACH;AAGF,QAAO,yBAAyB,IAAI;;AAGtC,SAAgB,oCACd,GAAG,aACiB;AACpB,MAAK,MAAM,WAAW,aAAa;EACjC,MAAM,QAAQ,8BAA8B,QAAQ;AACpD,MAAI,MACF,QAAO;;;AAOb,SAAgB,gCACd,GAAG,aACiB;AACpB,MAAK,MAAM,WAAW,aAAa;EACjC,MAAM,QAAQ,0BAA0B,QAAQ;AAChD,MAAI,MACF,QAAO"}
1
+ {"version":3,"file":"csp.js","names":[],"sources":["../../src/server/csp.ts"],"sourcesContent":["import type { IncomingHttpHeaders, OutgoingHttpHeaders } from \"node:http\";\n\nconst ESCAPE_REGEX = /[&><\\u2028\\u2029]/;\ntype NodeHeaders = IncomingHttpHeaders | OutgoingHttpHeaders;\n\nfunction matchesDirectiveName(directive: string, name: string): boolean {\n return directive === name || directive.startsWith(`${name} `);\n}\n\nfunction getNodeHeaderValue(\n headers: NodeHeaders | null | undefined,\n key: \"content-security-policy\" | \"content-security-policy-report-only\",\n): string | undefined {\n const value = headers?.[key];\n if (Array.isArray(value)) {\n return value.join(\", \");\n }\n if (value == null) {\n return undefined;\n }\n return String(value);\n}\n\nexport function getScriptNonceFromHeader(cspHeaderValue: string): string | undefined {\n const directives = cspHeaderValue.split(\";\").map((directive) => directive.trim());\n\n const directive =\n directives.find((value) => matchesDirectiveName(value, \"script-src\")) ??\n directives.find((value) => matchesDirectiveName(value, \"default-src\"));\n\n if (!directive) {\n return undefined;\n }\n\n const nonce = directive\n .split(\" \")\n .slice(1)\n .map((source) => source.trim())\n .find((source) => source.startsWith(\"'nonce-\") && source.length > 8 && source.endsWith(\"'\"))\n ?.slice(7, -1);\n\n if (!nonce) {\n return undefined;\n }\n\n if (ESCAPE_REGEX.test(nonce)) {\n throw new Error(\n \"Nonce value from Content-Security-Policy contained HTML escape characters.\\nLearn more: https://nextjs.org/docs/messages/nonce-contained-invalid-characters\",\n );\n }\n\n return nonce;\n}\n\nexport function getScriptNonceFromHeaders(headers: Headers | null | undefined): string | undefined {\n const csp =\n headers?.get(\"content-security-policy\") ?? headers?.get(\"content-security-policy-report-only\");\n\n if (!csp) {\n return undefined;\n }\n\n return getScriptNonceFromHeader(csp);\n}\n\nfunction getScriptNonceFromNodeHeaders(\n headers: NodeHeaders | null | undefined,\n): string | undefined {\n const csp =\n getNodeHeaderValue(headers, \"content-security-policy\") ??\n getNodeHeaderValue(headers, \"content-security-policy-report-only\");\n\n if (!csp) {\n return undefined;\n }\n\n return getScriptNonceFromHeader(csp);\n}\n\nexport function getScriptNonceFromNodeHeaderSources(\n ...headersList: readonly (NodeHeaders | null | undefined)[]\n): string | undefined {\n for (const headers of headersList) {\n const nonce = getScriptNonceFromNodeHeaders(headers);\n if (nonce) {\n return nonce;\n }\n }\n\n return undefined;\n}\n\nexport function getScriptNonceFromHeaderSources(\n ...headersList: readonly (Headers | null | undefined)[]\n): string | undefined {\n for (const headers of headersList) {\n const nonce = getScriptNonceFromHeaders(headers);\n if (nonce) {\n return nonce;\n }\n }\n\n return undefined;\n}\n"],"mappings":";AAEA,MAAM,eAAe;AAGrB,SAAS,qBAAqB,WAAmB,MAAuB;CACtE,OAAO,cAAc,QAAQ,UAAU,WAAW,GAAG,KAAK,GAAG;;AAG/D,SAAS,mBACP,SACA,KACoB;CACpB,MAAM,QAAQ,UAAU;CACxB,IAAI,MAAM,QAAQ,MAAM,EACtB,OAAO,MAAM,KAAK,KAAK;CAEzB,IAAI,SAAS,MACX;CAEF,OAAO,OAAO,MAAM;;AAGtB,SAAgB,yBAAyB,gBAA4C;CACnF,MAAM,aAAa,eAAe,MAAM,IAAI,CAAC,KAAK,cAAc,UAAU,MAAM,CAAC;CAEjF,MAAM,YACJ,WAAW,MAAM,UAAU,qBAAqB,OAAO,aAAa,CAAC,IACrE,WAAW,MAAM,UAAU,qBAAqB,OAAO,cAAc,CAAC;CAExE,IAAI,CAAC,WACH;CAGF,MAAM,QAAQ,UACX,MAAM,IAAI,CACV,MAAM,EAAE,CACR,KAAK,WAAW,OAAO,MAAM,CAAC,CAC9B,MAAM,WAAW,OAAO,WAAW,UAAU,IAAI,OAAO,SAAS,KAAK,OAAO,SAAS,IAAI,CAAC,EAC1F,MAAM,GAAG,GAAG;CAEhB,IAAI,CAAC,OACH;CAGF,IAAI,aAAa,KAAK,MAAM,EAC1B,MAAM,IAAI,MACR,8JACD;CAGH,OAAO;;AAGT,SAAgB,0BAA0B,SAAyD;CACjG,MAAM,MACJ,SAAS,IAAI,0BAA0B,IAAI,SAAS,IAAI,sCAAsC;CAEhG,IAAI,CAAC,KACH;CAGF,OAAO,yBAAyB,IAAI;;AAGtC,SAAS,8BACP,SACoB;CACpB,MAAM,MACJ,mBAAmB,SAAS,0BAA0B,IACtD,mBAAmB,SAAS,sCAAsC;CAEpE,IAAI,CAAC,KACH;CAGF,OAAO,yBAAyB,IAAI;;AAGtC,SAAgB,oCACd,GAAG,aACiB;CACpB,KAAK,MAAM,WAAW,aAAa;EACjC,MAAM,QAAQ,8BAA8B,QAAQ;EACpD,IAAI,OACF,OAAO;;;AAOb,SAAgB,gCACd,GAAG,aACiB;CACpB,KAAK,MAAM,WAAW,aAAa;EACjC,MAAM,QAAQ,0BAA0B,QAAQ;EAChD,IAAI,OACF,OAAO"}
@@ -1 +1 @@
1
- {"version":3,"file":"dev-error-overlay-store.js","names":[],"sources":["../../src/server/dev-error-overlay-store.ts"],"sourcesContent":["// Module-level store for the dev error overlay. Lives in its own file so the\n// overlay React component (dev-error-overlay.tsx) can subscribe via\n// useSyncExternalStore without circular imports.\n\nexport type Source = \"uncaught\" | \"caught\" | \"window-error\" | \"unhandledrejection\";\n\nexport type ReportedError = {\n source: Source;\n message: string;\n stack: string | undefined;\n componentStack: string | undefined;\n};\n\nexport type OverlayState = {\n errors: ReportedError[];\n index: number;\n minimized: boolean;\n};\n\n// Cap the buffer so a hot-reloading loop or an effect that throws on every\n// render can't grow the array (and its retained stack strings) without\n// bound. FIFO eviction keeps the most recent failures.\nconst MAX_DEV_OVERLAY_ERRORS = 50;\n\nlet snapshot: OverlayState = { errors: [], index: 0, minimized: false };\nconst listeners = new Set<() => void>();\n\nfunction emit(): void {\n for (const fn of listeners) fn();\n}\n\nexport function subscribeOverlay(fn: () => void): () => void {\n listeners.add(fn);\n return () => {\n listeners.delete(fn);\n };\n}\n\nexport function getOverlaySnapshot(): OverlayState {\n return snapshot;\n}\n\nexport function reportToOverlay(error: ReportedError): void {\n // Any new error pops the dialog open, regardless of source or current\n // state. The developer can minimize once they've taken stock; subsequent\n // failures will re-expand.\n const next = [...snapshot.errors, error];\n const dropped = next.length > MAX_DEV_OVERLAY_ERRORS ? next.length - MAX_DEV_OVERLAY_ERRORS : 0;\n const errors = dropped > 0 ? next.slice(dropped) : next;\n snapshot = {\n errors,\n index: errors.length - 1,\n minimized: false,\n };\n emit();\n}\n\nexport function dismissOverlay(): void {\n snapshot = { errors: [], index: 0, minimized: false };\n emit();\n}\n\nexport function setOverlayIndex(index: number): void {\n if (index < 0 || index >= snapshot.errors.length) return;\n snapshot = { ...snapshot, index };\n emit();\n}\n\nexport function minimizeOverlay(): void {\n if (snapshot.minimized) return;\n snapshot = { ...snapshot, minimized: true };\n emit();\n}\n\nexport function expandOverlay(): void {\n if (!snapshot.minimized) return;\n snapshot = { ...snapshot, minimized: false };\n emit();\n}\n"],"mappings":";AAsBA,MAAM,yBAAyB;AAE/B,IAAI,WAAyB;CAAE,QAAQ,EAAE;CAAE,OAAO;CAAG,WAAW;CAAO;AACvE,MAAM,4BAAY,IAAI,KAAiB;AAEvC,SAAS,OAAa;AACpB,MAAK,MAAM,MAAM,UAAW,KAAI;;AAGlC,SAAgB,iBAAiB,IAA4B;AAC3D,WAAU,IAAI,GAAG;AACjB,cAAa;AACX,YAAU,OAAO,GAAG;;;AAIxB,SAAgB,qBAAmC;AACjD,QAAO;;AAGT,SAAgB,gBAAgB,OAA4B;CAI1D,MAAM,OAAO,CAAC,GAAG,SAAS,QAAQ,MAAM;CACxC,MAAM,UAAU,KAAK,SAAS,yBAAyB,KAAK,SAAS,yBAAyB;CAC9F,MAAM,SAAS,UAAU,IAAI,KAAK,MAAM,QAAQ,GAAG;AACnD,YAAW;EACT;EACA,OAAO,OAAO,SAAS;EACvB,WAAW;EACZ;AACD,OAAM;;AAGR,SAAgB,iBAAuB;AACrC,YAAW;EAAE,QAAQ,EAAE;EAAE,OAAO;EAAG,WAAW;EAAO;AACrD,OAAM;;AAGR,SAAgB,gBAAgB,OAAqB;AACnD,KAAI,QAAQ,KAAK,SAAS,SAAS,OAAO,OAAQ;AAClD,YAAW;EAAE,GAAG;EAAU;EAAO;AACjC,OAAM;;AAGR,SAAgB,kBAAwB;AACtC,KAAI,SAAS,UAAW;AACxB,YAAW;EAAE,GAAG;EAAU,WAAW;EAAM;AAC3C,OAAM;;AAGR,SAAgB,gBAAsB;AACpC,KAAI,CAAC,SAAS,UAAW;AACzB,YAAW;EAAE,GAAG;EAAU,WAAW;EAAO;AAC5C,OAAM"}
1
+ {"version":3,"file":"dev-error-overlay-store.js","names":[],"sources":["../../src/server/dev-error-overlay-store.ts"],"sourcesContent":["// Module-level store for the dev error overlay. Lives in its own file so the\n// overlay React component (dev-error-overlay.tsx) can subscribe via\n// useSyncExternalStore without circular imports.\n\nexport type Source = \"uncaught\" | \"caught\" | \"window-error\" | \"unhandledrejection\";\n\nexport type ReportedError = {\n source: Source;\n message: string;\n stack: string | undefined;\n componentStack: string | undefined;\n};\n\nexport type OverlayState = {\n errors: ReportedError[];\n index: number;\n minimized: boolean;\n};\n\n// Cap the buffer so a hot-reloading loop or an effect that throws on every\n// render can't grow the array (and its retained stack strings) without\n// bound. FIFO eviction keeps the most recent failures.\nconst MAX_DEV_OVERLAY_ERRORS = 50;\n\nlet snapshot: OverlayState = { errors: [], index: 0, minimized: false };\nconst listeners = new Set<() => void>();\n\nfunction emit(): void {\n for (const fn of listeners) fn();\n}\n\nexport function subscribeOverlay(fn: () => void): () => void {\n listeners.add(fn);\n return () => {\n listeners.delete(fn);\n };\n}\n\nexport function getOverlaySnapshot(): OverlayState {\n return snapshot;\n}\n\nexport function reportToOverlay(error: ReportedError): void {\n // Any new error pops the dialog open, regardless of source or current\n // state. The developer can minimize once they've taken stock; subsequent\n // failures will re-expand.\n const next = [...snapshot.errors, error];\n const dropped = next.length > MAX_DEV_OVERLAY_ERRORS ? next.length - MAX_DEV_OVERLAY_ERRORS : 0;\n const errors = dropped > 0 ? next.slice(dropped) : next;\n snapshot = {\n errors,\n index: errors.length - 1,\n minimized: false,\n };\n emit();\n}\n\nexport function dismissOverlay(): void {\n snapshot = { errors: [], index: 0, minimized: false };\n emit();\n}\n\nexport function setOverlayIndex(index: number): void {\n if (index < 0 || index >= snapshot.errors.length) return;\n snapshot = { ...snapshot, index };\n emit();\n}\n\nexport function minimizeOverlay(): void {\n if (snapshot.minimized) return;\n snapshot = { ...snapshot, minimized: true };\n emit();\n}\n\nexport function expandOverlay(): void {\n if (!snapshot.minimized) return;\n snapshot = { ...snapshot, minimized: false };\n emit();\n}\n"],"mappings":";AAsBA,MAAM,yBAAyB;AAE/B,IAAI,WAAyB;CAAE,QAAQ,EAAE;CAAE,OAAO;CAAG,WAAW;CAAO;AACvE,MAAM,4BAAY,IAAI,KAAiB;AAEvC,SAAS,OAAa;CACpB,KAAK,MAAM,MAAM,WAAW,IAAI;;AAGlC,SAAgB,iBAAiB,IAA4B;CAC3D,UAAU,IAAI,GAAG;CACjB,aAAa;EACX,UAAU,OAAO,GAAG;;;AAIxB,SAAgB,qBAAmC;CACjD,OAAO;;AAGT,SAAgB,gBAAgB,OAA4B;CAI1D,MAAM,OAAO,CAAC,GAAG,SAAS,QAAQ,MAAM;CACxC,MAAM,UAAU,KAAK,SAAS,yBAAyB,KAAK,SAAS,yBAAyB;CAC9F,MAAM,SAAS,UAAU,IAAI,KAAK,MAAM,QAAQ,GAAG;CACnD,WAAW;EACT;EACA,OAAO,OAAO,SAAS;EACvB,WAAW;EACZ;CACD,MAAM;;AAGR,SAAgB,iBAAuB;CACrC,WAAW;EAAE,QAAQ,EAAE;EAAE,OAAO;EAAG,WAAW;EAAO;CACrD,MAAM;;AAGR,SAAgB,gBAAgB,OAAqB;CACnD,IAAI,QAAQ,KAAK,SAAS,SAAS,OAAO,QAAQ;CAClD,WAAW;EAAE,GAAG;EAAU;EAAO;CACjC,MAAM;;AAGR,SAAgB,kBAAwB;CACtC,IAAI,SAAS,WAAW;CACxB,WAAW;EAAE,GAAG;EAAU,WAAW;EAAM;CAC3C,MAAM;;AAGR,SAAgB,gBAAsB;CACpC,IAAI,CAAC,SAAS,WAAW;CACzB,WAAW;EAAE,GAAG;EAAU,WAAW;EAAO;CAC5C,MAAM"}
@@ -1,3 +1,4 @@
1
+ import { isNavigationSignalError } from "../utils/navigation-signal.js";
1
2
  import { dismissOverlay, expandOverlay, getOverlaySnapshot, minimizeOverlay, reportToOverlay, setOverlayIndex, subscribeOverlay } from "./dev-error-overlay-store.js";
2
3
  import { useEffect, useSyncExternalStore } from "react";
3
4
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
@@ -18,6 +19,7 @@ function installDevErrorOverlay() {
18
19
  installed = true;
19
20
  window.addEventListener("error", (event) => {
20
21
  const err = event.error;
22
+ if (isNavigationSignalError(err)) return;
21
23
  if (err instanceof Error) {
22
24
  if (alreadyReported(err)) return;
23
25
  reportDevError(err, { source: "window-error" });
@@ -25,6 +27,7 @@ function installDevErrorOverlay() {
25
27
  });
26
28
  window.addEventListener("unhandledrejection", (event) => {
27
29
  const reason = event.reason;
30
+ if (isNavigationSignalError(reason)) return;
28
31
  if (reason instanceof Error) {
29
32
  if (alreadyReported(reason)) return;
30
33
  reportDevError(reason, { source: "unhandledrejection" });
@@ -45,6 +48,7 @@ function reportDevError(error, options) {
45
48
  });
46
49
  }
47
50
  function devOnCaughtError(error, errorInfo) {
51
+ if (isNavigationSignalError(error)) return;
48
52
  console.error(error);
49
53
  if (errorInfo?.componentStack) console.error("The above error occurred in a React component:\n" + errorInfo.componentStack);
50
54
  reportDevError(error, {
@@ -53,6 +57,7 @@ function devOnCaughtError(error, errorInfo) {
53
57
  });
54
58
  }
55
59
  function devOnUncaughtError(error, errorInfo) {
60
+ if (isNavigationSignalError(error)) return;
56
61
  console.error(error);
57
62
  if (errorInfo?.componentStack) console.error("The above error occurred in a React component:\n" + errorInfo.componentStack);
58
63
  reportDevError(error, {