vinext 0.0.46 → 0.0.48

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 (351) hide show
  1. package/README.md +8 -6
  2. package/dist/build/layout-classification.js +3 -1
  3. package/dist/build/layout-classification.js.map +1 -1
  4. package/dist/build/prerender.d.ts +2 -1
  5. package/dist/build/prerender.js +80 -24
  6. package/dist/build/prerender.js.map +1 -1
  7. package/dist/build/report.d.ts +9 -5
  8. package/dist/build/report.js +17 -7
  9. package/dist/build/report.js.map +1 -1
  10. package/dist/build/route-classification-injector.d.ts +35 -0
  11. package/dist/build/route-classification-injector.js +61 -0
  12. package/dist/build/route-classification-injector.js.map +1 -0
  13. package/dist/build/route-classification-manifest.d.ts +1 -1
  14. package/dist/build/run-prerender.d.ts +5 -0
  15. package/dist/build/run-prerender.js +4 -1
  16. package/dist/build/run-prerender.js.map +1 -1
  17. package/dist/build/server-manifest.js +2 -7
  18. package/dist/build/server-manifest.js.map +1 -1
  19. package/dist/build/standalone.js +3 -5
  20. package/dist/build/standalone.js.map +1 -1
  21. package/dist/build/static-export.d.ts +1 -1
  22. package/dist/check.js +45 -29
  23. package/dist/check.js.map +1 -1
  24. package/dist/cli-args.d.ts +33 -0
  25. package/dist/cli-args.js +121 -0
  26. package/dist/cli-args.js.map +1 -0
  27. package/dist/cli.js +11 -20
  28. package/dist/cli.js.map +1 -1
  29. package/dist/cloudflare/kv-cache-handler.js +29 -9
  30. package/dist/cloudflare/kv-cache-handler.js.map +1 -1
  31. package/dist/config/config-matchers.js +46 -37
  32. package/dist/config/config-matchers.js.map +1 -1
  33. package/dist/config/next-config.d.ts +4 -2
  34. package/dist/config/next-config.js +3 -0
  35. package/dist/config/next-config.js.map +1 -1
  36. package/dist/deploy.d.ts +18 -2
  37. package/dist/deploy.js +47 -4
  38. package/dist/deploy.js.map +1 -1
  39. package/dist/entries/app-rsc-entry.d.ts +4 -3
  40. package/dist/entries/app-rsc-entry.js +379 -858
  41. package/dist/entries/app-rsc-entry.js.map +1 -1
  42. package/dist/entries/app-rsc-manifest.d.ts +1 -1
  43. package/dist/entries/app-rsc-manifest.js +6 -1
  44. package/dist/entries/app-rsc-manifest.js.map +1 -1
  45. package/dist/entries/pages-client-entry.js +3 -2
  46. package/dist/entries/pages-client-entry.js.map +1 -1
  47. package/dist/entries/pages-server-entry.js +19 -61
  48. package/dist/entries/pages-server-entry.js.map +1 -1
  49. package/dist/entries/runtime-entry-module.d.ts +12 -3
  50. package/dist/entries/runtime-entry-module.js +15 -4
  51. package/dist/entries/runtime-entry-module.js.map +1 -1
  52. package/dist/index.js +40 -58
  53. package/dist/index.js.map +1 -1
  54. package/dist/plugins/fonts.js +54 -32
  55. package/dist/plugins/fonts.js.map +1 -1
  56. package/dist/plugins/og-assets.js +15 -16
  57. package/dist/plugins/og-assets.js.map +1 -1
  58. package/dist/plugins/rsc-client-shim-excludes.d.ts +2 -1
  59. package/dist/plugins/rsc-client-shim-excludes.js +11 -1
  60. package/dist/plugins/rsc-client-shim-excludes.js.map +1 -1
  61. package/dist/routing/app-route-graph.d.ts +195 -0
  62. package/dist/routing/app-route-graph.js +1022 -0
  63. package/dist/routing/app-route-graph.js.map +1 -0
  64. package/dist/routing/app-router.d.ts +14 -88
  65. package/dist/routing/app-router.js +21 -712
  66. package/dist/routing/app-router.js.map +1 -1
  67. package/dist/routing/file-matcher.d.ts +3 -1
  68. package/dist/routing/file-matcher.js +6 -1
  69. package/dist/routing/file-matcher.js.map +1 -1
  70. package/dist/routing/pages-router.js +10 -19
  71. package/dist/routing/pages-router.js.map +1 -1
  72. package/dist/routing/route-matching.d.ts +28 -0
  73. package/dist/routing/route-matching.js +44 -0
  74. package/dist/routing/route-matching.js.map +1 -0
  75. package/dist/routing/route-pattern.js +4 -1
  76. package/dist/routing/route-pattern.js.map +1 -1
  77. package/dist/routing/route-trie.d.ts +8 -0
  78. package/dist/routing/route-trie.js +12 -1
  79. package/dist/routing/route-trie.js.map +1 -1
  80. package/dist/routing/route-validation.js +3 -4
  81. package/dist/routing/route-validation.js.map +1 -1
  82. package/dist/routing/utils.d.ts +8 -1
  83. package/dist/routing/utils.js +25 -2
  84. package/dist/routing/utils.js.map +1 -1
  85. package/dist/server/app-browser-entry.js +145 -294
  86. package/dist/server/app-browser-entry.js.map +1 -1
  87. package/dist/server/app-browser-error.d.ts +3 -4
  88. package/dist/server/app-browser-error.js +8 -4
  89. package/dist/server/app-browser-error.js.map +1 -1
  90. package/dist/server/app-browser-navigation-controller.d.ts +75 -0
  91. package/dist/server/app-browser-navigation-controller.js +290 -0
  92. package/dist/server/app-browser-navigation-controller.js.map +1 -0
  93. package/dist/server/app-browser-state.d.ts +33 -15
  94. package/dist/server/app-browser-state.js +52 -59
  95. package/dist/server/app-browser-state.js.map +1 -1
  96. package/dist/server/app-browser-visible-commit.d.ts +68 -0
  97. package/dist/server/app-browser-visible-commit.js +182 -0
  98. package/dist/server/app-browser-visible-commit.js.map +1 -0
  99. package/dist/server/app-client-reference-preloader.d.ts +15 -0
  100. package/dist/server/app-client-reference-preloader.js +46 -0
  101. package/dist/server/app-client-reference-preloader.js.map +1 -0
  102. package/dist/server/app-elements-wire.d.ts +130 -0
  103. package/dist/server/app-elements-wire.js +205 -0
  104. package/dist/server/app-elements-wire.js.map +1 -0
  105. package/dist/server/app-elements.d.ts +2 -84
  106. package/dist/server/app-elements.js +4 -107
  107. package/dist/server/app-elements.js.map +1 -1
  108. package/dist/server/app-fallback-renderer.d.ts +57 -0
  109. package/dist/server/app-fallback-renderer.js +79 -0
  110. package/dist/server/app-fallback-renderer.js.map +1 -0
  111. package/dist/server/app-hook-warning-suppression.d.ts +7 -0
  112. package/dist/server/app-hook-warning-suppression.js +12 -0
  113. package/dist/server/app-hook-warning-suppression.js.map +1 -0
  114. package/dist/server/app-middleware.d.ts +2 -1
  115. package/dist/server/app-middleware.js +34 -11
  116. package/dist/server/app-middleware.js.map +1 -1
  117. package/dist/server/app-mounted-slots-header.d.ts +17 -0
  118. package/dist/server/app-mounted-slots-header.js +21 -0
  119. package/dist/server/app-mounted-slots-header.js.map +1 -0
  120. package/dist/server/app-page-boundary-render.d.ts +3 -3
  121. package/dist/server/app-page-boundary-render.js +8 -5
  122. package/dist/server/app-page-boundary-render.js.map +1 -1
  123. package/dist/server/app-page-boundary.js +2 -1
  124. package/dist/server/app-page-boundary.js.map +1 -1
  125. package/dist/server/app-page-cache.d.ts +19 -4
  126. package/dist/server/app-page-cache.js +60 -22
  127. package/dist/server/app-page-cache.js.map +1 -1
  128. package/dist/server/app-page-dispatch.d.ts +9 -5
  129. package/dist/server/app-page-dispatch.js +41 -17
  130. package/dist/server/app-page-dispatch.js.map +1 -1
  131. package/dist/server/app-page-element-builder.d.ts +61 -0
  132. package/dist/server/app-page-element-builder.js +142 -0
  133. package/dist/server/app-page-element-builder.js.map +1 -0
  134. package/dist/server/app-page-execution.d.ts +23 -5
  135. package/dist/server/app-page-execution.js +39 -24
  136. package/dist/server/app-page-execution.js.map +1 -1
  137. package/dist/server/app-page-head.js +2 -1
  138. package/dist/server/app-page-head.js.map +1 -1
  139. package/dist/server/app-page-method.js +2 -5
  140. package/dist/server/app-page-method.js.map +1 -1
  141. package/dist/server/app-page-params.d.ts +2 -1
  142. package/dist/server/app-page-params.js +3 -3
  143. package/dist/server/app-page-params.js.map +1 -1
  144. package/dist/server/app-page-probe.d.ts +1 -1
  145. package/dist/server/app-page-probe.js +5 -1
  146. package/dist/server/app-page-probe.js.map +1 -1
  147. package/dist/server/app-page-render.d.ts +6 -2
  148. package/dist/server/app-page-render.js +118 -30
  149. package/dist/server/app-page-render.js.map +1 -1
  150. package/dist/server/app-page-request.d.ts +19 -5
  151. package/dist/server/app-page-request.js +49 -7
  152. package/dist/server/app-page-request.js.map +1 -1
  153. package/dist/server/app-page-response.d.ts +1 -0
  154. package/dist/server/app-page-response.js +6 -9
  155. package/dist/server/app-page-response.js.map +1 -1
  156. package/dist/server/app-page-route-wiring.d.ts +20 -4
  157. package/dist/server/app-page-route-wiring.js +15 -12
  158. package/dist/server/app-page-route-wiring.js.map +1 -1
  159. package/dist/server/app-page-stream.d.ts +7 -0
  160. package/dist/server/app-page-stream.js +9 -2
  161. package/dist/server/app-page-stream.js.map +1 -1
  162. package/dist/server/app-post-middleware-context.d.ts +16 -0
  163. package/dist/server/app-post-middleware-context.js +28 -0
  164. package/dist/server/app-post-middleware-context.js.map +1 -0
  165. package/dist/server/app-prerender-endpoints.js +3 -2
  166. package/dist/server/app-prerender-endpoints.js.map +1 -1
  167. package/dist/server/app-request-context.d.ts +22 -0
  168. package/dist/server/app-request-context.js +30 -0
  169. package/dist/server/app-request-context.js.map +1 -0
  170. package/dist/server/app-route-handler-cache.d.ts +1 -0
  171. package/dist/server/app-route-handler-cache.js +7 -2
  172. package/dist/server/app-route-handler-cache.js.map +1 -1
  173. package/dist/server/app-route-handler-dispatch.d.ts +1 -0
  174. package/dist/server/app-route-handler-dispatch.js +8 -5
  175. package/dist/server/app-route-handler-dispatch.js.map +1 -1
  176. package/dist/server/app-route-handler-execution.d.ts +2 -1
  177. package/dist/server/app-route-handler-execution.js +2 -2
  178. package/dist/server/app-route-handler-execution.js.map +1 -1
  179. package/dist/server/app-route-handler-policy.js +13 -13
  180. package/dist/server/app-route-handler-policy.js.map +1 -1
  181. package/dist/server/app-route-handler-response.d.ts +4 -2
  182. package/dist/server/app-route-handler-response.js +9 -7
  183. package/dist/server/app-route-handler-response.js.map +1 -1
  184. package/dist/server/app-route-handler-runtime.d.ts +9 -1
  185. package/dist/server/app-route-handler-runtime.js +11 -1
  186. package/dist/server/app-route-handler-runtime.js.map +1 -1
  187. package/dist/server/app-router-entry.js +9 -4
  188. package/dist/server/app-router-entry.js.map +1 -1
  189. package/dist/server/app-rsc-cache-busting.d.ts +34 -0
  190. package/dist/server/app-rsc-cache-busting.js +137 -0
  191. package/dist/server/app-rsc-cache-busting.js.map +1 -0
  192. package/dist/server/app-rsc-error-handler.d.ts +21 -0
  193. package/dist/server/app-rsc-error-handler.js +30 -0
  194. package/dist/server/app-rsc-error-handler.js.map +1 -0
  195. package/dist/server/app-rsc-handler.d.ts +117 -0
  196. package/dist/server/app-rsc-handler.js +271 -0
  197. package/dist/server/app-rsc-handler.js.map +1 -0
  198. package/dist/server/app-rsc-request-normalization.d.ts +42 -0
  199. package/dist/server/app-rsc-request-normalization.js +67 -0
  200. package/dist/server/app-rsc-request-normalization.js.map +1 -0
  201. package/dist/server/app-rsc-response-finalizer.d.ts +30 -0
  202. package/dist/server/app-rsc-response-finalizer.js +38 -0
  203. package/dist/server/app-rsc-response-finalizer.js.map +1 -0
  204. package/dist/server/app-rsc-route-matching.js +8 -4
  205. package/dist/server/app-rsc-route-matching.js.map +1 -1
  206. package/dist/server/app-segment-config.d.ts +33 -0
  207. package/dist/server/app-segment-config.js +90 -0
  208. package/dist/server/app-segment-config.js.map +1 -0
  209. package/dist/server/app-server-action-execution.d.ts +2 -0
  210. package/dist/server/app-server-action-execution.js +45 -51
  211. package/dist/server/app-server-action-execution.js.map +1 -1
  212. package/dist/server/app-ssr-entry.js +21 -20
  213. package/dist/server/app-ssr-entry.js.map +1 -1
  214. package/dist/server/artifact-compatibility.d.ts +44 -0
  215. package/dist/server/artifact-compatibility.js +82 -0
  216. package/dist/server/artifact-compatibility.js.map +1 -0
  217. package/dist/server/cache-control.d.ts +24 -0
  218. package/dist/server/cache-control.js +33 -0
  219. package/dist/server/cache-control.js.map +1 -0
  220. package/dist/server/cache-proof.d.ts +200 -0
  221. package/dist/server/cache-proof.js +342 -0
  222. package/dist/server/cache-proof.js.map +1 -0
  223. package/dist/server/dev-error-overlay-store.d.ts +23 -0
  224. package/dist/server/dev-error-overlay-store.js +67 -0
  225. package/dist/server/dev-error-overlay-store.js.map +1 -0
  226. package/dist/server/dev-error-overlay.d.ts +15 -0
  227. package/dist/server/dev-error-overlay.js +548 -0
  228. package/dist/server/dev-error-overlay.js.map +1 -0
  229. package/dist/server/dev-origin-check.js +8 -4
  230. package/dist/server/dev-origin-check.js.map +1 -1
  231. package/dist/server/dev-server.js +1 -6
  232. package/dist/server/dev-server.js.map +1 -1
  233. package/dist/server/http-error-responses.d.ts +67 -0
  234. package/dist/server/http-error-responses.js +77 -0
  235. package/dist/server/http-error-responses.js.map +1 -0
  236. package/dist/server/image-optimization.js +2 -1
  237. package/dist/server/image-optimization.js.map +1 -1
  238. package/dist/server/instrumentation-runtime.d.ts +44 -0
  239. package/dist/server/instrumentation-runtime.js +29 -0
  240. package/dist/server/instrumentation-runtime.js.map +1 -0
  241. package/dist/server/isr-cache.d.ts +2 -7
  242. package/dist/server/isr-cache.js +7 -10
  243. package/dist/server/isr-cache.js.map +1 -1
  244. package/dist/server/metadata-route-response.js +6 -5
  245. package/dist/server/metadata-route-response.js.map +1 -1
  246. package/dist/server/metadata-routes.d.ts +1 -0
  247. package/dist/server/metadata-routes.js +6 -0
  248. package/dist/server/metadata-routes.js.map +1 -1
  249. package/dist/server/middleware-matcher.js +2 -2
  250. package/dist/server/middleware-matcher.js.map +1 -1
  251. package/dist/server/middleware-response-headers.js +21 -0
  252. package/dist/server/middleware-response-headers.js.map +1 -1
  253. package/dist/server/middleware-runtime.js +3 -3
  254. package/dist/server/middleware-runtime.js.map +1 -1
  255. package/dist/server/navigation-trace.d.ts +33 -0
  256. package/dist/server/navigation-trace.js +35 -0
  257. package/dist/server/navigation-trace.js.map +1 -0
  258. package/dist/server/next-error-digest.d.ts +44 -0
  259. package/dist/server/next-error-digest.js +40 -0
  260. package/dist/server/next-error-digest.js.map +1 -0
  261. package/dist/server/pages-api-route.js +2 -1
  262. package/dist/server/pages-api-route.js.map +1 -1
  263. package/dist/server/pages-node-compat.js +4 -16
  264. package/dist/server/pages-node-compat.js.map +1 -1
  265. package/dist/server/pages-page-data.d.ts +2 -1
  266. package/dist/server/pages-page-data.js +6 -5
  267. package/dist/server/pages-page-data.js.map +1 -1
  268. package/dist/server/pages-page-response.d.ts +3 -8
  269. package/dist/server/pages-page-response.js +46 -15
  270. package/dist/server/pages-page-response.js.map +1 -1
  271. package/dist/server/prod-server.d.ts +6 -0
  272. package/dist/server/prod-server.js +28 -21
  273. package/dist/server/prod-server.js.map +1 -1
  274. package/dist/server/request-pipeline.d.ts +42 -1
  275. package/dist/server/request-pipeline.js +97 -17
  276. package/dist/server/request-pipeline.js.map +1 -1
  277. package/dist/server/rsc-stream-hints.d.ts +3 -1
  278. package/dist/server/rsc-stream-hints.js +4 -1
  279. package/dist/server/rsc-stream-hints.js.map +1 -1
  280. package/dist/server/seed-cache.js +19 -8
  281. package/dist/server/seed-cache.js.map +1 -1
  282. package/dist/shims/cache-runtime.d.ts +2 -2
  283. package/dist/shims/cache-runtime.js +31 -17
  284. package/dist/shims/cache-runtime.js.map +1 -1
  285. package/dist/shims/cache.d.ts +15 -3
  286. package/dist/shims/cache.js +45 -20
  287. package/dist/shims/cache.js.map +1 -1
  288. package/dist/shims/error-boundary.d.ts +17 -1
  289. package/dist/shims/error-boundary.js +31 -1
  290. package/dist/shims/error-boundary.js.map +1 -1
  291. package/dist/shims/fetch-cache.d.ts +4 -1
  292. package/dist/shims/fetch-cache.js +57 -16
  293. package/dist/shims/fetch-cache.js.map +1 -1
  294. package/dist/shims/head-state.js +2 -3
  295. package/dist/shims/head-state.js.map +1 -1
  296. package/dist/shims/headers.js +4 -44
  297. package/dist/shims/headers.js.map +1 -1
  298. package/dist/shims/i18n-state.js +2 -3
  299. package/dist/shims/i18n-state.js.map +1 -1
  300. package/dist/shims/image.js +93 -5
  301. package/dist/shims/image.js.map +1 -1
  302. package/dist/shims/internal/als-registry.d.ts +15 -0
  303. package/dist/shims/internal/als-registry.js +55 -0
  304. package/dist/shims/internal/als-registry.js.map +1 -0
  305. package/dist/shims/internal/cookie-serialize.d.ts +46 -0
  306. package/dist/shims/internal/cookie-serialize.js +51 -0
  307. package/dist/shims/internal/cookie-serialize.js.map +1 -0
  308. package/dist/shims/link.js +31 -26
  309. package/dist/shims/link.js.map +1 -1
  310. package/dist/shims/metadata.d.ts +26 -1
  311. package/dist/shims/metadata.js +94 -4
  312. package/dist/shims/metadata.js.map +1 -1
  313. package/dist/shims/navigation-state.js +2 -3
  314. package/dist/shims/navigation-state.js.map +1 -1
  315. package/dist/shims/navigation.d.ts +2 -7
  316. package/dist/shims/navigation.js +44 -36
  317. package/dist/shims/navigation.js.map +1 -1
  318. package/dist/shims/request-context.js +2 -4
  319. package/dist/shims/request-context.js.map +1 -1
  320. package/dist/shims/request-state-types.d.ts +1 -1
  321. package/dist/shims/router-state.js +2 -3
  322. package/dist/shims/router-state.js.map +1 -1
  323. package/dist/shims/router.js +2 -2
  324. package/dist/shims/router.js.map +1 -1
  325. package/dist/shims/server.js +5 -30
  326. package/dist/shims/server.js.map +1 -1
  327. package/dist/shims/slot.d.ts +1 -1
  328. package/dist/shims/slot.js +5 -4
  329. package/dist/shims/slot.js.map +1 -1
  330. package/dist/shims/thenable-params.d.ts +5 -2
  331. package/dist/shims/thenable-params.js +26 -6
  332. package/dist/shims/thenable-params.js.map +1 -1
  333. package/dist/shims/unified-request-context.d.ts +1 -1
  334. package/dist/shims/unified-request-context.js +3 -14
  335. package/dist/shims/unified-request-context.js.map +1 -1
  336. package/dist/shims/use-merged-ref.d.ts +7 -0
  337. package/dist/shims/use-merged-ref.js +40 -0
  338. package/dist/shims/use-merged-ref.js.map +1 -0
  339. package/dist/utils/base-path.d.ts +7 -1
  340. package/dist/utils/base-path.js +12 -1
  341. package/dist/utils/base-path.js.map +1 -1
  342. package/dist/utils/cache-control-metadata.d.ts +6 -0
  343. package/dist/utils/cache-control-metadata.js +16 -0
  344. package/dist/utils/cache-control-metadata.js.map +1 -0
  345. package/dist/utils/safe-json-file.d.ts +18 -0
  346. package/dist/utils/safe-json-file.js +25 -0
  347. package/dist/utils/safe-json-file.js.map +1 -0
  348. package/dist/utils/text-stream.d.ts +29 -0
  349. package/dist/utils/text-stream.js +66 -0
  350. package/dist/utils/text-stream.js.map +1 -0
  351. package/package.json +5 -5
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app-fallback-renderer.js","names":[],"sources":["../../src/server/app-fallback-renderer.ts"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport type { AppPageParams } from \"./app-page-boundary.js\";\nimport {\n renderAppPageErrorBoundary,\n renderAppPageHttpAccessFallback,\n type AppPageBoundaryRoute,\n} from \"./app-page-boundary-render.js\";\nimport type { AppPageFontPreload } from \"./app-page-execution.js\";\nimport type { AppPageMiddlewareContext } from \"./app-page-response.js\";\nimport type { AppPageSsrHandler } from \"./app-page-stream.js\";\nimport type { MetadataFileRoute } from \"./metadata-routes.js\";\nimport type { AppElements } from \"./app-elements.js\";\n\n// oxlint-disable-next-line @typescript-eslint/no-explicit-any\ntype AppPageComponent = import(\"react\").ComponentType<any>;\ntype AppPageModule = Record<string, unknown> & {\n default?: AppPageComponent | null | undefined;\n};\ntype AppPageBoundaryOnError = (\n error: unknown,\n requestInfo: unknown,\n errorContext: unknown,\n) => unknown;\n\ntype AppFallbackRendererRootBoundaries<TModule extends AppPageModule = AppPageModule> = {\n rootForbiddenModule?: TModule | null;\n rootLayouts: readonly (TModule | null | undefined)[];\n rootNotFoundModule?: TModule | null;\n rootUnauthorizedModule?: TModule | null;\n};\n\ntype AppFallbackRendererFontProviders = {\n buildFontLinkHeader: (preloads: readonly AppPageFontPreload[] | null | undefined) => string;\n getFontLinks: () => string[];\n getFontPreloads: () => AppPageFontPreload[];\n getFontStyles: () => string[];\n};\n\ntype AppFallbackRendererOptions<TModule extends AppPageModule = AppPageModule> = {\n clearRequestContext: () => void;\n createRscOnErrorHandler: (\n request: Request,\n pathname: string,\n routePath: string,\n ) => AppPageBoundaryOnError;\n fontProviders: AppFallbackRendererFontProviders;\n getNavigationContext: () => unknown;\n globalErrorModule?: TModule | null;\n makeThenableParams: (params: AppPageParams) => unknown;\n metadataRoutes: MetadataFileRoute[];\n resolveChildSegments: (\n routeSegments: readonly string[],\n treePosition: number,\n params: AppPageParams,\n ) => string[];\n rootBoundaries: AppFallbackRendererRootBoundaries<TModule>;\n rscRenderer: (\n element: ReactNode | AppElements,\n options: { onError: AppPageBoundaryOnError },\n ) => ReadableStream<Uint8Array>;\n sanitizer: (error: Error) => Error;\n ssrLoader: () => Promise<AppPageSsrHandler>;\n};\n\ntype AppFallbackRenderer<TModule extends AppPageModule = AppPageModule> = {\n renderErrorBoundary: (\n route: AppPageBoundaryRoute<TModule> | null,\n error: unknown,\n isRscRequest: boolean,\n request: Request,\n matchedParams: AppPageParams | undefined,\n scriptNonce: string | undefined,\n middlewareContext: AppPageMiddlewareContext,\n ) => Promise<Response | null>;\n renderHttpAccessFallback: (\n route: AppPageBoundaryRoute<TModule> | null,\n statusCode: number,\n isRscRequest: boolean,\n request: Request,\n opts: {\n boundaryComponent?: AppPageComponent | null;\n layouts?: readonly (TModule | null | undefined)[] | null;\n matchedParams?: AppPageParams;\n },\n scriptNonce: string | undefined,\n middlewareContext: AppPageMiddlewareContext,\n ) => Promise<Response | null>;\n renderNotFound: (\n route: AppPageBoundaryRoute<TModule> | null,\n isRscRequest: boolean,\n request: Request,\n matchedParams: AppPageParams | undefined,\n scriptNonce: string | undefined,\n middlewareContext: AppPageMiddlewareContext,\n ) => Promise<Response | null>;\n};\n\nconst EMPTY_MW_CTX: AppPageMiddlewareContext = { headers: null, status: null };\n\nexport function createAppFallbackRenderer<TModule extends AppPageModule>(\n options: AppFallbackRendererOptions<TModule>,\n): AppFallbackRenderer<TModule> {\n const {\n clearRequestContext,\n createRscOnErrorHandler: buildRscOnErrorHandler,\n fontProviders,\n getNavigationContext,\n globalErrorModule,\n makeThenableParams,\n metadataRoutes,\n resolveChildSegments,\n rootBoundaries,\n rscRenderer,\n sanitizer,\n ssrLoader,\n } = options;\n\n const { rootForbiddenModule, rootLayouts, rootNotFoundModule, rootUnauthorizedModule } =\n rootBoundaries;\n\n return {\n renderHttpAccessFallback(\n route,\n statusCode,\n isRscRequest,\n request,\n opts,\n scriptNonce,\n middlewareContext,\n ) {\n return renderAppPageHttpAccessFallback({\n boundaryComponent: opts?.boundaryComponent ?? null,\n buildFontLinkHeader: fontProviders.buildFontLinkHeader,\n clearRequestContext,\n createRscOnErrorHandler(pathname, routePath) {\n return buildRscOnErrorHandler(request, pathname, routePath);\n },\n getFontLinks: fontProviders.getFontLinks,\n getFontPreloads: fontProviders.getFontPreloads,\n getFontStyles: fontProviders.getFontStyles,\n getNavigationContext,\n globalErrorModule,\n isRscRequest,\n layoutModules: opts?.layouts ?? null,\n loadSsrHandler: ssrLoader,\n makeThenableParams,\n matchedParams: opts?.matchedParams ?? route?.params ?? {},\n middlewareContext: middlewareContext ?? EMPTY_MW_CTX,\n metadataRoutes,\n requestUrl: request.url,\n resolveChildSegments,\n rootForbiddenModule,\n rootLayouts,\n rootNotFoundModule,\n rootUnauthorizedModule,\n route,\n renderToReadableStream: rscRenderer,\n scriptNonce,\n statusCode,\n });\n },\n\n renderNotFound(route, isRscRequest, request, matchedParams, scriptNonce, middlewareContext) {\n return this.renderHttpAccessFallback(\n route,\n 404,\n isRscRequest,\n request,\n { matchedParams },\n scriptNonce,\n middlewareContext,\n );\n },\n\n renderErrorBoundary(\n route,\n error,\n isRscRequest,\n request,\n matchedParams,\n scriptNonce,\n middlewareContext,\n ) {\n return renderAppPageErrorBoundary({\n buildFontLinkHeader: fontProviders.buildFontLinkHeader,\n clearRequestContext,\n createRscOnErrorHandler(pathname, routePath) {\n return buildRscOnErrorHandler(request, pathname, routePath);\n },\n error,\n getFontLinks: fontProviders.getFontLinks,\n getFontPreloads: fontProviders.getFontPreloads,\n getFontStyles: fontProviders.getFontStyles,\n getNavigationContext,\n globalErrorModule,\n isRscRequest,\n loadSsrHandler: ssrLoader,\n makeThenableParams,\n matchedParams: matchedParams ?? route?.params ?? {},\n middlewareContext: middlewareContext ?? EMPTY_MW_CTX,\n metadataRoutes,\n requestUrl: request.url,\n resolveChildSegments,\n rootLayouts,\n route,\n renderToReadableStream: rscRenderer,\n sanitizeErrorForClient: sanitizer,\n scriptNonce,\n });\n },\n };\n}\n"],"mappings":";;AAiGA,MAAM,eAAyC;CAAE,SAAS;CAAM,QAAQ;CAAM;AAE9E,SAAgB,0BACd,SAC8B;CAC9B,MAAM,EACJ,qBACA,yBAAyB,wBACzB,eACA,sBACA,mBACA,oBACA,gBACA,sBACA,gBACA,aACA,WACA,cACE;CAEJ,MAAM,EAAE,qBAAqB,aAAa,oBAAoB,2BAC5D;AAEF,QAAO;EACL,yBACE,OACA,YACA,cACA,SACA,MACA,aACA,mBACA;AACA,UAAO,gCAAgC;IACrC,mBAAmB,MAAM,qBAAqB;IAC9C,qBAAqB,cAAc;IACnC;IACA,wBAAwB,UAAU,WAAW;AAC3C,YAAO,uBAAuB,SAAS,UAAU,UAAU;;IAE7D,cAAc,cAAc;IAC5B,iBAAiB,cAAc;IAC/B,eAAe,cAAc;IAC7B;IACA;IACA;IACA,eAAe,MAAM,WAAW;IAChC,gBAAgB;IAChB;IACA,eAAe,MAAM,iBAAiB,OAAO,UAAU,EAAE;IACzD,mBAAmB,qBAAqB;IACxC;IACA,YAAY,QAAQ;IACpB;IACA;IACA;IACA;IACA;IACA;IACA,wBAAwB;IACxB;IACA;IACD,CAAC;;EAGJ,eAAe,OAAO,cAAc,SAAS,eAAe,aAAa,mBAAmB;AAC1F,UAAO,KAAK,yBACV,OACA,KACA,cACA,SACA,EAAE,eAAe,EACjB,aACA,kBACD;;EAGH,oBACE,OACA,OACA,cACA,SACA,eACA,aACA,mBACA;AACA,UAAO,2BAA2B;IAChC,qBAAqB,cAAc;IACnC;IACA,wBAAwB,UAAU,WAAW;AAC3C,YAAO,uBAAuB,SAAS,UAAU,UAAU;;IAE7D;IACA,cAAc,cAAc;IAC5B,iBAAiB,cAAc;IAC/B,eAAe,cAAc;IAC7B;IACA;IACA;IACA,gBAAgB;IAChB;IACA,eAAe,iBAAiB,OAAO,UAAU,EAAE;IACnD,mBAAmB,qBAAqB;IACxC;IACA,YAAY,QAAQ;IACpB;IACA;IACA;IACA,wBAAwB;IACxB,wBAAwB;IACxB;IACD,CAAC;;EAEL"}
@@ -0,0 +1,7 @@
1
+ import { AsyncLocalStorage } from "node:async_hooks";
2
+
3
+ //#region src/server/app-hook-warning-suppression.d.ts
4
+ declare const suppressHookWarningAls: AsyncLocalStorage<boolean>;
5
+ //#endregion
6
+ export { suppressHookWarningAls };
7
+ //# sourceMappingURL=app-hook-warning-suppression.d.ts.map
@@ -0,0 +1,12 @@
1
+ import { AsyncLocalStorage } from "node:async_hooks";
2
+ //#region src/server/app-hook-warning-suppression.ts
3
+ const suppressHookWarningAls = new AsyncLocalStorage();
4
+ const _origConsoleError = console.error;
5
+ console.error = (...args) => {
6
+ if (suppressHookWarningAls.getStore() === true && typeof args[0] === "string" && args[0].includes("Invalid hook call")) return;
7
+ _origConsoleError.apply(console, args);
8
+ };
9
+ //#endregion
10
+ export { suppressHookWarningAls };
11
+
12
+ //# sourceMappingURL=app-hook-warning-suppression.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app-hook-warning-suppression.js","names":[],"sources":["../../src/server/app-hook-warning-suppression.ts"],"sourcesContent":["import { AsyncLocalStorage } from \"node:async_hooks\";\n\nexport const suppressHookWarningAls = new AsyncLocalStorage<boolean>();\n\nconst _origConsoleError = console.error;\nconsole.error = (...args: unknown[]) => {\n if (\n suppressHookWarningAls.getStore() === true &&\n typeof args[0] === \"string\" &&\n args[0].includes(\"Invalid hook call\")\n )\n return;\n _origConsoleError.apply(console, args);\n};\n"],"mappings":";;AAEA,MAAa,yBAAyB,IAAI,mBAA4B;AAEtE,MAAM,oBAAoB,QAAQ;AAClC,QAAQ,SAAS,GAAG,SAAoB;AACtC,KACE,uBAAuB,UAAU,KAAK,QACtC,OAAO,KAAK,OAAO,YACnB,KAAK,GAAG,SAAS,oBAAoB,CAErC;AACF,mBAAkB,MAAM,SAAS,KAAK"}
@@ -24,9 +24,10 @@ type ApplyAppMiddlewareResult = {
24
24
  kind: "response";
25
25
  response: Response;
26
26
  };
27
+ declare const FLIGHT_HEADERS: readonly string[];
27
28
  declare function isExternalMiddlewareRewrite(rewriteUrl: string, request: Request): boolean;
28
29
  declare function proxyExternalMiddlewareRewrite(request: Request, rewriteUrl: string, context: AppMiddlewareContext): Promise<Response>;
29
30
  declare function applyAppMiddleware(options: ApplyAppMiddlewareOptions): Promise<ApplyAppMiddlewareResult>;
30
31
  //#endregion
31
- export { AppMiddlewareContext, ApplyAppMiddlewareOptions, ApplyAppMiddlewareResult, applyAppMiddleware, isExternalMiddlewareRewrite, proxyExternalMiddlewareRewrite };
32
+ export { AppMiddlewareContext, ApplyAppMiddlewareOptions, ApplyAppMiddlewareResult, FLIGHT_HEADERS, applyAppMiddleware, isExternalMiddlewareRewrite, proxyExternalMiddlewareRewrite };
32
33
  //# sourceMappingURL=app-middleware.d.ts.map
@@ -1,14 +1,31 @@
1
1
  import { buildRequestHeadersFromMiddlewareResponse } from "./middleware-request-headers.js";
2
2
  import { isExternalUrl, proxyExternalRequest } from "../config/config-matchers.js";
3
- import { processMiddlewareHeaders } from "./request-pipeline.js";
3
+ import { internalServerErrorResponse } from "./http-error-responses.js";
4
+ import { cloneRequestWithHeaders, processMiddlewareHeaders } from "./request-pipeline.js";
4
5
  import { executeMiddleware } from "./middleware-runtime.js";
5
6
  import { applyMiddlewareRequestHeaders, setHeadersContext } from "../shims/headers.js";
6
7
  import { setNavigationContext } from "../shims/navigation.js";
7
8
  import { mergeMiddlewareResponseHeaders } from "./middleware-response-headers.js";
8
9
  //#region src/server/app-middleware.ts
10
+ const FLIGHT_HEADERS = [
11
+ "rsc",
12
+ "next-router-state-tree",
13
+ "next-router-prefetch",
14
+ "next-hmr-refresh",
15
+ "next-router-segment-prefetch"
16
+ ];
17
+ const FLIGHT_HEADER_SET = new Set(FLIGHT_HEADERS);
9
18
  function isForwardedMiddlewareContext(value) {
10
19
  return !!value && typeof value === "object";
11
20
  }
21
+ function requestWithoutFlightHeaders(request) {
22
+ let hasFlightHeader = false;
23
+ const headers = new Headers();
24
+ for (const [key, value] of request.headers) if (FLIGHT_HEADER_SET.has(key.toLowerCase())) hasFlightHeader = true;
25
+ else headers.append(key, value);
26
+ if (!hasFlightHeader) return request;
27
+ return cloneRequestWithHeaders(request.body ? request.clone() : request, headers);
28
+ }
12
29
  function appendForwardedHeader(headers, value) {
13
30
  if (!Array.isArray(value) || value.length < 2) return;
14
31
  const key = value[0];
@@ -46,10 +63,15 @@ async function proxyExternalMiddlewareRewrite(request, rewriteUrl, context) {
46
63
  setHeadersContext(null);
47
64
  setNavigationContext(null);
48
65
  const proxyResponse = await proxyExternalRequest(proxyRequest, rewriteUrl);
49
- if (!context.headers) return proxyResponse;
66
+ const headers = new Headers(proxyResponse.headers);
67
+ processMiddlewareHeaders(headers);
68
+ if (!context.headers) return new Response(proxyResponse.body, {
69
+ status: proxyResponse.status,
70
+ statusText: proxyResponse.statusText,
71
+ headers
72
+ });
50
73
  const middlewareHeaders = new Headers(context.headers);
51
74
  processMiddlewareHeaders(middlewareHeaders);
52
- const headers = new Headers(proxyResponse.headers);
53
75
  mergeMiddlewareResponseHeaders(headers, middlewareHeaders);
54
76
  return new Response(proxyResponse.body, {
55
77
  status: proxyResponse.status,
@@ -81,14 +103,15 @@ function applyForwardedMiddlewareContext(request, context) {
81
103
  }
82
104
  async function applyAppMiddleware(options) {
83
105
  const forwarded = applyForwardedMiddlewareContext(options.request, options.context);
106
+ const middlewareRequest = requestWithoutFlightHeaders(options.request);
84
107
  let cleanPathname = options.cleanPathname;
85
108
  let search = null;
86
109
  if (forwarded.rewriteUrl) try {
87
- if (isExternalMiddlewareRewrite(forwarded.rewriteUrl, options.request)) return {
110
+ if (isExternalMiddlewareRewrite(forwarded.rewriteUrl, middlewareRequest)) return {
88
111
  kind: "response",
89
- response: await proxyExternalMiddlewareRewrite(options.request, forwarded.rewriteUrl, options.context)
112
+ response: await proxyExternalMiddlewareRewrite(middlewareRequest, forwarded.rewriteUrl, options.context)
90
113
  };
91
- const rewriteParsed = new URL(forwarded.rewriteUrl, options.request.url);
114
+ const rewriteParsed = new URL(forwarded.rewriteUrl, middlewareRequest.url);
92
115
  cleanPathname = rewriteParsed.pathname;
93
116
  search = rewriteParsed.search;
94
117
  } catch (e) {
@@ -102,7 +125,7 @@ async function applyAppMiddleware(options) {
102
125
  isProxy: options.isProxy,
103
126
  module: options.module,
104
127
  normalizedPathname: cleanPathname,
105
- request: options.request
128
+ request: middlewareRequest
106
129
  });
107
130
  if (!result.continue) {
108
131
  if (result.redirectUrl) return {
@@ -115,7 +138,7 @@ async function applyAppMiddleware(options) {
115
138
  };
116
139
  return {
117
140
  kind: "response",
118
- response: new Response("Internal Server Error", { status: 500 })
141
+ response: internalServerErrorResponse()
119
142
  };
120
143
  }
121
144
  if (result.responseHeaders) options.context.headers = new Headers(result.responseHeaders);
@@ -123,9 +146,9 @@ async function applyAppMiddleware(options) {
123
146
  if (result.rewriteStatus !== void 0) options.context.status = result.rewriteStatus;
124
147
  if (isExternalUrl(result.rewriteUrl)) return {
125
148
  kind: "response",
126
- response: await proxyExternalMiddlewareRewrite(options.request, result.rewriteUrl, options.context)
149
+ response: await proxyExternalMiddlewareRewrite(middlewareRequest, result.rewriteUrl, options.context)
127
150
  };
128
- const rewriteParsed = new URL(result.rewriteUrl, options.request.url);
151
+ const rewriteParsed = new URL(result.rewriteUrl, middlewareRequest.url);
129
152
  cleanPathname = rewriteParsed.pathname;
130
153
  search = rewriteParsed.search;
131
154
  }
@@ -142,6 +165,6 @@ async function applyAppMiddleware(options) {
142
165
  };
143
166
  }
144
167
  //#endregion
145
- export { applyAppMiddleware, isExternalMiddlewareRewrite, proxyExternalMiddlewareRewrite };
168
+ export { FLIGHT_HEADERS, applyAppMiddleware, isExternalMiddlewareRewrite, proxyExternalMiddlewareRewrite };
146
169
 
147
170
  //# sourceMappingURL=app-middleware.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"app-middleware.js","names":[],"sources":["../../src/server/app-middleware.ts"],"sourcesContent":["import type { NextI18nConfig } from \"../config/next-config.js\";\nimport { isExternalUrl, proxyExternalRequest } from \"../config/config-matchers.js\";\nimport { applyMiddlewareRequestHeaders, setHeadersContext } from \"vinext/shims/headers\";\nimport { setNavigationContext } from \"vinext/shims/navigation\";\nimport { buildRequestHeadersFromMiddlewareResponse } from \"./middleware-request-headers.js\";\nimport { mergeMiddlewareResponseHeaders } from \"./middleware-response-headers.js\";\nimport { executeMiddleware, type MiddlewareModule } from \"./middleware-runtime.js\";\nimport { processMiddlewareHeaders } from \"./request-pipeline.js\";\n\nexport type AppMiddlewareContext = {\n headers: Headers | null;\n requestHeaders: Headers | null;\n status: number | null;\n};\n\nexport type ApplyAppMiddlewareOptions = {\n basePath?: string;\n cleanPathname: string;\n context: AppMiddlewareContext;\n i18nConfig?: NextI18nConfig | null;\n isProxy: boolean;\n module: MiddlewareModule;\n request: Request;\n};\n\nexport type ApplyAppMiddlewareResult =\n | {\n kind: \"continue\";\n cleanPathname: string;\n search: string | null;\n }\n | {\n kind: \"response\";\n response: Response;\n };\n\ntype ForwardedMiddlewareContext = {\n h?: unknown;\n r?: unknown;\n s?: unknown;\n};\n\nfunction isForwardedMiddlewareContext(value: unknown): value is ForwardedMiddlewareContext {\n return !!value && typeof value === \"object\";\n}\n\nfunction appendForwardedHeader(headers: Headers, value: unknown): void {\n if (!Array.isArray(value) || value.length < 2) return;\n const key = value[0];\n const headerValue = value[1];\n if (typeof key === \"string\" && typeof headerValue === \"string\") {\n headers.append(key, headerValue);\n }\n}\n\nfunction responseFromMiddlewareRedirect(result: {\n redirectStatus?: number;\n redirectUrl?: string;\n response?: Response;\n responseHeaders?: Headers;\n}): Response {\n if (result.response) return result.response;\n\n const headers = new Headers(result.responseHeaders);\n if (result.redirectUrl) {\n headers.set(\"Location\", result.redirectUrl);\n }\n return new Response(null, {\n status: result.redirectStatus ?? 307,\n headers,\n });\n}\n\nexport function isExternalMiddlewareRewrite(rewriteUrl: string, request: Request): boolean {\n const rewriteParsed = new URL(rewriteUrl, request.url);\n return rewriteParsed.origin !== new URL(request.url).origin;\n}\n\nfunction requestWithMiddlewareRequestHeaders(\n request: Request,\n middlewareHeaders: Headers | null,\n): Request {\n const nextHeaders = middlewareHeaders\n ? buildRequestHeadersFromMiddlewareResponse(request.headers, middlewareHeaders)\n : null;\n if (!nextHeaders) return request;\n\n const init: RequestInit = {\n method: request.method,\n headers: nextHeaders,\n body: request.body,\n };\n if (request.body) {\n Object.defineProperty(init, \"duplex\", { value: \"half\", enumerable: true });\n }\n\n return new Request(request.url, init);\n}\n\nexport async function proxyExternalMiddlewareRewrite(\n request: Request,\n rewriteUrl: string,\n context: AppMiddlewareContext,\n): Promise<Response> {\n const proxyRequest = requestWithMiddlewareRequestHeaders(\n request,\n context.requestHeaders ?? context.headers,\n );\n setHeadersContext(null);\n setNavigationContext(null);\n\n const proxyResponse = await proxyExternalRequest(proxyRequest, rewriteUrl);\n if (!context.headers) return proxyResponse;\n\n const middlewareHeaders = new Headers(context.headers);\n processMiddlewareHeaders(middlewareHeaders);\n const headers = new Headers(proxyResponse.headers);\n mergeMiddlewareResponseHeaders(headers, middlewareHeaders);\n return new Response(proxyResponse.body, {\n status: proxyResponse.status,\n statusText: proxyResponse.statusText,\n headers,\n });\n}\n\nfunction applyForwardedMiddlewareContext(\n request: Request,\n context: AppMiddlewareContext,\n): { applied: boolean; rewriteUrl?: string } {\n if (process.env.NODE_ENV === \"production\") {\n return { applied: false };\n }\n\n const header = request.headers.get(\"x-vinext-mw-ctx\");\n if (!header) return { applied: false };\n\n try {\n const data = JSON.parse(header);\n if (!isForwardedMiddlewareContext(data)) return { applied: false };\n\n if (Array.isArray(data.h) && data.h.length > 0) {\n context.headers = new Headers();\n for (const entry of data.h) {\n appendForwardedHeader(context.headers, entry);\n }\n }\n if (typeof data.s === \"number\") {\n context.status = data.s;\n }\n if (typeof data.r === \"string\" && data.r.length > 0) {\n return { applied: true, rewriteUrl: data.r };\n }\n return { applied: true };\n } catch (e) {\n console.error(\"[vinext] Failed to parse forwarded middleware context:\", e);\n return { applied: false };\n }\n}\n\nexport async function applyAppMiddleware(\n options: ApplyAppMiddlewareOptions,\n): Promise<ApplyAppMiddlewareResult> {\n const forwarded = applyForwardedMiddlewareContext(options.request, options.context);\n let cleanPathname = options.cleanPathname;\n let search: string | null = null;\n\n if (forwarded.rewriteUrl) {\n try {\n if (isExternalMiddlewareRewrite(forwarded.rewriteUrl, options.request)) {\n return {\n kind: \"response\",\n response: await proxyExternalMiddlewareRewrite(\n options.request,\n forwarded.rewriteUrl,\n options.context,\n ),\n };\n }\n const rewriteParsed = new URL(forwarded.rewriteUrl, options.request.url);\n cleanPathname = rewriteParsed.pathname;\n search = rewriteParsed.search;\n } catch (e) {\n console.error(\"[vinext] Failed to apply forwarded middleware rewrite:\", e);\n forwarded.applied = false;\n }\n }\n\n if (!forwarded.applied) {\n const result = await executeMiddleware({\n basePath: options.basePath,\n i18nConfig: options.i18nConfig,\n isProxy: options.isProxy,\n module: options.module,\n normalizedPathname: cleanPathname,\n request: options.request,\n });\n\n if (!result.continue) {\n if (result.redirectUrl) {\n return { kind: \"response\", response: responseFromMiddlewareRedirect(result) };\n }\n if (result.response) {\n return { kind: \"response\", response: result.response };\n }\n return { kind: \"response\", response: new Response(\"Internal Server Error\", { status: 500 }) };\n }\n\n if (result.responseHeaders) {\n options.context.headers = new Headers(result.responseHeaders);\n }\n\n if (result.rewriteUrl) {\n if (result.rewriteStatus !== undefined) {\n options.context.status = result.rewriteStatus;\n }\n if (isExternalUrl(result.rewriteUrl)) {\n return {\n kind: \"response\",\n response: await proxyExternalMiddlewareRewrite(\n options.request,\n result.rewriteUrl,\n options.context,\n ),\n };\n }\n const rewriteParsed = new URL(result.rewriteUrl, options.request.url);\n cleanPathname = rewriteParsed.pathname;\n search = rewriteParsed.search;\n }\n }\n\n if (options.context.headers) {\n options.context.requestHeaders = new Headers(options.context.headers);\n applyMiddlewareRequestHeaders(options.context.headers);\n processMiddlewareHeaders(options.context.headers);\n }\n\n return { kind: \"continue\", cleanPathname, search };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"app-middleware.js","names":[],"sources":["../../src/server/app-middleware.ts"],"sourcesContent":["import type { NextI18nConfig } from \"../config/next-config.js\";\nimport { isExternalUrl, proxyExternalRequest } from \"../config/config-matchers.js\";\nimport { applyMiddlewareRequestHeaders, setHeadersContext } from \"vinext/shims/headers\";\nimport { setNavigationContext } from \"vinext/shims/navigation\";\nimport { buildRequestHeadersFromMiddlewareResponse } from \"./middleware-request-headers.js\";\nimport { mergeMiddlewareResponseHeaders } from \"./middleware-response-headers.js\";\nimport { executeMiddleware, type MiddlewareModule } from \"./middleware-runtime.js\";\nimport { cloneRequestWithHeaders, processMiddlewareHeaders } from \"./request-pipeline.js\";\nimport { internalServerErrorResponse } from \"./http-error-responses.js\";\n\nexport type AppMiddlewareContext = {\n headers: Headers | null;\n requestHeaders: Headers | null;\n status: number | null;\n};\n\nexport type ApplyAppMiddlewareOptions = {\n basePath?: string;\n cleanPathname: string;\n context: AppMiddlewareContext;\n i18nConfig?: NextI18nConfig | null;\n isProxy: boolean;\n module: MiddlewareModule;\n request: Request;\n};\n\nexport type ApplyAppMiddlewareResult =\n | {\n kind: \"continue\";\n cleanPathname: string;\n search: string | null;\n }\n | {\n kind: \"response\";\n response: Response;\n };\n\ntype ForwardedMiddlewareContext = {\n h?: unknown;\n r?: unknown;\n s?: unknown;\n};\n\nexport const FLIGHT_HEADERS: readonly string[] = [\n \"rsc\",\n \"next-router-state-tree\",\n \"next-router-prefetch\",\n \"next-hmr-refresh\",\n \"next-router-segment-prefetch\",\n];\n\nconst FLIGHT_HEADER_SET = new Set(FLIGHT_HEADERS);\n\nfunction isForwardedMiddlewareContext(value: unknown): value is ForwardedMiddlewareContext {\n return !!value && typeof value === \"object\";\n}\n\nfunction requestWithoutFlightHeaders(request: Request): Request {\n let hasFlightHeader = false;\n const headers = new Headers();\n\n for (const [key, value] of request.headers) {\n if (FLIGHT_HEADER_SET.has(key.toLowerCase())) {\n hasFlightHeader = true;\n } else {\n headers.append(key, value);\n }\n }\n\n if (!hasFlightHeader) return request;\n const source = request.body ? request.clone() : request;\n return cloneRequestWithHeaders(source, headers);\n}\n\nfunction appendForwardedHeader(headers: Headers, value: unknown): void {\n if (!Array.isArray(value) || value.length < 2) return;\n const key = value[0];\n const headerValue = value[1];\n if (typeof key === \"string\" && typeof headerValue === \"string\") {\n headers.append(key, headerValue);\n }\n}\n\nfunction responseFromMiddlewareRedirect(result: {\n redirectStatus?: number;\n redirectUrl?: string;\n response?: Response;\n responseHeaders?: Headers;\n}): Response {\n if (result.response) return result.response;\n\n const headers = new Headers(result.responseHeaders);\n if (result.redirectUrl) {\n headers.set(\"Location\", result.redirectUrl);\n }\n return new Response(null, {\n status: result.redirectStatus ?? 307,\n headers,\n });\n}\n\nexport function isExternalMiddlewareRewrite(rewriteUrl: string, request: Request): boolean {\n const rewriteParsed = new URL(rewriteUrl, request.url);\n return rewriteParsed.origin !== new URL(request.url).origin;\n}\n\nfunction requestWithMiddlewareRequestHeaders(\n request: Request,\n middlewareHeaders: Headers | null,\n): Request {\n const nextHeaders = middlewareHeaders\n ? buildRequestHeadersFromMiddlewareResponse(request.headers, middlewareHeaders)\n : null;\n if (!nextHeaders) return request;\n\n const init: RequestInit = {\n method: request.method,\n headers: nextHeaders,\n body: request.body,\n };\n if (request.body) {\n Object.defineProperty(init, \"duplex\", { value: \"half\", enumerable: true });\n }\n\n return new Request(request.url, init);\n}\n\nexport async function proxyExternalMiddlewareRewrite(\n request: Request,\n rewriteUrl: string,\n context: AppMiddlewareContext,\n): Promise<Response> {\n const proxyRequest = requestWithMiddlewareRequestHeaders(\n request,\n context.requestHeaders ?? context.headers,\n );\n setHeadersContext(null);\n setNavigationContext(null);\n\n const proxyResponse = await proxyExternalRequest(proxyRequest, rewriteUrl);\n const headers = new Headers(proxyResponse.headers);\n processMiddlewareHeaders(headers);\n\n if (!context.headers) {\n return new Response(proxyResponse.body, {\n status: proxyResponse.status,\n statusText: proxyResponse.statusText,\n headers,\n });\n }\n\n const middlewareHeaders = new Headers(context.headers);\n processMiddlewareHeaders(middlewareHeaders);\n mergeMiddlewareResponseHeaders(headers, middlewareHeaders);\n return new Response(proxyResponse.body, {\n status: proxyResponse.status,\n statusText: proxyResponse.statusText,\n headers,\n });\n}\n\nfunction applyForwardedMiddlewareContext(\n request: Request,\n context: AppMiddlewareContext,\n): { applied: boolean; rewriteUrl?: string } {\n if (process.env.NODE_ENV === \"production\") {\n return { applied: false };\n }\n\n const header = request.headers.get(\"x-vinext-mw-ctx\");\n if (!header) return { applied: false };\n\n try {\n const data = JSON.parse(header);\n if (!isForwardedMiddlewareContext(data)) return { applied: false };\n\n if (Array.isArray(data.h) && data.h.length > 0) {\n context.headers = new Headers();\n for (const entry of data.h) {\n appendForwardedHeader(context.headers, entry);\n }\n }\n if (typeof data.s === \"number\") {\n context.status = data.s;\n }\n if (typeof data.r === \"string\" && data.r.length > 0) {\n return { applied: true, rewriteUrl: data.r };\n }\n return { applied: true };\n } catch (e) {\n console.error(\"[vinext] Failed to parse forwarded middleware context:\", e);\n return { applied: false };\n }\n}\n\nexport async function applyAppMiddleware(\n options: ApplyAppMiddlewareOptions,\n): Promise<ApplyAppMiddlewareResult> {\n const forwarded = applyForwardedMiddlewareContext(options.request, options.context);\n const middlewareRequest = requestWithoutFlightHeaders(options.request);\n let cleanPathname = options.cleanPathname;\n let search: string | null = null;\n\n if (forwarded.rewriteUrl) {\n try {\n if (isExternalMiddlewareRewrite(forwarded.rewriteUrl, middlewareRequest)) {\n return {\n kind: \"response\",\n response: await proxyExternalMiddlewareRewrite(\n middlewareRequest,\n forwarded.rewriteUrl,\n options.context,\n ),\n };\n }\n const rewriteParsed = new URL(forwarded.rewriteUrl, middlewareRequest.url);\n cleanPathname = rewriteParsed.pathname;\n search = rewriteParsed.search;\n } catch (e) {\n console.error(\"[vinext] Failed to apply forwarded middleware rewrite:\", e);\n forwarded.applied = false;\n }\n }\n\n if (!forwarded.applied) {\n const result = await executeMiddleware({\n basePath: options.basePath,\n i18nConfig: options.i18nConfig,\n isProxy: options.isProxy,\n module: options.module,\n normalizedPathname: cleanPathname,\n request: middlewareRequest,\n });\n\n if (!result.continue) {\n if (result.redirectUrl) {\n return { kind: \"response\", response: responseFromMiddlewareRedirect(result) };\n }\n if (result.response) {\n return { kind: \"response\", response: result.response };\n }\n return { kind: \"response\", response: internalServerErrorResponse() };\n }\n\n if (result.responseHeaders) {\n options.context.headers = new Headers(result.responseHeaders);\n }\n\n if (result.rewriteUrl) {\n if (result.rewriteStatus !== undefined) {\n options.context.status = result.rewriteStatus;\n }\n if (isExternalUrl(result.rewriteUrl)) {\n return {\n kind: \"response\",\n response: await proxyExternalMiddlewareRewrite(\n middlewareRequest,\n result.rewriteUrl,\n options.context,\n ),\n };\n }\n const rewriteParsed = new URL(result.rewriteUrl, middlewareRequest.url);\n cleanPathname = rewriteParsed.pathname;\n search = rewriteParsed.search;\n }\n }\n\n if (options.context.headers) {\n options.context.requestHeaders = new Headers(options.context.headers);\n applyMiddlewareRequestHeaders(options.context.headers);\n processMiddlewareHeaders(options.context.headers);\n }\n\n return { kind: \"continue\", cleanPathname, search };\n}\n"],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ //#region src/server/app-mounted-slots-header.d.ts
2
+ /**
3
+ * Normalize the `x-vinext-mounted-slots` header for request handling and cache keying.
4
+ *
5
+ * The browser sends mounted slot ids as a space-separated list in the order slots were
6
+ * rendered, which changes across navigations. This normalizes to a canonical form
7
+ * (sorted, deduplicated) so equivalent slot sets map to the same RSC cache entry.
8
+ *
9
+ * Consumed by:
10
+ * - app-rsc-request-normalization (request lifecycle, reads incoming header)
11
+ * - app-elements (outgoing x-vinext-mounted-slots construction)
12
+ * - isr-cache (RSC cache key generation)
13
+ */
14
+ declare function normalizeMountedSlotsHeader(raw: string | null | undefined): string | null;
15
+ //#endregion
16
+ export { normalizeMountedSlotsHeader };
17
+ //# sourceMappingURL=app-mounted-slots-header.d.ts.map
@@ -0,0 +1,21 @@
1
+ //#region src/server/app-mounted-slots-header.ts
2
+ /**
3
+ * Normalize the `x-vinext-mounted-slots` header for request handling and cache keying.
4
+ *
5
+ * The browser sends mounted slot ids as a space-separated list in the order slots were
6
+ * rendered, which changes across navigations. This normalizes to a canonical form
7
+ * (sorted, deduplicated) so equivalent slot sets map to the same RSC cache entry.
8
+ *
9
+ * Consumed by:
10
+ * - app-rsc-request-normalization (request lifecycle, reads incoming header)
11
+ * - app-elements (outgoing x-vinext-mounted-slots construction)
12
+ * - isr-cache (RSC cache key generation)
13
+ */
14
+ function normalizeMountedSlotsHeader(raw) {
15
+ if (!raw) return null;
16
+ return Array.from(new Set(raw.split(/\s+/).filter(Boolean))).sort().join(" ") || null;
17
+ }
18
+ //#endregion
19
+ export { normalizeMountedSlotsHeader };
20
+
21
+ //# sourceMappingURL=app-mounted-slots-header.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app-mounted-slots-header.js","names":[],"sources":["../../src/server/app-mounted-slots-header.ts"],"sourcesContent":["/**\n * Normalize the `x-vinext-mounted-slots` header for request handling and cache keying.\n *\n * The browser sends mounted slot ids as a space-separated list in the order slots were\n * rendered, which changes across navigations. This normalizes to a canonical form\n * (sorted, deduplicated) so equivalent slot sets map to the same RSC cache entry.\n *\n * Consumed by:\n * - app-rsc-request-normalization (request lifecycle, reads incoming header)\n * - app-elements (outgoing x-vinext-mounted-slots construction)\n * - isr-cache (RSC cache key generation)\n */\nexport function normalizeMountedSlotsHeader(raw: string | null | undefined): string | null {\n if (!raw) return null;\n const normalized = Array.from(new Set(raw.split(/\\s+/).filter(Boolean)))\n .sort()\n .join(\" \");\n return normalized || null;\n}\n"],"mappings":";;;;;;;;;;;;;AAYA,SAAgB,4BAA4B,KAA+C;AACzF,KAAI,CAAC,IAAK,QAAO;AAIjB,QAHmB,MAAM,KAAK,IAAI,IAAI,IAAI,MAAM,MAAM,CAAC,OAAO,QAAQ,CAAC,CAAC,CACrE,MAAM,CACN,KAAK,IAAI,IACS"}
@@ -1,8 +1,8 @@
1
1
  import { MetadataFileRoute } from "./metadata-routes.js";
2
- import { AppElements } from "./app-elements.js";
2
+ import { AppElements } from "./app-elements-wire.js";
3
+ import { AppPageParams } from "./app-page-boundary.js";
3
4
  import { AppPageFontPreload } from "./app-page-execution.js";
4
5
  import { AppPageMiddlewareContext } from "./app-page-response.js";
5
- import { AppPageParams } from "./app-page-boundary.js";
6
6
  import { AppPageSsrHandler } from "./app-page-stream.js";
7
7
  import { ComponentType, ReactNode } from "react";
8
8
 
@@ -65,5 +65,5 @@ type RenderAppPageErrorBoundaryOptions<TModule extends AppPageModule = AppPageMo
65
65
  declare function renderAppPageHttpAccessFallback<TModule extends AppPageModule>(options: RenderAppPageHttpAccessFallbackOptions<TModule>): Promise<Response | null>;
66
66
  declare function renderAppPageErrorBoundary<TModule extends AppPageModule>(options: RenderAppPageErrorBoundaryOptions<TModule>): Promise<Response | null>;
67
67
  //#endregion
68
- export { renderAppPageErrorBoundary, renderAppPageHttpAccessFallback };
68
+ export { AppPageBoundaryRoute, renderAppPageErrorBoundary, renderAppPageHttpAccessFallback };
69
69
  //# sourceMappingURL=app-page-boundary-render.d.ts.map
@@ -1,4 +1,5 @@
1
- import { APP_INTERCEPTION_CONTEXT_KEY, APP_ROOT_LAYOUT_KEY, APP_ROUTE_KEY, createAppPayloadRouteId } from "./app-elements.js";
1
+ import { AppElementsWire } from "./app-elements-wire.js";
2
+ import "./app-elements.js";
2
3
  import { ErrorBoundary } from "../shims/error-boundary.js";
3
4
  import { LayoutSegmentProvider } from "../shims/layout-segment-context.js";
4
5
  import { MetadataHead, ViewportHead } from "../shims/metadata.js";
@@ -69,11 +70,13 @@ function resolveHttpAccessFallbackHeadLayoutTreePositions(route, layoutModules)
69
70
  return route.layoutTreePositions?.slice(0, layoutModules.length);
70
71
  }
71
72
  function createAppPageBoundaryRscPayload(options) {
72
- const routeId = createAppPayloadRouteId(options.pathname, null);
73
+ const routeId = AppElementsWire.encodeRouteId(options.pathname, null);
73
74
  return {
74
- [APP_INTERCEPTION_CONTEXT_KEY]: null,
75
- [APP_ROUTE_KEY]: routeId,
76
- [APP_ROOT_LAYOUT_KEY]: resolveAppPageBoundaryRootLayoutTreePath(options.route),
75
+ ...AppElementsWire.createMetadataEntries({
76
+ interceptionContext: null,
77
+ rootLayoutTreePath: resolveAppPageBoundaryRootLayoutTreePath(options.route),
78
+ routeId
79
+ }),
77
80
  [routeId]: options.element
78
81
  };
79
82
  }
@@ -1 +1 @@
1
- {"version":3,"file":"app-page-boundary-render.js","names":[],"sources":["../../src/server/app-page-boundary-render.ts"],"sourcesContent":["import { Fragment, createElement, type ComponentType, type ReactNode } from \"react\";\nimport { buildClientHookErrorMessage } from \"vinext/shims/client-hook-error\";\nimport { ErrorBoundary } from \"vinext/shims/error-boundary\";\nimport { LayoutSegmentProvider } from \"vinext/shims/layout-segment-context\";\nimport { MetadataHead, ViewportHead } from \"vinext/shims/metadata\";\nimport type { AppPageFontPreload } from \"./app-page-execution.js\";\nimport type { AppPageMiddlewareContext } from \"./app-page-response.js\";\nimport type { MetadataFileRoute } from \"./metadata-routes.js\";\nimport { resolveAppPageHead } from \"./app-page-head.js\";\nimport {\n renderAppPageBoundaryResponse,\n resolveAppPageErrorBoundary,\n resolveAppPageHttpAccessBoundaryComponent,\n wrapAppPageBoundaryElement,\n type AppPageParams,\n} from \"./app-page-boundary.js\";\nimport {\n createAppPageFontData,\n renderAppPageHtmlResponse,\n type AppPageSsrHandler,\n} from \"./app-page-stream.js\";\nimport {\n APP_INTERCEPTION_CONTEXT_KEY,\n APP_ROOT_LAYOUT_KEY,\n APP_ROUTE_KEY,\n createAppPayloadRouteId,\n type AppElements,\n} from \"./app-elements.js\";\nimport { createAppPageLayoutEntries } from \"./app-page-route-wiring.js\";\n\n// oxlint-disable-next-line @typescript-eslint/no-explicit-any\ntype AppPageComponent = ComponentType<any>;\ntype AppPageModule = Record<string, unknown> & {\n default?: AppPageComponent | null | undefined;\n};\ntype AppPageBoundaryOnError = (\n error: unknown,\n requestInfo: unknown,\n errorContext: unknown,\n) => unknown;\n\ntype AppPageBoundaryRscPayloadOptions<TModule extends AppPageModule = AppPageModule> = {\n element: ReactNode;\n pathname: string;\n route?: AppPageBoundaryRoute<TModule> | null;\n};\n\ntype AppPageBoundaryRoute<TModule extends AppPageModule = AppPageModule> = {\n error?: TModule | null;\n errors?: readonly (TModule | null | undefined)[] | null;\n forbidden?: TModule | null;\n layoutTreePositions?: readonly number[] | null;\n layouts?: readonly (TModule | null | undefined)[];\n notFound?: TModule | null;\n params?: AppPageParams;\n pattern?: string;\n routeSegments?: readonly string[];\n unauthorized?: TModule | null;\n};\n\ntype AppPageBoundaryRenderCommonOptions<TModule extends AppPageModule = AppPageModule> = {\n buildFontLinkHeader: (preloads: readonly AppPageFontPreload[] | null | undefined) => string;\n clearRequestContext: () => void;\n createRscOnErrorHandler: (pathname: string, routePath: string) => AppPageBoundaryOnError;\n getFontLinks: () => string[];\n getFontPreloads: () => AppPageFontPreload[];\n getFontStyles: () => string[];\n getNavigationContext: () => unknown;\n globalErrorModule?: TModule | null;\n isRscRequest: boolean;\n loadSsrHandler: () => Promise<AppPageSsrHandler>;\n makeThenableParams: (params: AppPageParams) => unknown;\n middlewareContext: AppPageMiddlewareContext;\n metadataRoutes: MetadataFileRoute[];\n renderToReadableStream: (\n element: ReactNode | AppElements,\n options: { onError: AppPageBoundaryOnError },\n ) => ReadableStream<Uint8Array>;\n requestUrl: string;\n resolveChildSegments: (\n routeSegments: readonly string[],\n treePosition: number,\n params: AppPageParams,\n ) => string[];\n rootLayouts: readonly (TModule | null | undefined)[];\n scriptNonce?: string;\n};\n\ntype RenderAppPageHttpAccessFallbackOptions<TModule extends AppPageModule = AppPageModule> = {\n boundaryComponent?: AppPageComponent | null;\n layoutModules?: readonly (TModule | null | undefined)[] | null;\n matchedParams: AppPageParams;\n rootForbiddenModule?: TModule | null;\n rootNotFoundModule?: TModule | null;\n rootUnauthorizedModule?: TModule | null;\n route?: AppPageBoundaryRoute<TModule> | null;\n statusCode: number;\n} & AppPageBoundaryRenderCommonOptions<TModule>;\n\ntype RenderAppPageErrorBoundaryOptions<TModule extends AppPageModule = AppPageModule> = {\n error: unknown;\n matchedParams?: AppPageParams | null;\n route?: AppPageBoundaryRoute<TModule> | null;\n sanitizeErrorForClient: (error: Error) => Error;\n} & AppPageBoundaryRenderCommonOptions<TModule>;\n\nfunction getDefaultExport<TModule extends AppPageModule>(\n module: TModule | null | undefined,\n): AppPageComponent | null {\n return module?.default ?? null;\n}\n\nfunction wrapRenderedBoundaryElement<TModule extends AppPageModule>(\n options: Pick<\n AppPageBoundaryRenderCommonOptions<TModule>,\n \"globalErrorModule\" | \"isRscRequest\" | \"makeThenableParams\" | \"resolveChildSegments\"\n > & {\n element: ReactNode;\n includeGlobalErrorBoundary: boolean;\n layoutModules: readonly (TModule | null | undefined)[];\n layoutTreePositions?: readonly number[] | null;\n matchedParams: AppPageParams;\n routeSegments?: readonly string[];\n skipLayoutWrapping?: boolean;\n },\n): ReactNode {\n return wrapAppPageBoundaryElement({\n element: options.element,\n getDefaultExport,\n globalErrorComponent: getDefaultExport(options.globalErrorModule),\n includeGlobalErrorBoundary: options.includeGlobalErrorBoundary,\n isRscRequest: options.isRscRequest,\n layoutModules: options.layoutModules,\n layoutTreePositions: options.layoutTreePositions,\n makeThenableParams: options.makeThenableParams,\n matchedParams: options.matchedParams,\n renderErrorBoundary(GlobalErrorComponent, children) {\n return createElement(ErrorBoundary, {\n fallback: GlobalErrorComponent,\n // oxlint-disable-next-line react/no-children-prop\n children,\n });\n },\n renderLayout(LayoutComponent, children, asyncParams) {\n return createElement(LayoutComponent as AppPageComponent, {\n // oxlint-disable-next-line react/no-children-prop\n children,\n params: asyncParams,\n });\n },\n renderLayoutSegmentProvider(segmentMap, children) {\n return createElement(\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n LayoutSegmentProvider as ComponentType<any>,\n { segmentMap },\n children,\n );\n },\n resolveChildSegments: options.resolveChildSegments,\n routeSegments: options.routeSegments ?? [],\n skipLayoutWrapping: options.skipLayoutWrapping,\n });\n}\n\nfunction resolveAppPageBoundaryRootLayoutTreePath<TModule extends AppPageModule>(\n route: AppPageBoundaryRoute<TModule> | null | undefined,\n): string | null {\n if (route?.layouts) {\n const rootLayoutEntry = createAppPageLayoutEntries({\n errors: route.errors,\n layoutTreePositions: route.layoutTreePositions,\n layouts: route.layouts,\n notFounds: null,\n routeSegments: route.routeSegments,\n })[0];\n\n if (rootLayoutEntry) {\n return rootLayoutEntry.treePath;\n }\n }\n\n // Without route tree metadata we cannot derive a canonical root layout tree path.\n // Returning null keeps boundary payloads soft-navigation compatible.\n return null;\n}\n\nfunction resolveHttpAccessFallbackHeadRouteSegments<TModule extends AppPageModule>(\n route: AppPageBoundaryRoute<TModule> | null | undefined,\n layoutModules: readonly (TModule | null | undefined)[],\n): readonly string[] | undefined {\n if (!route?.routeSegments) {\n return undefined;\n }\n\n if (!route.layouts || layoutModules.length >= route.layouts.length) {\n return route.routeSegments;\n }\n\n const lastIncludedLayoutIndex = layoutModules.length - 1;\n if (lastIncludedLayoutIndex < 0) {\n return [];\n }\n\n const segmentCount = route.layoutTreePositions?.[lastIncludedLayoutIndex] ?? 0;\n return route.routeSegments.slice(0, segmentCount);\n}\n\nfunction resolveHttpAccessFallbackHeadLayoutTreePositions<TModule extends AppPageModule>(\n route: AppPageBoundaryRoute<TModule> | null | undefined,\n layoutModules: readonly (TModule | null | undefined)[],\n): readonly number[] | null | undefined {\n if (!route?.layouts || layoutModules.length >= route.layouts.length) {\n return route?.layoutTreePositions;\n }\n\n return route.layoutTreePositions?.slice(0, layoutModules.length);\n}\n\nfunction createAppPageBoundaryRscPayload<TModule extends AppPageModule>(\n options: AppPageBoundaryRscPayloadOptions<TModule>,\n): AppElements {\n const routeId = createAppPayloadRouteId(options.pathname, null);\n\n return {\n [APP_INTERCEPTION_CONTEXT_KEY]: null,\n [APP_ROUTE_KEY]: routeId,\n [APP_ROOT_LAYOUT_KEY]: resolveAppPageBoundaryRootLayoutTreePath(options.route),\n [routeId]: options.element,\n };\n}\n\nasync function renderAppPageBoundaryElementResponse<TModule extends AppPageModule>(\n options: AppPageBoundaryRenderCommonOptions<TModule> & {\n element: ReactNode;\n layoutModules: readonly (TModule | null | undefined)[];\n route?: AppPageBoundaryRoute<TModule> | null;\n routePattern?: string;\n status: number;\n },\n): Promise<Response> {\n const pathname = new URL(options.requestUrl).pathname;\n const payload = createAppPageBoundaryRscPayload({\n element: options.element,\n pathname,\n route: options.route,\n });\n\n return renderAppPageBoundaryResponse({\n async createHtmlResponse(rscStream, responseStatus) {\n const fontData = createAppPageFontData({\n getLinks: options.getFontLinks,\n getPreloads: options.getFontPreloads,\n getStyles: options.getFontStyles,\n });\n const ssrHandler = await options.loadSsrHandler();\n return renderAppPageHtmlResponse({\n clearRequestContext: options.clearRequestContext,\n fontData,\n fontLinkHeader: options.buildFontLinkHeader(fontData.preloads),\n middlewareHeaders: options.middlewareContext.headers,\n navigationContext: options.getNavigationContext(),\n rscStream,\n scriptNonce: options.scriptNonce,\n ssrHandler,\n status: responseStatus,\n });\n },\n createRscOnErrorHandler() {\n return options.createRscOnErrorHandler(pathname, options.routePattern ?? pathname);\n },\n element: payload,\n isRscRequest: options.isRscRequest,\n middlewareHeaders: options.middlewareContext.headers,\n renderToReadableStream: options.renderToReadableStream,\n status: options.status,\n });\n}\n\nexport async function renderAppPageHttpAccessFallback<TModule extends AppPageModule>(\n options: RenderAppPageHttpAccessFallbackOptions<TModule>,\n): Promise<Response | null> {\n const boundaryComponent =\n options.boundaryComponent ??\n resolveAppPageHttpAccessBoundaryComponent({\n getDefaultExport,\n rootForbiddenModule: options.rootForbiddenModule,\n rootNotFoundModule: options.rootNotFoundModule,\n rootUnauthorizedModule: options.rootUnauthorizedModule,\n routeForbiddenModule: options.route?.forbidden,\n routeNotFoundModule: options.route?.notFound,\n routeUnauthorizedModule: options.route?.unauthorized,\n statusCode: options.statusCode,\n });\n if (!boundaryComponent) {\n return null;\n }\n\n const layoutModules = options.layoutModules ?? options.route?.layouts ?? options.rootLayouts;\n const routeSegments = resolveHttpAccessFallbackHeadRouteSegments(options.route, layoutModules);\n const { metadata, viewport } = await resolveAppPageHead({\n layoutModules,\n layoutTreePositions: resolveHttpAccessFallbackHeadLayoutTreePositions(\n options.route,\n layoutModules,\n ),\n metadataRoutes: options.metadataRoutes,\n params: options.matchedParams,\n routePath: options.route?.pattern ?? new URL(options.requestUrl).pathname,\n routeSegments,\n });\n\n const headElements: ReactNode[] = [\n createElement(\"meta\", { charSet: \"utf-8\", key: \"charset\" }),\n createElement(\"meta\", { content: \"noindex\", key: \"robots\", name: \"robots\" }),\n ];\n if (metadata) {\n headElements.push(createElement(MetadataHead, { key: \"metadata\", metadata }));\n }\n headElements.push(createElement(ViewportHead, { key: \"viewport\", viewport }));\n\n const element = wrapRenderedBoundaryElement({\n element: createElement(Fragment, null, ...headElements, createElement(boundaryComponent)),\n globalErrorModule: options.globalErrorModule,\n includeGlobalErrorBoundary: true,\n isRscRequest: options.isRscRequest,\n layoutModules,\n layoutTreePositions: options.route?.layoutTreePositions,\n makeThenableParams: options.makeThenableParams,\n matchedParams: options.matchedParams,\n resolveChildSegments: options.resolveChildSegments,\n routeSegments: options.route?.routeSegments,\n });\n\n return renderAppPageBoundaryElementResponse({\n ...options,\n element,\n layoutModules,\n route: options.route,\n routePattern: options.route?.pattern,\n status: options.statusCode,\n });\n}\n\nexport async function renderAppPageErrorBoundary<TModule extends AppPageModule>(\n options: RenderAppPageErrorBoundaryOptions<TModule>,\n): Promise<Response | null> {\n const errorBoundary = resolveAppPageErrorBoundary({\n getDefaultExport,\n globalErrorModule: options.globalErrorModule,\n layoutErrorModules: options.route?.errors,\n pageErrorModule: options.route?.error,\n });\n if (!errorBoundary.component) {\n return null;\n }\n\n const rawError =\n options.error instanceof Error ? options.error : new Error(String(options.error));\n rewriteClientHookError(rawError);\n const errorObject = options.sanitizeErrorForClient(rawError);\n const matchedParams = options.matchedParams ?? options.route?.params ?? {};\n const layoutModules = options.route?.layouts ?? options.rootLayouts;\n const pathname = new URL(options.requestUrl).pathname;\n\n const headElements: ReactNode[] = [createElement(\"meta\", { charSet: \"utf-8\", key: \"charset\" })];\n if (!errorBoundary.isGlobalError) {\n try {\n const { metadata, viewport } = await resolveAppPageHead({\n fallbackOnFileMetadataError: true,\n layoutModules,\n layoutTreePositions: options.route?.layoutTreePositions,\n metadataRoutes: options.metadataRoutes,\n params: matchedParams,\n routePath: options.route?.pattern ?? pathname,\n routeSegments: options.route?.routeSegments,\n });\n if (metadata) {\n headElements.push(createElement(MetadataHead, { key: \"metadata\", metadata }));\n }\n headElements.push(createElement(ViewportHead, { key: \"viewport\", viewport }));\n } catch (error) {\n console.error(\n `[vinext] App page error boundary head resolution failed for ${options.route?.pattern ?? pathname}:`,\n error,\n );\n }\n }\n\n const element = wrapRenderedBoundaryElement({\n element: createElement(\n Fragment,\n null,\n ...headElements,\n createElement(errorBoundary.component, {\n error: errorObject,\n }),\n ),\n globalErrorModule: options.globalErrorModule,\n includeGlobalErrorBoundary: !errorBoundary.isGlobalError,\n isRscRequest: options.isRscRequest,\n layoutModules,\n layoutTreePositions: options.route?.layoutTreePositions,\n makeThenableParams: options.makeThenableParams,\n matchedParams,\n resolveChildSegments: options.resolveChildSegments,\n routeSegments: options.route?.routeSegments,\n skipLayoutWrapping: errorBoundary.isGlobalError,\n });\n\n return renderAppPageBoundaryElementResponse({\n ...options,\n element,\n layoutModules,\n route: options.route,\n routePattern: options.route?.pattern,\n status: 200,\n });\n}\n\n// React client-only hooks that are absent from the `react-server` export\n// condition. When called in a Server Component they produce a TypeError like\n// \"useState is not a function\". Rewrite into an actionable message matching\n// the format used by the next/navigation shims (see client-hook-error.ts).\nconst _clientHookPattern =\n /\\b(useState|useEffect|useReducer|useRef|useContext|useLayoutEffect|useInsertionEffect|useSyncExternalStore|useTransition|useImperativeHandle|useDeferredValue|useActionState|useOptimistic|useEffectEvent)\\b.*is not a function/;\n\nfunction rewriteClientHookError(error: Error): void {\n const match = error.message.match(_clientHookPattern);\n if (match) {\n error.message = buildClientHookErrorMessage(`${match[1]}()`);\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"app-page-boundary-render.js","names":[],"sources":["../../src/server/app-page-boundary-render.ts"],"sourcesContent":["import { Fragment, createElement, type ComponentType, type ReactNode } from \"react\";\nimport { buildClientHookErrorMessage } from \"vinext/shims/client-hook-error\";\nimport { ErrorBoundary } from \"vinext/shims/error-boundary\";\nimport { LayoutSegmentProvider } from \"vinext/shims/layout-segment-context\";\nimport { MetadataHead, ViewportHead } from \"vinext/shims/metadata\";\nimport type { AppPageFontPreload } from \"./app-page-execution.js\";\nimport type { AppPageMiddlewareContext } from \"./app-page-response.js\";\nimport type { MetadataFileRoute } from \"./metadata-routes.js\";\nimport { resolveAppPageHead } from \"./app-page-head.js\";\nimport {\n renderAppPageBoundaryResponse,\n resolveAppPageErrorBoundary,\n resolveAppPageHttpAccessBoundaryComponent,\n wrapAppPageBoundaryElement,\n type AppPageParams,\n} from \"./app-page-boundary.js\";\nimport {\n createAppPageFontData,\n renderAppPageHtmlResponse,\n type AppPageSsrHandler,\n} from \"./app-page-stream.js\";\nimport { AppElementsWire, type AppElements } from \"./app-elements.js\";\nimport { createAppPageLayoutEntries } from \"./app-page-route-wiring.js\";\n\n// oxlint-disable-next-line @typescript-eslint/no-explicit-any\ntype AppPageComponent = ComponentType<any>;\ntype AppPageModule = Record<string, unknown> & {\n default?: AppPageComponent | null | undefined;\n};\ntype AppPageBoundaryOnError = (\n error: unknown,\n requestInfo: unknown,\n errorContext: unknown,\n) => unknown;\n\ntype AppPageBoundaryRscPayloadOptions<TModule extends AppPageModule = AppPageModule> = {\n element: ReactNode;\n pathname: string;\n route?: AppPageBoundaryRoute<TModule> | null;\n};\n\nexport type AppPageBoundaryRoute<TModule extends AppPageModule = AppPageModule> = {\n error?: TModule | null;\n errors?: readonly (TModule | null | undefined)[] | null;\n forbidden?: TModule | null;\n layoutTreePositions?: readonly number[] | null;\n layouts?: readonly (TModule | null | undefined)[];\n notFound?: TModule | null;\n params?: AppPageParams;\n pattern?: string;\n routeSegments?: readonly string[];\n unauthorized?: TModule | null;\n};\n\ntype AppPageBoundaryRenderCommonOptions<TModule extends AppPageModule = AppPageModule> = {\n buildFontLinkHeader: (preloads: readonly AppPageFontPreload[] | null | undefined) => string;\n clearRequestContext: () => void;\n createRscOnErrorHandler: (pathname: string, routePath: string) => AppPageBoundaryOnError;\n getFontLinks: () => string[];\n getFontPreloads: () => AppPageFontPreload[];\n getFontStyles: () => string[];\n getNavigationContext: () => unknown;\n globalErrorModule?: TModule | null;\n isRscRequest: boolean;\n loadSsrHandler: () => Promise<AppPageSsrHandler>;\n makeThenableParams: (params: AppPageParams) => unknown;\n middlewareContext: AppPageMiddlewareContext;\n metadataRoutes: MetadataFileRoute[];\n renderToReadableStream: (\n element: ReactNode | AppElements,\n options: { onError: AppPageBoundaryOnError },\n ) => ReadableStream<Uint8Array>;\n requestUrl: string;\n resolveChildSegments: (\n routeSegments: readonly string[],\n treePosition: number,\n params: AppPageParams,\n ) => string[];\n rootLayouts: readonly (TModule | null | undefined)[];\n scriptNonce?: string;\n};\n\ntype RenderAppPageHttpAccessFallbackOptions<TModule extends AppPageModule = AppPageModule> = {\n boundaryComponent?: AppPageComponent | null;\n layoutModules?: readonly (TModule | null | undefined)[] | null;\n matchedParams: AppPageParams;\n rootForbiddenModule?: TModule | null;\n rootNotFoundModule?: TModule | null;\n rootUnauthorizedModule?: TModule | null;\n route?: AppPageBoundaryRoute<TModule> | null;\n statusCode: number;\n} & AppPageBoundaryRenderCommonOptions<TModule>;\n\ntype RenderAppPageErrorBoundaryOptions<TModule extends AppPageModule = AppPageModule> = {\n error: unknown;\n matchedParams?: AppPageParams | null;\n route?: AppPageBoundaryRoute<TModule> | null;\n sanitizeErrorForClient: (error: Error) => Error;\n} & AppPageBoundaryRenderCommonOptions<TModule>;\n\nfunction getDefaultExport<TModule extends AppPageModule>(\n module: TModule | null | undefined,\n): AppPageComponent | null {\n return module?.default ?? null;\n}\n\nfunction wrapRenderedBoundaryElement<TModule extends AppPageModule>(\n options: Pick<\n AppPageBoundaryRenderCommonOptions<TModule>,\n \"globalErrorModule\" | \"isRscRequest\" | \"makeThenableParams\" | \"resolveChildSegments\"\n > & {\n element: ReactNode;\n includeGlobalErrorBoundary: boolean;\n layoutModules: readonly (TModule | null | undefined)[];\n layoutTreePositions?: readonly number[] | null;\n matchedParams: AppPageParams;\n routeSegments?: readonly string[];\n skipLayoutWrapping?: boolean;\n },\n): ReactNode {\n return wrapAppPageBoundaryElement({\n element: options.element,\n getDefaultExport,\n globalErrorComponent: getDefaultExport(options.globalErrorModule),\n includeGlobalErrorBoundary: options.includeGlobalErrorBoundary,\n isRscRequest: options.isRscRequest,\n layoutModules: options.layoutModules,\n layoutTreePositions: options.layoutTreePositions,\n makeThenableParams: options.makeThenableParams,\n matchedParams: options.matchedParams,\n renderErrorBoundary(GlobalErrorComponent, children) {\n return createElement(ErrorBoundary, {\n fallback: GlobalErrorComponent,\n // oxlint-disable-next-line react/no-children-prop\n children,\n });\n },\n renderLayout(LayoutComponent, children, asyncParams) {\n return createElement(LayoutComponent as AppPageComponent, {\n // oxlint-disable-next-line react/no-children-prop\n children,\n params: asyncParams,\n });\n },\n renderLayoutSegmentProvider(segmentMap, children) {\n return createElement(\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n LayoutSegmentProvider as ComponentType<any>,\n { segmentMap },\n children,\n );\n },\n resolveChildSegments: options.resolveChildSegments,\n routeSegments: options.routeSegments ?? [],\n skipLayoutWrapping: options.skipLayoutWrapping,\n });\n}\n\nfunction resolveAppPageBoundaryRootLayoutTreePath<TModule extends AppPageModule>(\n route: AppPageBoundaryRoute<TModule> | null | undefined,\n): string | null {\n if (route?.layouts) {\n const rootLayoutEntry = createAppPageLayoutEntries({\n errors: route.errors,\n layoutTreePositions: route.layoutTreePositions,\n layouts: route.layouts,\n notFounds: null,\n routeSegments: route.routeSegments,\n })[0];\n\n if (rootLayoutEntry) {\n return rootLayoutEntry.treePath;\n }\n }\n\n // Without route tree metadata we cannot derive a canonical root layout tree path.\n // Returning null keeps boundary payloads soft-navigation compatible.\n return null;\n}\n\nfunction resolveHttpAccessFallbackHeadRouteSegments<TModule extends AppPageModule>(\n route: AppPageBoundaryRoute<TModule> | null | undefined,\n layoutModules: readonly (TModule | null | undefined)[],\n): readonly string[] | undefined {\n if (!route?.routeSegments) {\n return undefined;\n }\n\n if (!route.layouts || layoutModules.length >= route.layouts.length) {\n return route.routeSegments;\n }\n\n const lastIncludedLayoutIndex = layoutModules.length - 1;\n if (lastIncludedLayoutIndex < 0) {\n return [];\n }\n\n const segmentCount = route.layoutTreePositions?.[lastIncludedLayoutIndex] ?? 0;\n return route.routeSegments.slice(0, segmentCount);\n}\n\nfunction resolveHttpAccessFallbackHeadLayoutTreePositions<TModule extends AppPageModule>(\n route: AppPageBoundaryRoute<TModule> | null | undefined,\n layoutModules: readonly (TModule | null | undefined)[],\n): readonly number[] | null | undefined {\n if (!route?.layouts || layoutModules.length >= route.layouts.length) {\n return route?.layoutTreePositions;\n }\n\n return route.layoutTreePositions?.slice(0, layoutModules.length);\n}\n\nfunction createAppPageBoundaryRscPayload<TModule extends AppPageModule>(\n options: AppPageBoundaryRscPayloadOptions<TModule>,\n): AppElements {\n const routeId = AppElementsWire.encodeRouteId(options.pathname, null);\n\n return {\n ...AppElementsWire.createMetadataEntries({\n interceptionContext: null,\n rootLayoutTreePath: resolveAppPageBoundaryRootLayoutTreePath(options.route),\n routeId,\n }),\n [routeId]: options.element,\n };\n}\n\nasync function renderAppPageBoundaryElementResponse<TModule extends AppPageModule>(\n options: AppPageBoundaryRenderCommonOptions<TModule> & {\n element: ReactNode;\n layoutModules: readonly (TModule | null | undefined)[];\n route?: AppPageBoundaryRoute<TModule> | null;\n routePattern?: string;\n status: number;\n },\n): Promise<Response> {\n const pathname = new URL(options.requestUrl).pathname;\n const payload = createAppPageBoundaryRscPayload({\n element: options.element,\n pathname,\n route: options.route,\n });\n\n return renderAppPageBoundaryResponse({\n async createHtmlResponse(rscStream, responseStatus) {\n const fontData = createAppPageFontData({\n getLinks: options.getFontLinks,\n getPreloads: options.getFontPreloads,\n getStyles: options.getFontStyles,\n });\n const ssrHandler = await options.loadSsrHandler();\n return renderAppPageHtmlResponse({\n clearRequestContext: options.clearRequestContext,\n fontData,\n fontLinkHeader: options.buildFontLinkHeader(fontData.preloads),\n middlewareHeaders: options.middlewareContext.headers,\n navigationContext: options.getNavigationContext(),\n rscStream,\n scriptNonce: options.scriptNonce,\n ssrHandler,\n status: responseStatus,\n });\n },\n createRscOnErrorHandler() {\n return options.createRscOnErrorHandler(pathname, options.routePattern ?? pathname);\n },\n element: payload,\n isRscRequest: options.isRscRequest,\n middlewareHeaders: options.middlewareContext.headers,\n renderToReadableStream: options.renderToReadableStream,\n status: options.status,\n });\n}\n\nexport async function renderAppPageHttpAccessFallback<TModule extends AppPageModule>(\n options: RenderAppPageHttpAccessFallbackOptions<TModule>,\n): Promise<Response | null> {\n const boundaryComponent =\n options.boundaryComponent ??\n resolveAppPageHttpAccessBoundaryComponent({\n getDefaultExport,\n rootForbiddenModule: options.rootForbiddenModule,\n rootNotFoundModule: options.rootNotFoundModule,\n rootUnauthorizedModule: options.rootUnauthorizedModule,\n routeForbiddenModule: options.route?.forbidden,\n routeNotFoundModule: options.route?.notFound,\n routeUnauthorizedModule: options.route?.unauthorized,\n statusCode: options.statusCode,\n });\n if (!boundaryComponent) {\n return null;\n }\n\n const layoutModules = options.layoutModules ?? options.route?.layouts ?? options.rootLayouts;\n const routeSegments = resolveHttpAccessFallbackHeadRouteSegments(options.route, layoutModules);\n const { metadata, viewport } = await resolveAppPageHead({\n layoutModules,\n layoutTreePositions: resolveHttpAccessFallbackHeadLayoutTreePositions(\n options.route,\n layoutModules,\n ),\n metadataRoutes: options.metadataRoutes,\n params: options.matchedParams,\n routePath: options.route?.pattern ?? new URL(options.requestUrl).pathname,\n routeSegments,\n });\n\n const headElements: ReactNode[] = [\n createElement(\"meta\", { charSet: \"utf-8\", key: \"charset\" }),\n createElement(\"meta\", { content: \"noindex\", key: \"robots\", name: \"robots\" }),\n ];\n if (metadata) {\n headElements.push(createElement(MetadataHead, { key: \"metadata\", metadata }));\n }\n headElements.push(createElement(ViewportHead, { key: \"viewport\", viewport }));\n\n const element = wrapRenderedBoundaryElement({\n element: createElement(Fragment, null, ...headElements, createElement(boundaryComponent)),\n globalErrorModule: options.globalErrorModule,\n includeGlobalErrorBoundary: true,\n isRscRequest: options.isRscRequest,\n layoutModules,\n layoutTreePositions: options.route?.layoutTreePositions,\n makeThenableParams: options.makeThenableParams,\n matchedParams: options.matchedParams,\n resolveChildSegments: options.resolveChildSegments,\n routeSegments: options.route?.routeSegments,\n });\n\n return renderAppPageBoundaryElementResponse({\n ...options,\n element,\n layoutModules,\n route: options.route,\n routePattern: options.route?.pattern,\n status: options.statusCode,\n });\n}\n\nexport async function renderAppPageErrorBoundary<TModule extends AppPageModule>(\n options: RenderAppPageErrorBoundaryOptions<TModule>,\n): Promise<Response | null> {\n const errorBoundary = resolveAppPageErrorBoundary({\n getDefaultExport,\n globalErrorModule: options.globalErrorModule,\n layoutErrorModules: options.route?.errors,\n pageErrorModule: options.route?.error,\n });\n if (!errorBoundary.component) {\n return null;\n }\n\n const rawError =\n options.error instanceof Error ? options.error : new Error(String(options.error));\n rewriteClientHookError(rawError);\n const errorObject = options.sanitizeErrorForClient(rawError);\n const matchedParams = options.matchedParams ?? options.route?.params ?? {};\n const layoutModules = options.route?.layouts ?? options.rootLayouts;\n const pathname = new URL(options.requestUrl).pathname;\n\n const headElements: ReactNode[] = [createElement(\"meta\", { charSet: \"utf-8\", key: \"charset\" })];\n if (!errorBoundary.isGlobalError) {\n try {\n const { metadata, viewport } = await resolveAppPageHead({\n fallbackOnFileMetadataError: true,\n layoutModules,\n layoutTreePositions: options.route?.layoutTreePositions,\n metadataRoutes: options.metadataRoutes,\n params: matchedParams,\n routePath: options.route?.pattern ?? pathname,\n routeSegments: options.route?.routeSegments,\n });\n if (metadata) {\n headElements.push(createElement(MetadataHead, { key: \"metadata\", metadata }));\n }\n headElements.push(createElement(ViewportHead, { key: \"viewport\", viewport }));\n } catch (error) {\n console.error(\n `[vinext] App page error boundary head resolution failed for ${options.route?.pattern ?? pathname}:`,\n error,\n );\n }\n }\n\n const element = wrapRenderedBoundaryElement({\n element: createElement(\n Fragment,\n null,\n ...headElements,\n createElement(errorBoundary.component, {\n error: errorObject,\n }),\n ),\n globalErrorModule: options.globalErrorModule,\n includeGlobalErrorBoundary: !errorBoundary.isGlobalError,\n isRscRequest: options.isRscRequest,\n layoutModules,\n layoutTreePositions: options.route?.layoutTreePositions,\n makeThenableParams: options.makeThenableParams,\n matchedParams,\n resolveChildSegments: options.resolveChildSegments,\n routeSegments: options.route?.routeSegments,\n skipLayoutWrapping: errorBoundary.isGlobalError,\n });\n\n return renderAppPageBoundaryElementResponse({\n ...options,\n element,\n layoutModules,\n route: options.route,\n routePattern: options.route?.pattern,\n status: 200,\n });\n}\n\n// React client-only hooks that are absent from the `react-server` export\n// condition. When called in a Server Component they produce a TypeError like\n// \"useState is not a function\". Rewrite into an actionable message matching\n// the format used by the next/navigation shims (see client-hook-error.ts).\nconst _clientHookPattern =\n /\\b(useState|useEffect|useReducer|useRef|useContext|useLayoutEffect|useInsertionEffect|useSyncExternalStore|useTransition|useImperativeHandle|useDeferredValue|useActionState|useOptimistic|useEffectEvent)\\b.*is not a function/;\n\nfunction rewriteClientHookError(error: Error): void {\n const match = error.message.match(_clientHookPattern);\n if (match) {\n error.message = buildClientHookErrorMessage(`${match[1]}()`);\n }\n}\n"],"mappings":"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"}
@@ -1,3 +1,4 @@
1
+ import { VINEXT_RSC_VARY_HEADER } from "./app-rsc-cache-busting.js";
1
2
  import { resolveAppPageSegmentParams } from "./app-page-params.js";
2
3
  import { mergeMiddlewareResponseHeaders } from "./middleware-response-headers.js";
3
4
  //#region src/server/app-page-boundary.ts
@@ -64,7 +65,7 @@ async function renderAppPageBoundaryResponse(options) {
64
65
  if (options.isRscRequest) {
65
66
  const headers = new Headers({
66
67
  "Content-Type": "text/x-component; charset=utf-8",
67
- Vary: "RSC, Accept"
68
+ Vary: VINEXT_RSC_VARY_HEADER
68
69
  });
69
70
  mergeMiddlewareResponseHeaders(headers, options.middlewareHeaders ?? null);
70
71
  return new Response(rscStream, {
@@ -1 +1 @@
1
- {"version":3,"file":"app-page-boundary.js","names":[],"sources":["../../src/server/app-page-boundary.ts"],"sourcesContent":["import { mergeMiddlewareResponseHeaders } from \"./middleware-response-headers.js\";\nimport { resolveAppPageSegmentParams } from \"./app-page-params.js\";\n\nexport type AppPageParams = Record<string, string | string[]>;\n\ntype ResolveAppPageHttpAccessBoundaryComponentOptions<TModule, TComponent> = {\n getDefaultExport: (module: TModule | null | undefined) => TComponent | null | undefined;\n rootForbiddenModule?: TModule | null;\n rootNotFoundModule?: TModule | null;\n rootUnauthorizedModule?: TModule | null;\n routeForbiddenModule?: TModule | null;\n routeNotFoundModule?: TModule | null;\n routeUnauthorizedModule?: TModule | null;\n statusCode: number;\n};\n\ntype ResolveAppPageParentHttpAccessBoundaryModuleOptions<TModule> = {\n layoutIndex: number;\n rootForbiddenModule?: TModule | null;\n rootNotFoundModule?: TModule | null;\n rootUnauthorizedModule?: TModule | null;\n routeForbiddenModules?: readonly (TModule | null | undefined)[] | null;\n routeNotFoundModules?: readonly (TModule | null | undefined)[] | null;\n routeUnauthorizedModules?: readonly (TModule | null | undefined)[] | null;\n statusCode: number;\n};\n\ntype ResolveAppPageErrorBoundaryOptions<TModule, TComponent> = {\n getDefaultExport: (module: TModule | null | undefined) => TComponent | null | undefined;\n globalErrorModule?: TModule | null;\n layoutErrorModules?: readonly (TModule | null | undefined)[] | null;\n pageErrorModule?: TModule | null;\n};\n\ntype ResolveAppPageErrorBoundaryResult<TComponent> = {\n component: TComponent | null;\n isGlobalError: boolean;\n};\n\ntype WrapAppPageBoundaryElementOptions<\n TElement,\n TLayoutModule,\n TLayoutComponent,\n TChildSegments,\n TGlobalErrorComponent,\n> = {\n element: TElement;\n getDefaultExport: (\n module: TLayoutModule | null | undefined,\n ) => TLayoutComponent | null | undefined;\n globalErrorComponent?: TGlobalErrorComponent | null;\n includeGlobalErrorBoundary: boolean;\n isRscRequest: boolean;\n layoutModules: readonly (TLayoutModule | null | undefined)[];\n layoutTreePositions?: readonly number[] | null;\n makeThenableParams: (params: AppPageParams) => unknown;\n matchedParams: AppPageParams;\n renderErrorBoundary: (component: TGlobalErrorComponent, children: TElement) => TElement;\n renderLayout: (component: TLayoutComponent, children: TElement, params: unknown) => TElement;\n renderLayoutSegmentProvider?: (\n segmentMap: { children: TChildSegments },\n children: TElement,\n ) => TElement;\n resolveChildSegments?: (\n routeSegments: readonly string[],\n treePosition: number,\n params: AppPageParams,\n ) => TChildSegments;\n routeSegments?: readonly string[];\n skipLayoutWrapping?: boolean;\n};\n\ntype AppPageBoundaryOnError = (\n error: unknown,\n requestInfo: unknown,\n errorContext: unknown,\n) => unknown;\n\ntype RenderAppPageBoundaryResponseOptions<TElement> = {\n createHtmlResponse: (rscStream: ReadableStream<Uint8Array>, status: number) => Promise<Response>;\n createRscOnErrorHandler: () => AppPageBoundaryOnError;\n element: TElement;\n isRscRequest: boolean;\n middlewareHeaders?: Headers | null;\n renderToReadableStream: (\n element: TElement,\n options: { onError: AppPageBoundaryOnError },\n ) => ReadableStream<Uint8Array>;\n status: number;\n};\n\nexport function resolveAppPageHttpAccessBoundaryComponent<TModule, TComponent>(\n options: ResolveAppPageHttpAccessBoundaryComponentOptions<TModule, TComponent>,\n): TComponent | null {\n let boundaryModule: TModule | null | undefined;\n\n if (options.statusCode === 403) {\n boundaryModule = options.routeForbiddenModule ?? options.rootForbiddenModule;\n } else if (options.statusCode === 401) {\n boundaryModule = options.routeUnauthorizedModule ?? options.rootUnauthorizedModule;\n } else {\n boundaryModule = options.routeNotFoundModule ?? options.rootNotFoundModule;\n }\n\n return options.getDefaultExport(boundaryModule) ?? null;\n}\n\nexport function resolveAppPageParentHttpAccessBoundaryModule<TModule>(\n options: ResolveAppPageParentHttpAccessBoundaryModuleOptions<TModule>,\n): TModule | null {\n let routeModules = options.routeNotFoundModules;\n let rootModule = options.rootNotFoundModule;\n\n if (options.statusCode === 403) {\n routeModules = options.routeForbiddenModules;\n rootModule = options.rootForbiddenModule;\n } else if (options.statusCode === 401) {\n routeModules = options.routeUnauthorizedModules;\n rootModule = options.rootUnauthorizedModule;\n }\n\n if (routeModules) {\n for (let index = options.layoutIndex - 1; index >= 0; index--) {\n const module = routeModules[index];\n if (module) {\n return module;\n }\n }\n }\n\n return rootModule ?? null;\n}\n\nexport function resolveAppPageErrorBoundary<TModule, TComponent>(\n options: ResolveAppPageErrorBoundaryOptions<TModule, TComponent>,\n): ResolveAppPageErrorBoundaryResult<TComponent> {\n const pageErrorComponent = options.getDefaultExport(options.pageErrorModule);\n if (pageErrorComponent) {\n return {\n component: pageErrorComponent,\n isGlobalError: false,\n };\n }\n\n if (options.layoutErrorModules) {\n for (let index = options.layoutErrorModules.length - 1; index >= 0; index--) {\n const layoutErrorComponent = options.getDefaultExport(options.layoutErrorModules[index]);\n if (layoutErrorComponent) {\n return {\n component: layoutErrorComponent,\n isGlobalError: false,\n };\n }\n }\n }\n\n const globalErrorComponent = options.getDefaultExport(options.globalErrorModule);\n return {\n component: globalErrorComponent ?? null,\n isGlobalError: Boolean(globalErrorComponent),\n };\n}\n\nexport function wrapAppPageBoundaryElement<\n TElement,\n TLayoutModule,\n TLayoutComponent,\n TChildSegments,\n TGlobalErrorComponent,\n>(\n options: WrapAppPageBoundaryElementOptions<\n TElement,\n TLayoutModule,\n TLayoutComponent,\n TChildSegments,\n TGlobalErrorComponent\n >,\n): TElement {\n let element = options.element;\n\n if (!options.skipLayoutWrapping) {\n for (let index = options.layoutModules.length - 1; index >= 0; index--) {\n const layoutComponent = options.getDefaultExport(options.layoutModules[index]);\n if (!layoutComponent) {\n continue;\n }\n\n const treePosition = options.layoutTreePositions ? options.layoutTreePositions[index] : 0;\n const asyncParams = options.makeThenableParams(\n resolveAppPageSegmentParams(options.routeSegments, treePosition, options.matchedParams),\n );\n element = options.renderLayout(layoutComponent, element, asyncParams);\n\n if (\n options.isRscRequest &&\n options.renderLayoutSegmentProvider &&\n options.resolveChildSegments\n ) {\n const childSegments = options.resolveChildSegments(\n options.routeSegments ?? [],\n treePosition,\n options.matchedParams,\n );\n element = options.renderLayoutSegmentProvider({ children: childSegments }, element);\n }\n }\n }\n\n if (options.isRscRequest && options.includeGlobalErrorBoundary && options.globalErrorComponent) {\n element = options.renderErrorBoundary(options.globalErrorComponent, element);\n }\n\n return element;\n}\n\nexport async function renderAppPageBoundaryResponse<TElement>(\n options: RenderAppPageBoundaryResponseOptions<TElement>,\n): Promise<Response> {\n const rscStream = options.renderToReadableStream(options.element, {\n onError: options.createRscOnErrorHandler(),\n });\n\n if (options.isRscRequest) {\n // Do NOT clear request-scoped context here. RSC responses are consumed lazily\n // by the client, so headers()/cookies() and async server components still need\n // their ALS-backed state while the stream is being read.\n const headers = new Headers({\n \"Content-Type\": \"text/x-component; charset=utf-8\",\n Vary: \"RSC, Accept\",\n });\n mergeMiddlewareResponseHeaders(headers, options.middlewareHeaders ?? null);\n\n return new Response(rscStream, {\n status: options.status,\n headers,\n });\n }\n\n return options.createHtmlResponse(rscStream, options.status);\n}\n"],"mappings":";;;AA2FA,SAAgB,0CACd,SACmB;CACnB,IAAI;AAEJ,KAAI,QAAQ,eAAe,IACzB,kBAAiB,QAAQ,wBAAwB,QAAQ;UAChD,QAAQ,eAAe,IAChC,kBAAiB,QAAQ,2BAA2B,QAAQ;KAE5D,kBAAiB,QAAQ,uBAAuB,QAAQ;AAG1D,QAAO,QAAQ,iBAAiB,eAAe,IAAI;;AAGrD,SAAgB,6CACd,SACgB;CAChB,IAAI,eAAe,QAAQ;CAC3B,IAAI,aAAa,QAAQ;AAEzB,KAAI,QAAQ,eAAe,KAAK;AAC9B,iBAAe,QAAQ;AACvB,eAAa,QAAQ;YACZ,QAAQ,eAAe,KAAK;AACrC,iBAAe,QAAQ;AACvB,eAAa,QAAQ;;AAGvB,KAAI,aACF,MAAK,IAAI,QAAQ,QAAQ,cAAc,GAAG,SAAS,GAAG,SAAS;EAC7D,MAAM,SAAS,aAAa;AAC5B,MAAI,OACF,QAAO;;AAKb,QAAO,cAAc;;AAGvB,SAAgB,4BACd,SAC+C;CAC/C,MAAM,qBAAqB,QAAQ,iBAAiB,QAAQ,gBAAgB;AAC5E,KAAI,mBACF,QAAO;EACL,WAAW;EACX,eAAe;EAChB;AAGH,KAAI,QAAQ,mBACV,MAAK,IAAI,QAAQ,QAAQ,mBAAmB,SAAS,GAAG,SAAS,GAAG,SAAS;EAC3E,MAAM,uBAAuB,QAAQ,iBAAiB,QAAQ,mBAAmB,OAAO;AACxF,MAAI,qBACF,QAAO;GACL,WAAW;GACX,eAAe;GAChB;;CAKP,MAAM,uBAAuB,QAAQ,iBAAiB,QAAQ,kBAAkB;AAChF,QAAO;EACL,WAAW,wBAAwB;EACnC,eAAe,QAAQ,qBAAqB;EAC7C;;AAGH,SAAgB,2BAOd,SAOU;CACV,IAAI,UAAU,QAAQ;AAEtB,KAAI,CAAC,QAAQ,mBACX,MAAK,IAAI,QAAQ,QAAQ,cAAc,SAAS,GAAG,SAAS,GAAG,SAAS;EACtE,MAAM,kBAAkB,QAAQ,iBAAiB,QAAQ,cAAc,OAAO;AAC9E,MAAI,CAAC,gBACH;EAGF,MAAM,eAAe,QAAQ,sBAAsB,QAAQ,oBAAoB,SAAS;EACxF,MAAM,cAAc,QAAQ,mBAC1B,4BAA4B,QAAQ,eAAe,cAAc,QAAQ,cAAc,CACxF;AACD,YAAU,QAAQ,aAAa,iBAAiB,SAAS,YAAY;AAErE,MACE,QAAQ,gBACR,QAAQ,+BACR,QAAQ,sBACR;GACA,MAAM,gBAAgB,QAAQ,qBAC5B,QAAQ,iBAAiB,EAAE,EAC3B,cACA,QAAQ,cACT;AACD,aAAU,QAAQ,4BAA4B,EAAE,UAAU,eAAe,EAAE,QAAQ;;;AAKzF,KAAI,QAAQ,gBAAgB,QAAQ,8BAA8B,QAAQ,qBACxE,WAAU,QAAQ,oBAAoB,QAAQ,sBAAsB,QAAQ;AAG9E,QAAO;;AAGT,eAAsB,8BACpB,SACmB;CACnB,MAAM,YAAY,QAAQ,uBAAuB,QAAQ,SAAS,EAChE,SAAS,QAAQ,yBAAyB,EAC3C,CAAC;AAEF,KAAI,QAAQ,cAAc;EAIxB,MAAM,UAAU,IAAI,QAAQ;GAC1B,gBAAgB;GAChB,MAAM;GACP,CAAC;AACF,iCAA+B,SAAS,QAAQ,qBAAqB,KAAK;AAE1E,SAAO,IAAI,SAAS,WAAW;GAC7B,QAAQ,QAAQ;GAChB;GACD,CAAC;;AAGJ,QAAO,QAAQ,mBAAmB,WAAW,QAAQ,OAAO"}
1
+ {"version":3,"file":"app-page-boundary.js","names":[],"sources":["../../src/server/app-page-boundary.ts"],"sourcesContent":["import { mergeMiddlewareResponseHeaders } from \"./middleware-response-headers.js\";\nimport { VINEXT_RSC_VARY_HEADER } from \"./app-rsc-cache-busting.js\";\nimport { resolveAppPageSegmentParams } from \"./app-page-params.js\";\n\nexport type AppPageParams = Record<string, string | string[]>;\n\ntype ResolveAppPageHttpAccessBoundaryComponentOptions<TModule, TComponent> = {\n getDefaultExport: (module: TModule | null | undefined) => TComponent | null | undefined;\n rootForbiddenModule?: TModule | null;\n rootNotFoundModule?: TModule | null;\n rootUnauthorizedModule?: TModule | null;\n routeForbiddenModule?: TModule | null;\n routeNotFoundModule?: TModule | null;\n routeUnauthorizedModule?: TModule | null;\n statusCode: number;\n};\n\ntype ResolveAppPageParentHttpAccessBoundaryModuleOptions<TModule> = {\n layoutIndex: number;\n rootForbiddenModule?: TModule | null;\n rootNotFoundModule?: TModule | null;\n rootUnauthorizedModule?: TModule | null;\n routeForbiddenModules?: readonly (TModule | null | undefined)[] | null;\n routeNotFoundModules?: readonly (TModule | null | undefined)[] | null;\n routeUnauthorizedModules?: readonly (TModule | null | undefined)[] | null;\n statusCode: number;\n};\n\ntype ResolveAppPageErrorBoundaryOptions<TModule, TComponent> = {\n getDefaultExport: (module: TModule | null | undefined) => TComponent | null | undefined;\n globalErrorModule?: TModule | null;\n layoutErrorModules?: readonly (TModule | null | undefined)[] | null;\n pageErrorModule?: TModule | null;\n};\n\ntype ResolveAppPageErrorBoundaryResult<TComponent> = {\n component: TComponent | null;\n isGlobalError: boolean;\n};\n\ntype WrapAppPageBoundaryElementOptions<\n TElement,\n TLayoutModule,\n TLayoutComponent,\n TChildSegments,\n TGlobalErrorComponent,\n> = {\n element: TElement;\n getDefaultExport: (\n module: TLayoutModule | null | undefined,\n ) => TLayoutComponent | null | undefined;\n globalErrorComponent?: TGlobalErrorComponent | null;\n includeGlobalErrorBoundary: boolean;\n isRscRequest: boolean;\n layoutModules: readonly (TLayoutModule | null | undefined)[];\n layoutTreePositions?: readonly number[] | null;\n makeThenableParams: (params: AppPageParams) => unknown;\n matchedParams: AppPageParams;\n renderErrorBoundary: (component: TGlobalErrorComponent, children: TElement) => TElement;\n renderLayout: (component: TLayoutComponent, children: TElement, params: unknown) => TElement;\n renderLayoutSegmentProvider?: (\n segmentMap: { children: TChildSegments },\n children: TElement,\n ) => TElement;\n resolveChildSegments?: (\n routeSegments: readonly string[],\n treePosition: number,\n params: AppPageParams,\n ) => TChildSegments;\n routeSegments?: readonly string[];\n skipLayoutWrapping?: boolean;\n};\n\ntype AppPageBoundaryOnError = (\n error: unknown,\n requestInfo: unknown,\n errorContext: unknown,\n) => unknown;\n\ntype RenderAppPageBoundaryResponseOptions<TElement> = {\n createHtmlResponse: (rscStream: ReadableStream<Uint8Array>, status: number) => Promise<Response>;\n createRscOnErrorHandler: () => AppPageBoundaryOnError;\n element: TElement;\n isRscRequest: boolean;\n middlewareHeaders?: Headers | null;\n renderToReadableStream: (\n element: TElement,\n options: { onError: AppPageBoundaryOnError },\n ) => ReadableStream<Uint8Array>;\n status: number;\n};\n\nexport function resolveAppPageHttpAccessBoundaryComponent<TModule, TComponent>(\n options: ResolveAppPageHttpAccessBoundaryComponentOptions<TModule, TComponent>,\n): TComponent | null {\n let boundaryModule: TModule | null | undefined;\n\n if (options.statusCode === 403) {\n boundaryModule = options.routeForbiddenModule ?? options.rootForbiddenModule;\n } else if (options.statusCode === 401) {\n boundaryModule = options.routeUnauthorizedModule ?? options.rootUnauthorizedModule;\n } else {\n boundaryModule = options.routeNotFoundModule ?? options.rootNotFoundModule;\n }\n\n return options.getDefaultExport(boundaryModule) ?? null;\n}\n\nexport function resolveAppPageParentHttpAccessBoundaryModule<TModule>(\n options: ResolveAppPageParentHttpAccessBoundaryModuleOptions<TModule>,\n): TModule | null {\n let routeModules = options.routeNotFoundModules;\n let rootModule = options.rootNotFoundModule;\n\n if (options.statusCode === 403) {\n routeModules = options.routeForbiddenModules;\n rootModule = options.rootForbiddenModule;\n } else if (options.statusCode === 401) {\n routeModules = options.routeUnauthorizedModules;\n rootModule = options.rootUnauthorizedModule;\n }\n\n if (routeModules) {\n for (let index = options.layoutIndex - 1; index >= 0; index--) {\n const module = routeModules[index];\n if (module) {\n return module;\n }\n }\n }\n\n return rootModule ?? null;\n}\n\nexport function resolveAppPageErrorBoundary<TModule, TComponent>(\n options: ResolveAppPageErrorBoundaryOptions<TModule, TComponent>,\n): ResolveAppPageErrorBoundaryResult<TComponent> {\n const pageErrorComponent = options.getDefaultExport(options.pageErrorModule);\n if (pageErrorComponent) {\n return {\n component: pageErrorComponent,\n isGlobalError: false,\n };\n }\n\n if (options.layoutErrorModules) {\n for (let index = options.layoutErrorModules.length - 1; index >= 0; index--) {\n const layoutErrorComponent = options.getDefaultExport(options.layoutErrorModules[index]);\n if (layoutErrorComponent) {\n return {\n component: layoutErrorComponent,\n isGlobalError: false,\n };\n }\n }\n }\n\n const globalErrorComponent = options.getDefaultExport(options.globalErrorModule);\n return {\n component: globalErrorComponent ?? null,\n isGlobalError: Boolean(globalErrorComponent),\n };\n}\n\nexport function wrapAppPageBoundaryElement<\n TElement,\n TLayoutModule,\n TLayoutComponent,\n TChildSegments,\n TGlobalErrorComponent,\n>(\n options: WrapAppPageBoundaryElementOptions<\n TElement,\n TLayoutModule,\n TLayoutComponent,\n TChildSegments,\n TGlobalErrorComponent\n >,\n): TElement {\n let element = options.element;\n\n if (!options.skipLayoutWrapping) {\n for (let index = options.layoutModules.length - 1; index >= 0; index--) {\n const layoutComponent = options.getDefaultExport(options.layoutModules[index]);\n if (!layoutComponent) {\n continue;\n }\n\n const treePosition = options.layoutTreePositions ? options.layoutTreePositions[index] : 0;\n const asyncParams = options.makeThenableParams(\n resolveAppPageSegmentParams(options.routeSegments, treePosition, options.matchedParams),\n );\n element = options.renderLayout(layoutComponent, element, asyncParams);\n\n if (\n options.isRscRequest &&\n options.renderLayoutSegmentProvider &&\n options.resolveChildSegments\n ) {\n const childSegments = options.resolveChildSegments(\n options.routeSegments ?? [],\n treePosition,\n options.matchedParams,\n );\n element = options.renderLayoutSegmentProvider({ children: childSegments }, element);\n }\n }\n }\n\n if (options.isRscRequest && options.includeGlobalErrorBoundary && options.globalErrorComponent) {\n element = options.renderErrorBoundary(options.globalErrorComponent, element);\n }\n\n return element;\n}\n\nexport async function renderAppPageBoundaryResponse<TElement>(\n options: RenderAppPageBoundaryResponseOptions<TElement>,\n): Promise<Response> {\n const rscStream = options.renderToReadableStream(options.element, {\n onError: options.createRscOnErrorHandler(),\n });\n\n if (options.isRscRequest) {\n // Do NOT clear request-scoped context here. RSC responses are consumed lazily\n // by the client, so headers()/cookies() and async server components still need\n // their ALS-backed state while the stream is being read.\n const headers = new Headers({\n \"Content-Type\": \"text/x-component; charset=utf-8\",\n Vary: VINEXT_RSC_VARY_HEADER,\n });\n mergeMiddlewareResponseHeaders(headers, options.middlewareHeaders ?? null);\n\n return new Response(rscStream, {\n status: options.status,\n headers,\n });\n }\n\n return options.createHtmlResponse(rscStream, options.status);\n}\n"],"mappings":";;;;AA4FA,SAAgB,0CACd,SACmB;CACnB,IAAI;AAEJ,KAAI,QAAQ,eAAe,IACzB,kBAAiB,QAAQ,wBAAwB,QAAQ;UAChD,QAAQ,eAAe,IAChC,kBAAiB,QAAQ,2BAA2B,QAAQ;KAE5D,kBAAiB,QAAQ,uBAAuB,QAAQ;AAG1D,QAAO,QAAQ,iBAAiB,eAAe,IAAI;;AAGrD,SAAgB,6CACd,SACgB;CAChB,IAAI,eAAe,QAAQ;CAC3B,IAAI,aAAa,QAAQ;AAEzB,KAAI,QAAQ,eAAe,KAAK;AAC9B,iBAAe,QAAQ;AACvB,eAAa,QAAQ;YACZ,QAAQ,eAAe,KAAK;AACrC,iBAAe,QAAQ;AACvB,eAAa,QAAQ;;AAGvB,KAAI,aACF,MAAK,IAAI,QAAQ,QAAQ,cAAc,GAAG,SAAS,GAAG,SAAS;EAC7D,MAAM,SAAS,aAAa;AAC5B,MAAI,OACF,QAAO;;AAKb,QAAO,cAAc;;AAGvB,SAAgB,4BACd,SAC+C;CAC/C,MAAM,qBAAqB,QAAQ,iBAAiB,QAAQ,gBAAgB;AAC5E,KAAI,mBACF,QAAO;EACL,WAAW;EACX,eAAe;EAChB;AAGH,KAAI,QAAQ,mBACV,MAAK,IAAI,QAAQ,QAAQ,mBAAmB,SAAS,GAAG,SAAS,GAAG,SAAS;EAC3E,MAAM,uBAAuB,QAAQ,iBAAiB,QAAQ,mBAAmB,OAAO;AACxF,MAAI,qBACF,QAAO;GACL,WAAW;GACX,eAAe;GAChB;;CAKP,MAAM,uBAAuB,QAAQ,iBAAiB,QAAQ,kBAAkB;AAChF,QAAO;EACL,WAAW,wBAAwB;EACnC,eAAe,QAAQ,qBAAqB;EAC7C;;AAGH,SAAgB,2BAOd,SAOU;CACV,IAAI,UAAU,QAAQ;AAEtB,KAAI,CAAC,QAAQ,mBACX,MAAK,IAAI,QAAQ,QAAQ,cAAc,SAAS,GAAG,SAAS,GAAG,SAAS;EACtE,MAAM,kBAAkB,QAAQ,iBAAiB,QAAQ,cAAc,OAAO;AAC9E,MAAI,CAAC,gBACH;EAGF,MAAM,eAAe,QAAQ,sBAAsB,QAAQ,oBAAoB,SAAS;EACxF,MAAM,cAAc,QAAQ,mBAC1B,4BAA4B,QAAQ,eAAe,cAAc,QAAQ,cAAc,CACxF;AACD,YAAU,QAAQ,aAAa,iBAAiB,SAAS,YAAY;AAErE,MACE,QAAQ,gBACR,QAAQ,+BACR,QAAQ,sBACR;GACA,MAAM,gBAAgB,QAAQ,qBAC5B,QAAQ,iBAAiB,EAAE,EAC3B,cACA,QAAQ,cACT;AACD,aAAU,QAAQ,4BAA4B,EAAE,UAAU,eAAe,EAAE,QAAQ;;;AAKzF,KAAI,QAAQ,gBAAgB,QAAQ,8BAA8B,QAAQ,qBACxE,WAAU,QAAQ,oBAAoB,QAAQ,sBAAsB,QAAQ;AAG9E,QAAO;;AAGT,eAAsB,8BACpB,SACmB;CACnB,MAAM,YAAY,QAAQ,uBAAuB,QAAQ,SAAS,EAChE,SAAS,QAAQ,yBAAyB,EAC3C,CAAC;AAEF,KAAI,QAAQ,cAAc;EAIxB,MAAM,UAAU,IAAI,QAAQ;GAC1B,gBAAgB;GAChB,MAAM;GACP,CAAC;AACF,iCAA+B,SAAS,QAAQ,qBAAqB,KAAK;AAE1E,SAAO,IAAI,SAAS,WAAW;GAC7B,QAAQ,QAAQ;GAChB;GACD,CAAC;;AAGJ,QAAO,QAAQ,mBAAmB,WAAW,QAAQ,OAAO"}
@@ -1,18 +1,25 @@
1
- import { CachedAppPageValue } from "../shims/cache.js";
1
+ import { CacheControlMetadata, CachedAppPageValue } from "../shims/cache.js";
2
2
  import { ISRCacheEntry } from "./isr-cache.js";
3
3
 
4
4
  //#region src/server/app-page-cache.d.ts
5
5
  type AppPageDebugLogger = (event: string, detail: string) => void;
6
6
  type AppPageCacheGetter = (key: string) => Promise<ISRCacheEntry | null>;
7
- type AppPageCacheSetter = (key: string, data: CachedAppPageValue, revalidateSeconds: number, tags: string[]) => Promise<void>;
7
+ type AppPageCacheSetter = (key: string, data: CachedAppPageValue, revalidateSeconds: number, tags: string[], expireSeconds?: number) => Promise<void>;
8
8
  type AppPageBackgroundRegenerator = (key: string, renderFn: () => Promise<void>) => void;
9
+ type AppPageRequestCacheLife = {
10
+ revalidate?: number;
11
+ expire?: number;
12
+ };
9
13
  type AppPageCacheRenderResult = {
14
+ cacheControl?: CacheControlMetadata;
10
15
  html: string;
11
16
  rscData: ArrayBuffer;
12
17
  tags: string[];
13
18
  };
14
19
  type BuildAppPageCachedResponseOptions = {
20
+ cacheControl?: CacheControlMetadata;
15
21
  cacheState: "HIT" | "STALE";
22
+ expireSeconds?: number;
16
23
  isRscRequest: boolean;
17
24
  mountedSlotsHeader?: string | null;
18
25
  revalidateSeconds: number;
@@ -27,20 +34,25 @@ type ReadAppPageCacheResponseOptions = {
27
34
  isrRscKey: (pathname: string, mountedSlotsHeader?: string | null) => string;
28
35
  isrSet: AppPageCacheSetter;
29
36
  mountedSlotsHeader?: string | null;
37
+ expireSeconds?: number;
30
38
  revalidateSeconds: number;
31
39
  renderFreshPageForCache: () => Promise<AppPageCacheRenderResult>;
32
40
  scheduleBackgroundRegeneration: AppPageBackgroundRegenerator;
33
41
  };
34
42
  type FinalizeAppPageHtmlCacheResponseOptions = {
43
+ capturedDynamicUsageBeforeContextCleanup?: () => boolean;
35
44
  capturedRscDataPromise: Promise<ArrayBuffer> | null;
36
45
  cleanPathname: string;
37
46
  consumeDynamicUsage: () => boolean;
38
47
  getPageTags: () => string[];
48
+ getRequestCacheLife?: () => AppPageRequestCacheLife | null;
39
49
  isrDebug?: AppPageDebugLogger;
40
50
  isrHtmlKey: (pathname: string) => string;
41
51
  isrRscKey: (pathname: string, mountedSlotsHeader?: string | null) => string;
42
52
  isrSet: AppPageCacheSetter;
43
- revalidateSeconds: number;
53
+ preserveClientResponseHeaders?: boolean;
54
+ expireSeconds?: number;
55
+ revalidateSeconds: number | null;
44
56
  waitUntil?: (promise: Promise<void>) => void;
45
57
  };
46
58
  type ScheduleAppPageRscCacheWriteOptions = {
@@ -49,11 +61,14 @@ type ScheduleAppPageRscCacheWriteOptions = {
49
61
  consumeDynamicUsage: () => boolean;
50
62
  dynamicUsedDuringBuild: boolean;
51
63
  getPageTags: () => string[];
64
+ getRequestCacheLife?: () => AppPageRequestCacheLife | null;
52
65
  isrDebug?: AppPageDebugLogger;
53
66
  isrRscKey: (pathname: string, mountedSlotsHeader?: string | null) => string;
54
67
  isrSet: AppPageCacheSetter;
55
68
  mountedSlotsHeader?: string | null;
56
- revalidateSeconds: number;
69
+ preserveClientResponseHeaders?: boolean;
70
+ expireSeconds?: number;
71
+ revalidateSeconds: number | null;
57
72
  waitUntil?: (promise: Promise<void>) => void;
58
73
  };
59
74
  declare function buildAppPageCacheTags(pathname: string, extraTags: readonly string[]): string[];