@rangojs/router 0.0.0-experimental.13 → 0.0.0-experimental.135c6902

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 (1098) hide show
  1. package/AGENTS.md +9 -0
  2. package/README.md +884 -4
  3. package/dist/__internal.d.ts +83 -0
  4. package/dist/__internal.d.ts.map +1 -0
  5. package/dist/__internal.js +19 -0
  6. package/dist/__internal.js.map +1 -0
  7. package/dist/__mocks__/version.d.ts +7 -0
  8. package/dist/__mocks__/version.d.ts.map +1 -0
  9. package/dist/__mocks__/version.js +7 -0
  10. package/dist/__mocks__/version.js.map +1 -0
  11. package/dist/__tests__/client-href.test.d.ts +2 -0
  12. package/dist/__tests__/client-href.test.d.ts.map +1 -0
  13. package/dist/__tests__/client-href.test.js +74 -0
  14. package/dist/__tests__/client-href.test.js.map +1 -0
  15. package/dist/__tests__/component-utils.test.d.ts +2 -0
  16. package/dist/__tests__/component-utils.test.d.ts.map +1 -0
  17. package/dist/__tests__/component-utils.test.js +51 -0
  18. package/dist/__tests__/component-utils.test.js.map +1 -0
  19. package/dist/__tests__/event-controller.test.d.ts +2 -0
  20. package/dist/__tests__/event-controller.test.d.ts.map +1 -0
  21. package/dist/__tests__/event-controller.test.js +538 -0
  22. package/dist/__tests__/event-controller.test.js.map +1 -0
  23. package/dist/__tests__/helpers/route-tree.d.ts +118 -0
  24. package/dist/__tests__/helpers/route-tree.d.ts.map +1 -0
  25. package/dist/__tests__/helpers/route-tree.js +374 -0
  26. package/dist/__tests__/helpers/route-tree.js.map +1 -0
  27. package/dist/__tests__/match-result.test.d.ts +2 -0
  28. package/dist/__tests__/match-result.test.d.ts.map +1 -0
  29. package/dist/__tests__/match-result.test.js +154 -0
  30. package/dist/__tests__/match-result.test.js.map +1 -0
  31. package/dist/__tests__/navigation-store.test.d.ts +2 -0
  32. package/dist/__tests__/navigation-store.test.d.ts.map +1 -0
  33. package/dist/__tests__/navigation-store.test.js +440 -0
  34. package/dist/__tests__/navigation-store.test.js.map +1 -0
  35. package/dist/__tests__/partial-update.test.d.ts +2 -0
  36. package/dist/__tests__/partial-update.test.d.ts.map +1 -0
  37. package/dist/__tests__/partial-update.test.js +1009 -0
  38. package/dist/__tests__/partial-update.test.js.map +1 -0
  39. package/dist/__tests__/reverse-types.test.d.ts +8 -0
  40. package/dist/__tests__/reverse-types.test.d.ts.map +1 -0
  41. package/dist/__tests__/reverse-types.test.js +656 -0
  42. package/dist/__tests__/reverse-types.test.js.map +1 -0
  43. package/dist/__tests__/route-definition.test.d.ts +2 -0
  44. package/dist/__tests__/route-definition.test.d.ts.map +1 -0
  45. package/dist/__tests__/route-definition.test.js +55 -0
  46. package/dist/__tests__/route-definition.test.js.map +1 -0
  47. package/dist/__tests__/router-helpers.test.d.ts +2 -0
  48. package/dist/__tests__/router-helpers.test.d.ts.map +1 -0
  49. package/dist/__tests__/router-helpers.test.js +377 -0
  50. package/dist/__tests__/router-helpers.test.js.map +1 -0
  51. package/dist/__tests__/router-integration-2.test.d.ts +2 -0
  52. package/dist/__tests__/router-integration-2.test.d.ts.map +1 -0
  53. package/dist/__tests__/router-integration-2.test.js +426 -0
  54. package/dist/__tests__/router-integration-2.test.js.map +1 -0
  55. package/dist/__tests__/router-integration.test.d.ts +2 -0
  56. package/dist/__tests__/router-integration.test.d.ts.map +1 -0
  57. package/dist/__tests__/router-integration.test.js +1051 -0
  58. package/dist/__tests__/router-integration.test.js.map +1 -0
  59. package/dist/__tests__/search-params.test.d.ts +5 -0
  60. package/dist/__tests__/search-params.test.d.ts.map +1 -0
  61. package/dist/__tests__/search-params.test.js +306 -0
  62. package/dist/__tests__/search-params.test.js.map +1 -0
  63. package/dist/__tests__/segment-system.test.d.ts +2 -0
  64. package/dist/__tests__/segment-system.test.d.ts.map +1 -0
  65. package/dist/__tests__/segment-system.test.js +627 -0
  66. package/dist/__tests__/segment-system.test.js.map +1 -0
  67. package/dist/__tests__/static-handler-types.test.d.ts +8 -0
  68. package/dist/__tests__/static-handler-types.test.d.ts.map +1 -0
  69. package/dist/__tests__/static-handler-types.test.js +63 -0
  70. package/dist/__tests__/static-handler-types.test.js.map +1 -0
  71. package/dist/__tests__/urls.test.d.ts +2 -0
  72. package/dist/__tests__/urls.test.d.ts.map +1 -0
  73. package/dist/__tests__/urls.test.js +421 -0
  74. package/dist/__tests__/urls.test.js.map +1 -0
  75. package/dist/__tests__/use-mount.test.d.ts +2 -0
  76. package/dist/__tests__/use-mount.test.d.ts.map +1 -0
  77. package/dist/__tests__/use-mount.test.js +35 -0
  78. package/dist/__tests__/use-mount.test.js.map +1 -0
  79. package/dist/bin/rango.d.ts +2 -0
  80. package/dist/bin/rango.d.ts.map +1 -0
  81. package/dist/bin/rango.js +1531 -212
  82. package/dist/bin/rango.js.map +1 -0
  83. package/dist/browser/event-controller.d.ts +191 -0
  84. package/dist/browser/event-controller.d.ts.map +1 -0
  85. package/dist/browser/event-controller.js +559 -0
  86. package/dist/browser/event-controller.js.map +1 -0
  87. package/dist/browser/index.d.ts +2 -0
  88. package/dist/browser/index.d.ts.map +1 -0
  89. package/dist/browser/index.js +14 -0
  90. package/dist/browser/index.js.map +1 -0
  91. package/dist/browser/link-interceptor.d.ts +38 -0
  92. package/dist/browser/link-interceptor.d.ts.map +1 -0
  93. package/dist/browser/link-interceptor.js +99 -0
  94. package/dist/browser/link-interceptor.js.map +1 -0
  95. package/dist/browser/logging.d.ts +10 -0
  96. package/dist/browser/logging.d.ts.map +1 -0
  97. package/dist/browser/logging.js +29 -0
  98. package/dist/browser/logging.js.map +1 -0
  99. package/dist/browser/lru-cache.d.ts +17 -0
  100. package/dist/browser/lru-cache.d.ts.map +1 -0
  101. package/dist/browser/lru-cache.js +50 -0
  102. package/dist/browser/lru-cache.js.map +1 -0
  103. package/dist/browser/merge-segment-loaders.d.ts +39 -0
  104. package/dist/browser/merge-segment-loaders.d.ts.map +1 -0
  105. package/dist/browser/merge-segment-loaders.js +102 -0
  106. package/dist/browser/merge-segment-loaders.js.map +1 -0
  107. package/dist/browser/navigation-bridge.d.ts +102 -0
  108. package/dist/browser/navigation-bridge.d.ts.map +1 -0
  109. package/dist/browser/navigation-bridge.js +708 -0
  110. package/dist/browser/navigation-bridge.js.map +1 -0
  111. package/dist/browser/navigation-client.d.ts +25 -0
  112. package/dist/browser/navigation-client.d.ts.map +1 -0
  113. package/dist/browser/navigation-client.js +157 -0
  114. package/dist/browser/navigation-client.js.map +1 -0
  115. package/dist/browser/navigation-store.d.ts +101 -0
  116. package/dist/browser/navigation-store.d.ts.map +1 -0
  117. package/dist/browser/navigation-store.js +625 -0
  118. package/dist/browser/navigation-store.js.map +1 -0
  119. package/dist/browser/partial-update.d.ts +75 -0
  120. package/dist/browser/partial-update.d.ts.map +1 -0
  121. package/dist/browser/partial-update.js +426 -0
  122. package/dist/browser/partial-update.js.map +1 -0
  123. package/dist/browser/react/Link.d.ts +86 -0
  124. package/dist/browser/react/Link.d.ts.map +1 -0
  125. package/dist/browser/react/Link.js +128 -0
  126. package/dist/browser/react/Link.js.map +1 -0
  127. package/dist/browser/react/NavigationProvider.d.ts +63 -0
  128. package/dist/browser/react/NavigationProvider.d.ts.map +1 -0
  129. package/dist/browser/react/NavigationProvider.js +216 -0
  130. package/dist/browser/react/NavigationProvider.js.map +1 -0
  131. package/dist/browser/react/ScrollRestoration.d.ts +75 -0
  132. package/dist/browser/react/ScrollRestoration.d.ts.map +1 -0
  133. package/dist/browser/react/ScrollRestoration.js +57 -0
  134. package/dist/browser/react/ScrollRestoration.js.map +1 -0
  135. package/dist/browser/react/context.d.ts +46 -0
  136. package/dist/browser/react/context.d.ts.map +1 -0
  137. package/dist/browser/react/context.js +10 -0
  138. package/dist/browser/react/context.js.map +1 -0
  139. package/dist/browser/react/index.d.ts +11 -0
  140. package/dist/browser/react/index.d.ts.map +1 -0
  141. package/dist/browser/react/index.js +22 -0
  142. package/dist/browser/react/index.js.map +1 -0
  143. package/dist/browser/react/location-state-shared.d.ts +63 -0
  144. package/dist/browser/react/location-state-shared.d.ts.map +1 -0
  145. package/dist/browser/react/location-state-shared.js +81 -0
  146. package/dist/browser/react/location-state-shared.js.map +1 -0
  147. package/dist/browser/react/location-state.d.ts +23 -0
  148. package/dist/browser/react/location-state.d.ts.map +1 -0
  149. package/dist/browser/react/location-state.js +29 -0
  150. package/dist/browser/react/location-state.js.map +1 -0
  151. package/dist/browser/react/mount-context.d.ts +24 -0
  152. package/dist/browser/react/mount-context.d.ts.map +1 -0
  153. package/dist/browser/react/mount-context.js +24 -0
  154. package/dist/browser/react/mount-context.js.map +1 -0
  155. package/dist/browser/react/use-action.d.ts +64 -0
  156. package/dist/browser/react/use-action.d.ts.map +1 -0
  157. package/dist/browser/react/use-action.js +134 -0
  158. package/dist/browser/react/use-action.js.map +1 -0
  159. package/dist/browser/react/use-client-cache.d.ts +41 -0
  160. package/dist/browser/react/use-client-cache.d.ts.map +1 -0
  161. package/dist/browser/react/use-client-cache.js +39 -0
  162. package/dist/browser/react/use-client-cache.js.map +1 -0
  163. package/dist/browser/react/use-handle.d.ts +31 -0
  164. package/dist/browser/react/use-handle.d.ts.map +1 -0
  165. package/dist/browser/react/use-handle.js +144 -0
  166. package/dist/browser/react/use-handle.js.map +1 -0
  167. package/dist/browser/react/use-href.d.ts +33 -0
  168. package/dist/browser/react/use-href.d.ts.map +1 -0
  169. package/dist/browser/react/use-href.js +39 -0
  170. package/dist/browser/react/use-href.js.map +1 -0
  171. package/dist/browser/react/use-link-status.d.ts +37 -0
  172. package/dist/browser/react/use-link-status.d.ts.map +1 -0
  173. package/dist/browser/react/use-link-status.js +99 -0
  174. package/dist/browser/react/use-link-status.js.map +1 -0
  175. package/dist/browser/react/use-mount.d.ts +25 -0
  176. package/dist/browser/react/use-mount.d.ts.map +1 -0
  177. package/dist/browser/react/use-mount.js +30 -0
  178. package/dist/browser/react/use-mount.js.map +1 -0
  179. package/dist/browser/react/use-navigation.d.ts +27 -0
  180. package/dist/browser/react/use-navigation.d.ts.map +1 -0
  181. package/dist/browser/react/use-navigation.js +87 -0
  182. package/dist/browser/react/use-navigation.js.map +1 -0
  183. package/dist/browser/react/use-segments.d.ts +38 -0
  184. package/dist/browser/react/use-segments.d.ts.map +1 -0
  185. package/dist/browser/react/use-segments.js +130 -0
  186. package/dist/browser/react/use-segments.js.map +1 -0
  187. package/dist/browser/request-controller.d.ts +26 -0
  188. package/dist/browser/request-controller.d.ts.map +1 -0
  189. package/dist/browser/request-controller.js +147 -0
  190. package/dist/browser/request-controller.js.map +1 -0
  191. package/dist/browser/rsc-router.d.ts +129 -0
  192. package/dist/browser/rsc-router.d.ts.map +1 -0
  193. package/dist/browser/rsc-router.js +195 -0
  194. package/dist/browser/rsc-router.js.map +1 -0
  195. package/dist/browser/scroll-restoration.d.ts +93 -0
  196. package/dist/browser/scroll-restoration.d.ts.map +1 -0
  197. package/dist/browser/scroll-restoration.js +321 -0
  198. package/dist/browser/scroll-restoration.js.map +1 -0
  199. package/dist/browser/segment-structure-assert.d.ts +17 -0
  200. package/dist/browser/segment-structure-assert.d.ts.map +1 -0
  201. package/dist/browser/segment-structure-assert.js +59 -0
  202. package/dist/browser/segment-structure-assert.js.map +1 -0
  203. package/dist/browser/server-action-bridge.d.ts +26 -0
  204. package/dist/browser/server-action-bridge.d.ts.map +1 -0
  205. package/dist/browser/server-action-bridge.js +668 -0
  206. package/dist/browser/server-action-bridge.js.map +1 -0
  207. package/dist/browser/shallow.d.ts +12 -0
  208. package/dist/browser/shallow.d.ts.map +1 -0
  209. package/dist/browser/shallow.js +34 -0
  210. package/dist/browser/shallow.js.map +1 -0
  211. package/dist/browser/types.d.ts +369 -0
  212. package/dist/browser/types.d.ts.map +1 -0
  213. package/dist/browser/types.js +2 -0
  214. package/dist/browser/types.js.map +1 -0
  215. package/dist/build/__tests__/generate-cli.test.d.ts +2 -0
  216. package/dist/build/__tests__/generate-cli.test.d.ts.map +1 -0
  217. package/dist/build/__tests__/generate-cli.test.js +237 -0
  218. package/dist/build/__tests__/generate-cli.test.js.map +1 -0
  219. package/dist/build/__tests__/generate-manifest.test.d.ts +2 -0
  220. package/dist/build/__tests__/generate-manifest.test.d.ts.map +1 -0
  221. package/dist/build/__tests__/generate-manifest.test.js +119 -0
  222. package/dist/build/__tests__/generate-manifest.test.js.map +1 -0
  223. package/dist/build/__tests__/generate-route-types.test.d.ts +2 -0
  224. package/dist/build/__tests__/generate-route-types.test.d.ts.map +1 -0
  225. package/dist/build/__tests__/generate-route-types.test.js +620 -0
  226. package/dist/build/__tests__/generate-route-types.test.js.map +1 -0
  227. package/dist/build/__tests__/per-router-manifest.test.d.ts +2 -0
  228. package/dist/build/__tests__/per-router-manifest.test.d.ts.map +1 -0
  229. package/dist/build/__tests__/per-router-manifest.test.js +308 -0
  230. package/dist/build/__tests__/per-router-manifest.test.js.map +1 -0
  231. package/dist/build/generate-manifest.d.ts +81 -0
  232. package/dist/build/generate-manifest.d.ts.map +1 -0
  233. package/dist/build/generate-manifest.js +276 -0
  234. package/dist/build/generate-manifest.js.map +1 -0
  235. package/dist/build/generate-route-types.d.ts +115 -0
  236. package/dist/build/generate-route-types.d.ts.map +1 -0
  237. package/dist/build/generate-route-types.js +740 -0
  238. package/dist/build/generate-route-types.js.map +1 -0
  239. package/dist/build/index.d.ts +21 -0
  240. package/dist/build/index.d.ts.map +1 -0
  241. package/dist/build/index.js +21 -0
  242. package/dist/build/index.js.map +1 -0
  243. package/dist/build/route-trie.d.ts +71 -0
  244. package/dist/build/route-trie.d.ts.map +1 -0
  245. package/dist/build/route-trie.js +175 -0
  246. package/dist/build/route-trie.js.map +1 -0
  247. package/dist/cache/__tests__/cache-scope.test.d.ts +2 -0
  248. package/dist/cache/__tests__/cache-scope.test.d.ts.map +1 -0
  249. package/dist/cache/__tests__/cache-scope.test.js +208 -0
  250. package/dist/cache/__tests__/cache-scope.test.js.map +1 -0
  251. package/dist/cache/__tests__/document-cache.test.d.ts +2 -0
  252. package/dist/cache/__tests__/document-cache.test.d.ts.map +1 -0
  253. package/dist/cache/__tests__/document-cache.test.js +345 -0
  254. package/dist/cache/__tests__/document-cache.test.js.map +1 -0
  255. package/dist/cache/__tests__/memory-segment-store.test.d.ts +2 -0
  256. package/dist/cache/__tests__/memory-segment-store.test.d.ts.map +1 -0
  257. package/dist/cache/__tests__/memory-segment-store.test.js +425 -0
  258. package/dist/cache/__tests__/memory-segment-store.test.js.map +1 -0
  259. package/dist/cache/__tests__/memory-store.test.d.ts +2 -0
  260. package/dist/cache/__tests__/memory-store.test.d.ts.map +1 -0
  261. package/dist/cache/__tests__/memory-store.test.js +367 -0
  262. package/dist/cache/__tests__/memory-store.test.js.map +1 -0
  263. package/dist/cache/cache-scope.d.ts +102 -0
  264. package/dist/cache/cache-scope.d.ts.map +1 -0
  265. package/dist/cache/cache-scope.js +440 -0
  266. package/dist/cache/cache-scope.js.map +1 -0
  267. package/dist/cache/cf/__tests__/cf-cache-store.test.d.ts +2 -0
  268. package/dist/cache/cf/__tests__/cf-cache-store.test.d.ts.map +1 -0
  269. package/dist/cache/cf/__tests__/cf-cache-store.test.js +330 -0
  270. package/dist/cache/cf/__tests__/cf-cache-store.test.js.map +1 -0
  271. package/dist/cache/cf/cf-cache-store.d.ts +165 -0
  272. package/dist/cache/cf/cf-cache-store.d.ts.map +1 -0
  273. package/dist/cache/cf/cf-cache-store.js +242 -0
  274. package/dist/cache/cf/cf-cache-store.js.map +1 -0
  275. package/dist/cache/cf/index.d.ts +14 -0
  276. package/dist/cache/cf/index.d.ts.map +1 -0
  277. package/dist/cache/cf/index.js +17 -0
  278. package/dist/cache/cf/index.js.map +1 -0
  279. package/dist/cache/document-cache.d.ts +64 -0
  280. package/dist/cache/document-cache.d.ts.map +1 -0
  281. package/dist/cache/document-cache.js +228 -0
  282. package/dist/cache/document-cache.js.map +1 -0
  283. package/dist/cache/index.d.ts +19 -0
  284. package/dist/cache/index.d.ts.map +1 -0
  285. package/dist/cache/index.js +21 -0
  286. package/dist/cache/index.js.map +1 -0
  287. package/dist/cache/memory-segment-store.d.ts +110 -0
  288. package/dist/cache/memory-segment-store.d.ts.map +1 -0
  289. package/dist/cache/memory-segment-store.js +117 -0
  290. package/dist/cache/memory-segment-store.js.map +1 -0
  291. package/dist/cache/memory-store.d.ts +41 -0
  292. package/dist/cache/memory-store.d.ts.map +1 -0
  293. package/dist/cache/memory-store.js +191 -0
  294. package/dist/cache/memory-store.js.map +1 -0
  295. package/dist/cache/types.d.ts +317 -0
  296. package/dist/cache/types.d.ts.map +1 -0
  297. package/dist/cache/types.js +12 -0
  298. package/dist/cache/types.js.map +1 -0
  299. package/dist/client.d.ts +248 -0
  300. package/dist/client.d.ts.map +1 -0
  301. package/dist/client.js +367 -0
  302. package/dist/client.js.map +1 -0
  303. package/dist/client.rsc.d.ts +26 -0
  304. package/dist/client.rsc.d.ts.map +1 -0
  305. package/dist/client.rsc.js +46 -0
  306. package/dist/client.rsc.js.map +1 -0
  307. package/dist/component-utils.d.ts +36 -0
  308. package/dist/component-utils.d.ts.map +1 -0
  309. package/dist/component-utils.js +61 -0
  310. package/dist/component-utils.js.map +1 -0
  311. package/dist/components/DefaultDocument.d.ts +13 -0
  312. package/dist/components/DefaultDocument.d.ts.map +1 -0
  313. package/dist/components/DefaultDocument.js +15 -0
  314. package/dist/components/DefaultDocument.js.map +1 -0
  315. package/dist/debug.d.ts +58 -0
  316. package/dist/debug.d.ts.map +1 -0
  317. package/dist/debug.js +157 -0
  318. package/dist/debug.js.map +1 -0
  319. package/dist/default-error-boundary.d.ts +11 -0
  320. package/dist/default-error-boundary.d.ts.map +1 -0
  321. package/dist/default-error-boundary.js +45 -0
  322. package/dist/default-error-boundary.js.map +1 -0
  323. package/dist/deps/browser.d.ts +2 -0
  324. package/dist/deps/browser.d.ts.map +1 -0
  325. package/dist/deps/browser.js +3 -0
  326. package/dist/deps/browser.js.map +1 -0
  327. package/dist/deps/html-stream-client.d.ts +2 -0
  328. package/dist/deps/html-stream-client.d.ts.map +1 -0
  329. package/dist/deps/html-stream-client.js +3 -0
  330. package/dist/deps/html-stream-client.js.map +1 -0
  331. package/dist/deps/html-stream-server.d.ts +2 -0
  332. package/dist/deps/html-stream-server.d.ts.map +1 -0
  333. package/dist/deps/html-stream-server.js +3 -0
  334. package/dist/deps/html-stream-server.js.map +1 -0
  335. package/dist/deps/rsc.d.ts +2 -0
  336. package/dist/deps/rsc.d.ts.map +1 -0
  337. package/dist/deps/rsc.js +4 -0
  338. package/dist/deps/rsc.js.map +1 -0
  339. package/dist/deps/ssr.d.ts +2 -0
  340. package/dist/deps/ssr.d.ts.map +1 -0
  341. package/dist/deps/ssr.js +3 -0
  342. package/dist/deps/ssr.js.map +1 -0
  343. package/dist/errors.d.ts +174 -0
  344. package/dist/errors.d.ts.map +1 -0
  345. package/dist/errors.js +241 -0
  346. package/dist/errors.js.map +1 -0
  347. package/dist/handle.d.ts +78 -0
  348. package/dist/handle.d.ts.map +1 -0
  349. package/dist/handle.js +82 -0
  350. package/dist/handle.js.map +1 -0
  351. package/dist/handles/MetaTags.d.ts +14 -0
  352. package/dist/handles/MetaTags.d.ts.map +1 -0
  353. package/dist/handles/MetaTags.js +136 -0
  354. package/dist/handles/MetaTags.js.map +1 -0
  355. package/dist/handles/index.d.ts +6 -0
  356. package/dist/handles/index.d.ts.map +1 -0
  357. package/dist/handles/index.js +6 -0
  358. package/dist/handles/index.js.map +1 -0
  359. package/dist/handles/meta.d.ts +39 -0
  360. package/dist/handles/meta.d.ts.map +1 -0
  361. package/dist/handles/meta.js +202 -0
  362. package/dist/handles/meta.js.map +1 -0
  363. package/dist/host/__tests__/errors.test.d.ts +2 -0
  364. package/dist/host/__tests__/errors.test.d.ts.map +1 -0
  365. package/dist/host/__tests__/errors.test.js +76 -0
  366. package/dist/host/__tests__/errors.test.js.map +1 -0
  367. package/dist/host/__tests__/pattern-comprehensive.test.d.ts +2 -0
  368. package/dist/host/__tests__/pattern-comprehensive.test.d.ts.map +1 -0
  369. package/dist/host/__tests__/pattern-comprehensive.test.js +732 -0
  370. package/dist/host/__tests__/pattern-comprehensive.test.js.map +1 -0
  371. package/dist/host/__tests__/pattern-matcher.test.d.ts +2 -0
  372. package/dist/host/__tests__/pattern-matcher.test.d.ts.map +1 -0
  373. package/dist/host/__tests__/pattern-matcher.test.js +251 -0
  374. package/dist/host/__tests__/pattern-matcher.test.js.map +1 -0
  375. package/dist/host/__tests__/router.test.d.ts +2 -0
  376. package/dist/host/__tests__/router.test.d.ts.map +1 -0
  377. package/dist/host/__tests__/router.test.js +241 -0
  378. package/dist/host/__tests__/router.test.js.map +1 -0
  379. package/dist/host/__tests__/testing.test.d.ts +2 -0
  380. package/dist/host/__tests__/testing.test.d.ts.map +1 -0
  381. package/dist/host/__tests__/testing.test.js +64 -0
  382. package/dist/host/__tests__/testing.test.js.map +1 -0
  383. package/dist/host/__tests__/utils.test.d.ts +2 -0
  384. package/dist/host/__tests__/utils.test.d.ts.map +1 -0
  385. package/dist/host/__tests__/utils.test.js +29 -0
  386. package/dist/host/__tests__/utils.test.js.map +1 -0
  387. package/dist/host/cookie-handler.d.ts +34 -0
  388. package/dist/host/cookie-handler.d.ts.map +1 -0
  389. package/dist/host/cookie-handler.js +124 -0
  390. package/dist/host/cookie-handler.js.map +1 -0
  391. package/dist/host/errors.d.ts +56 -0
  392. package/dist/host/errors.d.ts.map +1 -0
  393. package/dist/host/errors.js +79 -0
  394. package/dist/host/errors.js.map +1 -0
  395. package/dist/host/index.d.ts +29 -0
  396. package/dist/host/index.d.ts.map +1 -0
  397. package/dist/host/index.js +32 -0
  398. package/dist/host/index.js.map +1 -0
  399. package/dist/host/pattern-matcher.d.ts +36 -0
  400. package/dist/host/pattern-matcher.d.ts.map +1 -0
  401. package/dist/host/pattern-matcher.js +172 -0
  402. package/dist/host/pattern-matcher.js.map +1 -0
  403. package/dist/host/router.d.ts +26 -0
  404. package/dist/host/router.d.ts.map +1 -0
  405. package/dist/host/router.js +218 -0
  406. package/dist/host/router.js.map +1 -0
  407. package/dist/host/testing.d.ts +36 -0
  408. package/dist/host/testing.d.ts.map +1 -0
  409. package/dist/host/testing.js +55 -0
  410. package/dist/host/testing.js.map +1 -0
  411. package/dist/host/types.d.ts +115 -0
  412. package/dist/host/types.d.ts.map +1 -0
  413. package/dist/host/types.js +7 -0
  414. package/dist/host/types.js.map +1 -0
  415. package/dist/host/utils.d.ts +21 -0
  416. package/dist/host/utils.d.ts.map +1 -0
  417. package/dist/host/utils.js +23 -0
  418. package/dist/host/utils.js.map +1 -0
  419. package/dist/href-client.d.ts +131 -0
  420. package/dist/href-client.d.ts.map +1 -0
  421. package/dist/href-client.js +64 -0
  422. package/dist/href-client.js.map +1 -0
  423. package/{src/href-context.ts → dist/href-context.d.ts} +7 -11
  424. package/dist/href-context.d.ts.map +1 -0
  425. package/dist/href-context.js +21 -0
  426. package/dist/href-context.js.map +1 -0
  427. package/dist/index.d.ts +73 -0
  428. package/dist/index.d.ts.map +1 -0
  429. package/dist/index.js +91 -0
  430. package/dist/index.js.map +1 -0
  431. package/dist/index.rsc.d.ts +32 -0
  432. package/dist/index.rsc.d.ts.map +1 -0
  433. package/dist/index.rsc.js +40 -0
  434. package/dist/index.rsc.js.map +1 -0
  435. package/dist/internal-debug.d.ts +2 -0
  436. package/dist/internal-debug.d.ts.map +1 -0
  437. package/dist/internal-debug.js +5 -0
  438. package/dist/internal-debug.js.map +1 -0
  439. package/dist/loader.d.ts +14 -0
  440. package/dist/loader.d.ts.map +1 -0
  441. package/dist/loader.js +20 -0
  442. package/dist/loader.js.map +1 -0
  443. package/dist/loader.rsc.d.ts +19 -0
  444. package/dist/loader.rsc.d.ts.map +1 -0
  445. package/dist/loader.rsc.js +99 -0
  446. package/dist/loader.rsc.js.map +1 -0
  447. package/dist/network-error-thrower.d.ts +17 -0
  448. package/dist/network-error-thrower.d.ts.map +1 -0
  449. package/dist/network-error-thrower.js +14 -0
  450. package/dist/network-error-thrower.js.map +1 -0
  451. package/dist/outlet-context.d.ts +13 -0
  452. package/dist/outlet-context.d.ts.map +1 -0
  453. package/dist/outlet-context.js +3 -0
  454. package/dist/outlet-context.js.map +1 -0
  455. package/dist/prerender/__tests__/param-hash.test.d.ts +2 -0
  456. package/dist/prerender/__tests__/param-hash.test.d.ts.map +1 -0
  457. package/dist/prerender/__tests__/param-hash.test.js +148 -0
  458. package/dist/prerender/__tests__/param-hash.test.js.map +1 -0
  459. package/dist/prerender/param-hash.d.ts +16 -0
  460. package/dist/prerender/param-hash.d.ts.map +1 -0
  461. package/dist/prerender/param-hash.js +36 -0
  462. package/dist/prerender/param-hash.js.map +1 -0
  463. package/dist/prerender/store.d.ts +38 -0
  464. package/dist/prerender/store.d.ts.map +1 -0
  465. package/dist/prerender/store.js +61 -0
  466. package/dist/prerender/store.js.map +1 -0
  467. package/dist/prerender.d.ts +66 -0
  468. package/dist/prerender.d.ts.map +1 -0
  469. package/dist/prerender.js +57 -0
  470. package/dist/prerender.js.map +1 -0
  471. package/dist/reverse.d.ts +196 -0
  472. package/dist/reverse.d.ts.map +1 -0
  473. package/dist/reverse.js +78 -0
  474. package/dist/reverse.js.map +1 -0
  475. package/dist/root-error-boundary.d.ts +33 -0
  476. package/dist/root-error-boundary.d.ts.map +1 -0
  477. package/dist/root-error-boundary.js +165 -0
  478. package/dist/root-error-boundary.js.map +1 -0
  479. package/dist/route-content-wrapper.d.ts +46 -0
  480. package/dist/route-content-wrapper.d.ts.map +1 -0
  481. package/dist/route-content-wrapper.js +77 -0
  482. package/dist/route-content-wrapper.js.map +1 -0
  483. package/dist/route-definition.d.ts +421 -0
  484. package/dist/route-definition.d.ts.map +1 -0
  485. package/dist/route-definition.js +868 -0
  486. package/dist/route-definition.js.map +1 -0
  487. package/dist/route-map-builder.d.ts +155 -0
  488. package/dist/route-map-builder.d.ts.map +1 -0
  489. package/dist/route-map-builder.js +237 -0
  490. package/dist/route-map-builder.js.map +1 -0
  491. package/dist/route-types.d.ts +165 -0
  492. package/dist/route-types.d.ts.map +1 -0
  493. package/dist/route-types.js +7 -0
  494. package/dist/route-types.js.map +1 -0
  495. package/dist/router/__tests__/handler-context.test.d.ts +2 -0
  496. package/dist/router/__tests__/handler-context.test.d.ts.map +1 -0
  497. package/dist/router/__tests__/handler-context.test.js +65 -0
  498. package/dist/router/__tests__/handler-context.test.js.map +1 -0
  499. package/dist/router/__tests__/loader-cycle-detection.test.d.ts +2 -0
  500. package/dist/router/__tests__/loader-cycle-detection.test.d.ts.map +1 -0
  501. package/dist/router/__tests__/loader-cycle-detection.test.js +221 -0
  502. package/dist/router/__tests__/loader-cycle-detection.test.js.map +1 -0
  503. package/dist/router/__tests__/match-context.test.d.ts +2 -0
  504. package/dist/router/__tests__/match-context.test.d.ts.map +1 -0
  505. package/dist/router/__tests__/match-context.test.js +92 -0
  506. package/dist/router/__tests__/match-context.test.js.map +1 -0
  507. package/dist/router/__tests__/match-pipelines.test.d.ts +2 -0
  508. package/dist/router/__tests__/match-pipelines.test.d.ts.map +1 -0
  509. package/dist/router/__tests__/match-pipelines.test.js +417 -0
  510. package/dist/router/__tests__/match-pipelines.test.js.map +1 -0
  511. package/dist/router/__tests__/match-result.test.d.ts +2 -0
  512. package/dist/router/__tests__/match-result.test.d.ts.map +1 -0
  513. package/dist/router/__tests__/match-result.test.js +457 -0
  514. package/dist/router/__tests__/match-result.test.js.map +1 -0
  515. package/dist/router/__tests__/on-error.test.d.ts +2 -0
  516. package/dist/router/__tests__/on-error.test.d.ts.map +1 -0
  517. package/dist/router/__tests__/on-error.test.js +678 -0
  518. package/dist/router/__tests__/on-error.test.js.map +1 -0
  519. package/dist/router/__tests__/pattern-matching.test.d.ts +2 -0
  520. package/dist/router/__tests__/pattern-matching.test.d.ts.map +1 -0
  521. package/dist/router/__tests__/pattern-matching.test.js +629 -0
  522. package/dist/router/__tests__/pattern-matching.test.js.map +1 -0
  523. package/dist/router/__tests__/segment-resolution-parallel-loading.test.d.ts +2 -0
  524. package/dist/router/__tests__/segment-resolution-parallel-loading.test.d.ts.map +1 -0
  525. package/dist/router/__tests__/segment-resolution-parallel-loading.test.js +155 -0
  526. package/dist/router/__tests__/segment-resolution-parallel-loading.test.js.map +1 -0
  527. package/dist/router/error-handling.d.ts +77 -0
  528. package/dist/router/error-handling.d.ts.map +1 -0
  529. package/dist/router/error-handling.js +202 -0
  530. package/dist/router/error-handling.js.map +1 -0
  531. package/dist/router/handler-context.d.ts +20 -0
  532. package/dist/router/handler-context.d.ts.map +1 -0
  533. package/dist/router/handler-context.js +198 -0
  534. package/dist/router/handler-context.js.map +1 -0
  535. package/dist/router/intercept-resolution.d.ts +66 -0
  536. package/dist/router/intercept-resolution.d.ts.map +1 -0
  537. package/dist/router/intercept-resolution.js +246 -0
  538. package/dist/router/intercept-resolution.js.map +1 -0
  539. package/dist/router/loader-resolution.d.ts +64 -0
  540. package/dist/router/loader-resolution.d.ts.map +1 -0
  541. package/dist/router/loader-resolution.js +284 -0
  542. package/dist/router/loader-resolution.js.map +1 -0
  543. package/dist/router/logging.d.ts +15 -0
  544. package/dist/router/logging.d.ts.map +1 -0
  545. package/dist/router/logging.js +99 -0
  546. package/dist/router/logging.js.map +1 -0
  547. package/dist/router/manifest.d.ts +22 -0
  548. package/dist/router/manifest.d.ts.map +1 -0
  549. package/dist/router/manifest.js +181 -0
  550. package/dist/router/manifest.js.map +1 -0
  551. package/dist/router/match-api.d.ts +35 -0
  552. package/dist/router/match-api.d.ts.map +1 -0
  553. package/dist/router/match-api.js +406 -0
  554. package/dist/router/match-api.js.map +1 -0
  555. package/dist/router/match-context.d.ts +206 -0
  556. package/dist/router/match-context.d.ts.map +1 -0
  557. package/dist/router/match-context.js +17 -0
  558. package/dist/router/match-context.js.map +1 -0
  559. package/dist/router/match-middleware/background-revalidation.d.ts +127 -0
  560. package/dist/router/match-middleware/background-revalidation.d.ts.map +1 -0
  561. package/dist/router/match-middleware/background-revalidation.js +75 -0
  562. package/dist/router/match-middleware/background-revalidation.js.map +1 -0
  563. package/dist/router/match-middleware/cache-lookup.d.ts +112 -0
  564. package/dist/router/match-middleware/cache-lookup.d.ts.map +1 -0
  565. package/dist/router/match-middleware/cache-lookup.js +257 -0
  566. package/dist/router/match-middleware/cache-lookup.js.map +1 -0
  567. package/dist/router/match-middleware/cache-store.d.ts +113 -0
  568. package/dist/router/match-middleware/cache-store.d.ts.map +1 -0
  569. package/dist/router/match-middleware/cache-store.js +108 -0
  570. package/dist/router/match-middleware/cache-store.js.map +1 -0
  571. package/dist/router/match-middleware/index.d.ts +81 -0
  572. package/dist/router/match-middleware/index.d.ts.map +1 -0
  573. package/dist/router/match-middleware/index.js +80 -0
  574. package/dist/router/match-middleware/index.js.map +1 -0
  575. package/dist/router/match-middleware/intercept-resolution.d.ts +117 -0
  576. package/dist/router/match-middleware/intercept-resolution.d.ts.map +1 -0
  577. package/dist/router/match-middleware/intercept-resolution.js +134 -0
  578. package/dist/router/match-middleware/intercept-resolution.js.map +1 -0
  579. package/dist/router/match-middleware/segment-resolution.d.ts +99 -0
  580. package/dist/router/match-middleware/segment-resolution.d.ts.map +1 -0
  581. package/dist/router/match-middleware/segment-resolution.js +53 -0
  582. package/dist/router/match-middleware/segment-resolution.js.map +1 -0
  583. package/dist/router/match-pipelines.d.ts +147 -0
  584. package/dist/router/match-pipelines.d.ts.map +1 -0
  585. package/dist/router/match-pipelines.js +82 -0
  586. package/dist/router/match-pipelines.js.map +1 -0
  587. package/dist/router/match-result.d.ts +126 -0
  588. package/dist/router/match-result.d.ts.map +1 -0
  589. package/dist/router/match-result.js +93 -0
  590. package/dist/router/match-result.js.map +1 -0
  591. package/dist/router/metrics.d.ts +20 -0
  592. package/dist/router/metrics.d.ts.map +1 -0
  593. package/dist/router/metrics.js +47 -0
  594. package/dist/router/metrics.js.map +1 -0
  595. package/dist/router/middleware.d.ts +249 -0
  596. package/dist/router/middleware.d.ts.map +1 -0
  597. package/dist/router/middleware.js +434 -0
  598. package/dist/router/middleware.js.map +1 -0
  599. package/dist/router/middleware.test.d.ts +2 -0
  600. package/dist/router/middleware.test.d.ts.map +1 -0
  601. package/dist/router/middleware.test.js +816 -0
  602. package/dist/router/middleware.test.js.map +1 -0
  603. package/dist/router/pattern-matching.d.ts +149 -0
  604. package/dist/router/pattern-matching.d.ts.map +1 -0
  605. package/dist/router/pattern-matching.js +349 -0
  606. package/dist/router/pattern-matching.js.map +1 -0
  607. package/dist/router/revalidation.d.ts +44 -0
  608. package/dist/router/revalidation.d.ts.map +1 -0
  609. package/dist/router/revalidation.js +147 -0
  610. package/dist/router/revalidation.js.map +1 -0
  611. package/dist/router/router-context.d.ts +135 -0
  612. package/dist/router/router-context.d.ts.map +1 -0
  613. package/dist/router/router-context.js +36 -0
  614. package/dist/router/router-context.js.map +1 -0
  615. package/dist/router/segment-resolution.d.ts +127 -0
  616. package/dist/router/segment-resolution.d.ts.map +1 -0
  617. package/dist/router/segment-resolution.js +919 -0
  618. package/dist/router/segment-resolution.js.map +1 -0
  619. package/dist/router/trie-matching.d.ts +40 -0
  620. package/dist/router/trie-matching.d.ts.map +1 -0
  621. package/dist/router/trie-matching.js +127 -0
  622. package/dist/router/trie-matching.js.map +1 -0
  623. package/dist/router/types.d.ts +136 -0
  624. package/dist/router/types.d.ts.map +1 -0
  625. package/dist/router/types.js +7 -0
  626. package/dist/router/types.js.map +1 -0
  627. package/dist/router.d.ts +753 -0
  628. package/dist/router.d.ts.map +1 -0
  629. package/dist/router.gen.d.ts +6 -0
  630. package/dist/router.gen.d.ts.map +1 -0
  631. package/dist/router.gen.js +6 -0
  632. package/dist/router.gen.js.map +1 -0
  633. package/dist/router.js +1304 -0
  634. package/dist/router.js.map +1 -0
  635. package/dist/rsc/__tests__/helpers.test.d.ts +2 -0
  636. package/dist/rsc/__tests__/helpers.test.d.ts.map +1 -0
  637. package/dist/rsc/__tests__/helpers.test.js +140 -0
  638. package/dist/rsc/__tests__/helpers.test.js.map +1 -0
  639. package/dist/rsc/handler.d.ts +45 -0
  640. package/dist/rsc/handler.d.ts.map +1 -0
  641. package/dist/rsc/handler.js +1172 -0
  642. package/dist/rsc/handler.js.map +1 -0
  643. package/dist/rsc/helpers.d.ts +16 -0
  644. package/dist/rsc/helpers.d.ts.map +1 -0
  645. package/dist/rsc/helpers.js +55 -0
  646. package/dist/rsc/helpers.js.map +1 -0
  647. package/dist/rsc/index.d.ts +22 -0
  648. package/dist/rsc/index.d.ts.map +1 -0
  649. package/dist/rsc/index.js +23 -0
  650. package/dist/rsc/index.js.map +1 -0
  651. package/dist/rsc/nonce.d.ts +9 -0
  652. package/dist/rsc/nonce.d.ts.map +1 -0
  653. package/dist/rsc/nonce.js +18 -0
  654. package/dist/rsc/nonce.js.map +1 -0
  655. package/dist/rsc/types.d.ts +206 -0
  656. package/dist/rsc/types.d.ts.map +1 -0
  657. package/dist/rsc/types.js +8 -0
  658. package/dist/rsc/types.js.map +1 -0
  659. package/dist/search-params.d.ts +103 -0
  660. package/dist/search-params.d.ts.map +1 -0
  661. package/dist/search-params.js +74 -0
  662. package/dist/search-params.js.map +1 -0
  663. package/dist/segment-system.d.ts +75 -0
  664. package/dist/segment-system.d.ts.map +1 -0
  665. package/dist/segment-system.js +336 -0
  666. package/dist/segment-system.js.map +1 -0
  667. package/dist/server/context.d.ts +245 -0
  668. package/dist/server/context.d.ts.map +1 -0
  669. package/dist/server/context.js +197 -0
  670. package/dist/server/context.js.map +1 -0
  671. package/dist/server/fetchable-loader-store.d.ts +18 -0
  672. package/dist/server/fetchable-loader-store.d.ts.map +1 -0
  673. package/dist/server/fetchable-loader-store.js +18 -0
  674. package/dist/server/fetchable-loader-store.js.map +1 -0
  675. package/dist/server/handle-store.d.ts +85 -0
  676. package/dist/server/handle-store.d.ts.map +1 -0
  677. package/dist/server/handle-store.js +142 -0
  678. package/dist/server/handle-store.js.map +1 -0
  679. package/dist/server/loader-registry.d.ts +55 -0
  680. package/dist/server/loader-registry.d.ts.map +1 -0
  681. package/dist/server/loader-registry.js +132 -0
  682. package/dist/server/loader-registry.js.map +1 -0
  683. package/dist/server/request-context.d.ts +226 -0
  684. package/dist/server/request-context.d.ts.map +1 -0
  685. package/dist/server/request-context.js +290 -0
  686. package/dist/server/request-context.js.map +1 -0
  687. package/dist/server/root-layout.d.ts +4 -0
  688. package/dist/server/root-layout.d.ts.map +1 -0
  689. package/dist/server/root-layout.js +5 -0
  690. package/dist/server/root-layout.js.map +1 -0
  691. package/dist/server.d.ts +15 -0
  692. package/dist/server.d.ts.map +1 -0
  693. package/dist/server.js +20 -0
  694. package/dist/server.js.map +1 -0
  695. package/dist/ssr/__tests__/ssr-handler.test.d.ts +2 -0
  696. package/dist/ssr/__tests__/ssr-handler.test.d.ts.map +1 -0
  697. package/dist/ssr/__tests__/ssr-handler.test.js +132 -0
  698. package/dist/ssr/__tests__/ssr-handler.test.js.map +1 -0
  699. package/dist/ssr/index.d.ts +98 -0
  700. package/dist/ssr/index.d.ts.map +1 -0
  701. package/dist/ssr/index.js +158 -0
  702. package/dist/ssr/index.js.map +1 -0
  703. package/dist/static-handler.d.ts +50 -0
  704. package/dist/static-handler.d.ts.map +1 -0
  705. package/dist/static-handler.gen.d.ts +5 -0
  706. package/dist/static-handler.gen.d.ts.map +1 -0
  707. package/dist/static-handler.gen.js +5 -0
  708. package/dist/static-handler.gen.js.map +1 -0
  709. package/dist/static-handler.js +29 -0
  710. package/dist/static-handler.js.map +1 -0
  711. package/dist/theme/ThemeProvider.d.ts +20 -0
  712. package/dist/theme/ThemeProvider.d.ts.map +1 -0
  713. package/dist/theme/ThemeProvider.js +240 -0
  714. package/dist/theme/ThemeProvider.js.map +1 -0
  715. package/dist/theme/ThemeScript.d.ts +48 -0
  716. package/dist/theme/ThemeScript.d.ts.map +1 -0
  717. package/dist/theme/ThemeScript.js +13 -0
  718. package/dist/theme/ThemeScript.js.map +1 -0
  719. package/dist/theme/__tests__/theme.test.d.ts +2 -0
  720. package/dist/theme/__tests__/theme.test.d.ts.map +1 -0
  721. package/dist/theme/__tests__/theme.test.js +103 -0
  722. package/dist/theme/__tests__/theme.test.js.map +1 -0
  723. package/dist/theme/constants.d.ts +29 -0
  724. package/dist/theme/constants.d.ts.map +1 -0
  725. package/dist/theme/constants.js +48 -0
  726. package/dist/theme/constants.js.map +1 -0
  727. package/dist/theme/index.d.ts +31 -0
  728. package/dist/theme/index.d.ts.map +1 -0
  729. package/dist/theme/index.js +36 -0
  730. package/dist/theme/index.js.map +1 -0
  731. package/dist/theme/theme-context.d.ts +40 -0
  732. package/dist/theme/theme-context.d.ts.map +1 -0
  733. package/dist/theme/theme-context.js +60 -0
  734. package/dist/theme/theme-context.js.map +1 -0
  735. package/dist/theme/theme-script.d.ts +27 -0
  736. package/dist/theme/theme-script.d.ts.map +1 -0
  737. package/dist/theme/theme-script.js +147 -0
  738. package/dist/theme/theme-script.js.map +1 -0
  739. package/dist/theme/types.d.ts +163 -0
  740. package/dist/theme/types.d.ts.map +1 -0
  741. package/dist/theme/types.js +11 -0
  742. package/dist/theme/types.js.map +1 -0
  743. package/dist/theme/use-theme.d.ts +12 -0
  744. package/dist/theme/use-theme.d.ts.map +1 -0
  745. package/dist/theme/use-theme.js +40 -0
  746. package/dist/theme/use-theme.js.map +1 -0
  747. package/dist/types.d.ts +1479 -0
  748. package/dist/types.d.ts.map +1 -0
  749. package/dist/types.js +10 -0
  750. package/dist/types.js.map +1 -0
  751. package/dist/urls.d.ts +441 -0
  752. package/dist/urls.d.ts.map +1 -0
  753. package/dist/urls.gen.d.ts +8 -0
  754. package/dist/urls.gen.d.ts.map +1 -0
  755. package/dist/urls.gen.js +8 -0
  756. package/dist/urls.gen.js.map +1 -0
  757. package/dist/urls.js +443 -0
  758. package/dist/urls.js.map +1 -0
  759. package/dist/use-loader.d.ts +127 -0
  760. package/dist/use-loader.d.ts.map +1 -0
  761. package/dist/use-loader.js +237 -0
  762. package/dist/use-loader.js.map +1 -0
  763. package/dist/vite/__tests__/ast-handler-extract.test.d.ts +2 -0
  764. package/dist/vite/__tests__/ast-handler-extract.test.d.ts.map +1 -0
  765. package/dist/vite/__tests__/ast-handler-extract.test.js +294 -0
  766. package/dist/vite/__tests__/ast-handler-extract.test.js.map +1 -0
  767. package/dist/vite/__tests__/expose-id-utils.test.d.ts +2 -0
  768. package/dist/vite/__tests__/expose-id-utils.test.d.ts.map +1 -0
  769. package/dist/vite/__tests__/expose-id-utils.test.js +224 -0
  770. package/dist/vite/__tests__/expose-id-utils.test.js.map +1 -0
  771. package/dist/vite/__tests__/expose-internal-ids.test.d.ts +2 -0
  772. package/dist/vite/__tests__/expose-internal-ids.test.d.ts.map +1 -0
  773. package/dist/vite/__tests__/expose-internal-ids.test.js +647 -0
  774. package/dist/vite/__tests__/expose-internal-ids.test.js.map +1 -0
  775. package/dist/vite/__tests__/expose-router-id.test.d.ts +2 -0
  776. package/dist/vite/__tests__/expose-router-id.test.d.ts.map +1 -0
  777. package/dist/vite/__tests__/expose-router-id.test.js +39 -0
  778. package/dist/vite/__tests__/expose-router-id.test.js.map +1 -0
  779. package/dist/vite/ast-handler-extract.d.ts +49 -0
  780. package/dist/vite/ast-handler-extract.d.ts.map +1 -0
  781. package/dist/vite/ast-handler-extract.js +249 -0
  782. package/dist/vite/ast-handler-extract.js.map +1 -0
  783. package/dist/vite/expose-action-id.d.ts +19 -0
  784. package/dist/vite/expose-action-id.d.ts.map +1 -0
  785. package/dist/vite/expose-action-id.js +250 -0
  786. package/dist/vite/expose-action-id.js.map +1 -0
  787. package/dist/vite/expose-id-utils.d.ts +69 -0
  788. package/dist/vite/expose-id-utils.d.ts.map +1 -0
  789. package/dist/vite/expose-id-utils.js +289 -0
  790. package/dist/vite/expose-id-utils.js.map +1 -0
  791. package/dist/vite/expose-internal-ids.d.ts +22 -0
  792. package/dist/vite/expose-internal-ids.d.ts.map +1 -0
  793. package/dist/vite/expose-internal-ids.js +886 -0
  794. package/dist/vite/expose-internal-ids.js.map +1 -0
  795. package/dist/vite/index.d.ts +149 -0
  796. package/dist/vite/index.d.ts.map +1 -0
  797. package/dist/vite/index.js +3995 -2489
  798. package/dist/vite/index.js.map +1 -0
  799. package/dist/vite/package-resolution.d.ts +43 -0
  800. package/dist/vite/package-resolution.d.ts.map +1 -0
  801. package/dist/vite/package-resolution.js +112 -0
  802. package/dist/vite/package-resolution.js.map +1 -0
  803. package/dist/vite/virtual-entries.d.ts +25 -0
  804. package/dist/vite/virtual-entries.d.ts.map +1 -0
  805. package/{src/vite/virtual-entries.ts → dist/vite/virtual-entries.js} +12 -16
  806. package/dist/vite/virtual-entries.js.map +1 -0
  807. package/package.json +57 -52
  808. package/skills/breadcrumbs/SKILL.md +250 -0
  809. package/skills/cache-guide/SKILL.md +262 -0
  810. package/skills/caching/SKILL.md +85 -23
  811. package/skills/composability/SKILL.md +172 -0
  812. package/skills/debug-manifest/SKILL.md +12 -8
  813. package/skills/document-cache/SKILL.md +18 -16
  814. package/skills/fonts/SKILL.md +6 -4
  815. package/skills/hooks/SKILL.md +328 -70
  816. package/skills/host-router/SKILL.md +218 -0
  817. package/skills/intercept/SKILL.md +131 -8
  818. package/skills/layout/SKILL.md +100 -3
  819. package/skills/links/SKILL.md +62 -15
  820. package/skills/loader/SKILL.md +368 -42
  821. package/skills/middleware/SKILL.md +171 -34
  822. package/skills/mime-routes/SKILL.md +14 -10
  823. package/skills/parallel/SKILL.md +137 -1
  824. package/skills/prerender/SKILL.md +366 -28
  825. package/skills/rango/SKILL.md +85 -21
  826. package/skills/response-routes/SKILL.md +136 -83
  827. package/skills/route/SKILL.md +195 -21
  828. package/skills/router-setup/SKILL.md +123 -30
  829. package/skills/theme/SKILL.md +9 -8
  830. package/skills/typesafety/SKILL.md +240 -102
  831. package/skills/use-cache/SKILL.md +324 -0
  832. package/src/__internal.ts +102 -4
  833. package/src/bin/rango.ts +312 -15
  834. package/src/browser/action-coordinator.ts +97 -0
  835. package/src/browser/action-response-classifier.ts +99 -0
  836. package/src/browser/event-controller.ts +92 -64
  837. package/src/browser/history-state.ts +80 -0
  838. package/src/browser/intercept-utils.ts +52 -0
  839. package/src/browser/link-interceptor.ts +24 -4
  840. package/src/browser/logging.ts +11 -0
  841. package/src/browser/merge-segment-loaders.ts +20 -12
  842. package/src/browser/navigation-bridge.ts +266 -558
  843. package/src/browser/navigation-client.ts +132 -75
  844. package/src/browser/navigation-store.ts +33 -50
  845. package/src/browser/navigation-transaction.ts +297 -0
  846. package/src/browser/network-error-handler.ts +61 -0
  847. package/src/browser/partial-update.ts +292 -309
  848. package/src/browser/prefetch/cache.ts +206 -0
  849. package/src/browser/prefetch/fetch.ts +144 -0
  850. package/src/browser/prefetch/observer.ts +65 -0
  851. package/src/browser/prefetch/policy.ts +48 -0
  852. package/src/browser/prefetch/queue.ts +128 -0
  853. package/src/browser/rango-state.ts +112 -0
  854. package/src/browser/react/Link.tsx +190 -70
  855. package/src/browser/react/NavigationProvider.tsx +78 -11
  856. package/src/browser/react/context.ts +6 -0
  857. package/src/browser/react/filter-segment-order.ts +11 -0
  858. package/src/browser/react/index.ts +12 -12
  859. package/src/browser/react/location-state-shared.ts +95 -53
  860. package/src/browser/react/location-state.ts +60 -15
  861. package/src/browser/react/mount-context.ts +6 -1
  862. package/src/browser/react/nonce-context.ts +23 -0
  863. package/src/browser/react/shallow-equal.ts +27 -0
  864. package/src/browser/react/use-action.ts +29 -51
  865. package/src/browser/react/use-client-cache.ts +5 -3
  866. package/src/browser/react/use-handle.ts +29 -70
  867. package/src/browser/react/use-link-status.ts +6 -5
  868. package/src/browser/react/use-navigation.ts +22 -63
  869. package/src/browser/react/use-params.ts +65 -0
  870. package/src/browser/react/use-pathname.ts +47 -0
  871. package/src/browser/react/use-router.ts +63 -0
  872. package/src/browser/react/use-search-params.ts +56 -0
  873. package/src/browser/react/use-segments.ts +80 -97
  874. package/src/browser/response-adapter.ts +73 -0
  875. package/src/browser/rsc-router.tsx +188 -57
  876. package/src/browser/scroll-restoration.ts +117 -44
  877. package/src/browser/segment-reconciler.ts +221 -0
  878. package/src/browser/segment-structure-assert.ts +16 -0
  879. package/src/browser/server-action-bridge.ts +488 -606
  880. package/src/browser/shallow.ts +6 -1
  881. package/src/browser/types.ts +116 -47
  882. package/src/browser/validate-redirect-origin.ts +29 -0
  883. package/src/build/generate-manifest.ts +63 -21
  884. package/src/build/generate-route-types.ts +36 -1038
  885. package/src/build/index.ts +2 -5
  886. package/src/build/route-trie.ts +38 -12
  887. package/src/build/route-types/ast-helpers.ts +25 -0
  888. package/src/build/route-types/ast-route-extraction.ts +98 -0
  889. package/src/build/route-types/codegen.ts +102 -0
  890. package/src/build/route-types/include-resolution.ts +411 -0
  891. package/src/build/route-types/param-extraction.ts +48 -0
  892. package/src/build/route-types/per-module-writer.ts +128 -0
  893. package/src/build/route-types/router-processing.ts +479 -0
  894. package/src/build/route-types/scan-filter.ts +78 -0
  895. package/src/build/runtime-discovery.ts +231 -0
  896. package/src/cache/background-task.ts +34 -0
  897. package/src/cache/cache-key-utils.ts +44 -0
  898. package/src/cache/cache-policy.ts +125 -0
  899. package/src/cache/cache-runtime.ts +338 -0
  900. package/src/cache/cache-scope.ts +122 -303
  901. package/src/cache/cf/cf-cache-store.ts +571 -17
  902. package/src/cache/cf/index.ts +13 -3
  903. package/src/cache/document-cache.ts +116 -77
  904. package/src/cache/handle-capture.ts +81 -0
  905. package/src/cache/handle-snapshot.ts +41 -0
  906. package/src/cache/index.ts +1 -15
  907. package/src/cache/memory-segment-store.ts +191 -13
  908. package/src/cache/profile-registry.ts +73 -0
  909. package/src/cache/read-through-swr.ts +134 -0
  910. package/src/cache/segment-codec.ts +256 -0
  911. package/src/cache/taint.ts +98 -0
  912. package/src/cache/types.ts +72 -122
  913. package/src/client.rsc.tsx +3 -1
  914. package/src/client.tsx +84 -126
  915. package/src/component-utils.ts +4 -4
  916. package/src/components/DefaultDocument.tsx +5 -1
  917. package/src/context-var.ts +86 -0
  918. package/src/debug.ts +19 -9
  919. package/src/errors.ts +77 -7
  920. package/src/handle.ts +12 -7
  921. package/src/handles/MetaTags.tsx +73 -20
  922. package/src/handles/breadcrumbs.ts +66 -0
  923. package/src/handles/index.ts +1 -0
  924. package/src/handles/meta.ts +30 -13
  925. package/src/host/cookie-handler.ts +21 -15
  926. package/src/host/errors.ts +8 -8
  927. package/src/host/index.ts +4 -7
  928. package/src/host/pattern-matcher.ts +27 -27
  929. package/src/host/router.ts +61 -39
  930. package/src/host/testing.ts +8 -8
  931. package/src/host/types.ts +15 -7
  932. package/src/host/utils.ts +1 -1
  933. package/src/href-client.ts +65 -45
  934. package/src/index.rsc.ts +104 -40
  935. package/src/index.ts +122 -67
  936. package/src/internal-debug.ts +9 -3
  937. package/src/loader.rsc.ts +18 -93
  938. package/src/loader.ts +26 -9
  939. package/src/network-error-thrower.tsx +3 -1
  940. package/src/outlet-provider.tsx +45 -0
  941. package/src/prerender/param-hash.ts +4 -2
  942. package/src/prerender/store.ts +121 -17
  943. package/src/prerender.ts +325 -20
  944. package/src/reverse.ts +144 -124
  945. package/src/root-error-boundary.tsx +41 -29
  946. package/src/route-content-wrapper.tsx +7 -4
  947. package/src/route-definition/dsl-helpers.ts +959 -0
  948. package/src/route-definition/helper-factories.ts +200 -0
  949. package/src/route-definition/helpers-types.ts +430 -0
  950. package/src/route-definition/index.ts +52 -0
  951. package/src/route-definition/redirect.ts +93 -0
  952. package/src/route-definition.ts +1 -1450
  953. package/src/route-map-builder.ts +87 -133
  954. package/src/route-name.ts +53 -0
  955. package/src/route-types.ts +41 -6
  956. package/src/router/content-negotiation.ts +116 -0
  957. package/src/router/debug-manifest.ts +72 -0
  958. package/src/router/error-handling.ts +9 -9
  959. package/src/router/find-match.ts +160 -0
  960. package/src/router/handler-context.ts +324 -116
  961. package/src/router/intercept-resolution.ts +11 -4
  962. package/src/router/lazy-includes.ts +237 -0
  963. package/src/router/loader-resolution.ts +179 -133
  964. package/src/router/logging.ts +112 -6
  965. package/src/router/manifest.ts +58 -19
  966. package/src/router/match-api.ts +89 -88
  967. package/src/router/match-context.ts +4 -2
  968. package/src/router/match-handlers.ts +440 -0
  969. package/src/router/match-middleware/background-revalidation.ts +84 -89
  970. package/src/router/match-middleware/cache-lookup.ts +261 -48
  971. package/src/router/match-middleware/cache-store.ts +54 -13
  972. package/src/router/match-middleware/intercept-resolution.ts +45 -22
  973. package/src/router/match-middleware/segment-resolution.ts +20 -9
  974. package/src/router/match-pipelines.ts +10 -45
  975. package/src/router/match-result.ts +34 -17
  976. package/src/router/metrics.ts +235 -15
  977. package/src/router/middleware-cookies.ts +55 -0
  978. package/src/router/middleware-types.ts +222 -0
  979. package/src/router/middleware.ts +327 -369
  980. package/src/router/pattern-matching.ts +169 -31
  981. package/src/router/prerender-match.ts +402 -0
  982. package/src/router/preview-match.ts +170 -0
  983. package/src/router/revalidation.ts +105 -14
  984. package/src/router/router-context.ts +40 -21
  985. package/src/router/router-interfaces.ts +452 -0
  986. package/src/router/router-options.ts +592 -0
  987. package/src/router/router-registry.ts +24 -0
  988. package/src/router/segment-resolution/fresh.ts +656 -0
  989. package/src/router/segment-resolution/helpers.ts +263 -0
  990. package/src/router/segment-resolution/loader-cache.ts +199 -0
  991. package/src/router/segment-resolution/revalidation.ts +1277 -0
  992. package/src/router/segment-resolution/static-store.ts +67 -0
  993. package/src/router/segment-resolution.ts +21 -1354
  994. package/src/router/segment-wrappers.ts +291 -0
  995. package/src/router/telemetry-otel.ts +299 -0
  996. package/src/router/telemetry.ts +300 -0
  997. package/src/router/timeout.ts +148 -0
  998. package/src/router/trie-matching.ts +96 -29
  999. package/src/router/types.ts +15 -9
  1000. package/src/router.ts +642 -2366
  1001. package/src/rsc/handler-context.ts +45 -0
  1002. package/src/rsc/handler.ts +646 -1027
  1003. package/src/rsc/helpers.ts +140 -6
  1004. package/src/rsc/index.ts +0 -20
  1005. package/src/rsc/loader-fetch.ts +209 -0
  1006. package/src/rsc/manifest-init.ts +86 -0
  1007. package/src/rsc/nonce.ts +14 -0
  1008. package/src/rsc/origin-guard.ts +141 -0
  1009. package/src/rsc/progressive-enhancement.ts +379 -0
  1010. package/src/rsc/response-error.ts +37 -0
  1011. package/src/rsc/response-route-handler.ts +347 -0
  1012. package/src/rsc/rsc-rendering.ts +237 -0
  1013. package/src/rsc/runtime-warnings.ts +42 -0
  1014. package/src/rsc/server-action.ts +348 -0
  1015. package/src/rsc/ssr-setup.ts +128 -0
  1016. package/src/rsc/types.ts +38 -11
  1017. package/src/search-params.ts +66 -54
  1018. package/src/segment-system.tsx +165 -17
  1019. package/src/server/context.ts +237 -54
  1020. package/src/server/cookie-store.ts +190 -0
  1021. package/src/server/fetchable-loader-store.ts +11 -6
  1022. package/src/server/handle-store.ts +94 -15
  1023. package/src/server/loader-registry.ts +15 -56
  1024. package/src/server/request-context.ts +438 -71
  1025. package/src/server.ts +26 -164
  1026. package/src/ssr/index.tsx +101 -31
  1027. package/src/static-handler.ts +22 -4
  1028. package/src/theme/ThemeProvider.tsx +21 -15
  1029. package/src/theme/ThemeScript.tsx +5 -5
  1030. package/src/theme/constants.ts +5 -2
  1031. package/src/theme/index.ts +4 -14
  1032. package/src/theme/theme-context.ts +4 -30
  1033. package/src/theme/theme-script.ts +21 -18
  1034. package/src/types/boundaries.ts +158 -0
  1035. package/src/types/cache-types.ts +198 -0
  1036. package/src/types/error-types.ts +192 -0
  1037. package/src/types/global-namespace.ts +100 -0
  1038. package/src/types/handler-context.ts +687 -0
  1039. package/src/types/index.ts +88 -0
  1040. package/src/types/loader-types.ts +183 -0
  1041. package/src/types/route-config.ts +170 -0
  1042. package/src/types/route-entry.ts +109 -0
  1043. package/src/types/segments.ts +150 -0
  1044. package/src/types.ts +1 -1795
  1045. package/src/urls/include-helper.ts +197 -0
  1046. package/src/urls/index.ts +53 -0
  1047. package/src/urls/path-helper-types.ts +339 -0
  1048. package/src/urls/path-helper.ts +329 -0
  1049. package/src/urls/pattern-types.ts +95 -0
  1050. package/src/urls/response-types.ts +106 -0
  1051. package/src/urls/type-extraction.ts +372 -0
  1052. package/src/urls/urls-function.ts +98 -0
  1053. package/src/urls.ts +1 -1323
  1054. package/src/use-loader.tsx +85 -77
  1055. package/src/vite/discovery/bundle-postprocess.ts +184 -0
  1056. package/src/vite/discovery/discover-routers.ts +344 -0
  1057. package/src/vite/discovery/prerender-collection.ts +385 -0
  1058. package/src/vite/discovery/route-types-writer.ts +258 -0
  1059. package/src/vite/discovery/self-gen-tracking.ts +47 -0
  1060. package/src/vite/discovery/state.ts +108 -0
  1061. package/src/vite/discovery/virtual-module-codegen.ts +203 -0
  1062. package/src/vite/index.ts +11 -2259
  1063. package/src/vite/plugin-types.ts +48 -0
  1064. package/src/vite/plugins/cjs-to-esm.ts +93 -0
  1065. package/src/vite/plugins/client-ref-dedup.ts +115 -0
  1066. package/src/vite/plugins/client-ref-hashing.ts +105 -0
  1067. package/src/vite/{expose-action-id.ts → plugins/expose-action-id.ts} +72 -47
  1068. package/src/vite/{expose-id-utils.ts → plugins/expose-id-utils.ts} +8 -43
  1069. package/src/vite/plugins/expose-ids/export-analysis.ts +296 -0
  1070. package/src/vite/plugins/expose-ids/handler-transform.ts +179 -0
  1071. package/src/vite/plugins/expose-ids/loader-transform.ts +74 -0
  1072. package/src/vite/plugins/expose-ids/router-transform.ts +110 -0
  1073. package/src/vite/plugins/expose-ids/types.ts +45 -0
  1074. package/src/vite/plugins/expose-internal-ids.ts +569 -0
  1075. package/src/vite/plugins/refresh-cmd.ts +65 -0
  1076. package/src/vite/plugins/use-cache-transform.ts +323 -0
  1077. package/src/vite/plugins/version-injector.ts +83 -0
  1078. package/src/vite/plugins/version-plugin.ts +266 -0
  1079. package/src/vite/plugins/virtual-entries.ts +123 -0
  1080. package/src/vite/plugins/virtual-stub-plugin.ts +29 -0
  1081. package/src/vite/rango.ts +445 -0
  1082. package/src/vite/router-discovery.ts +777 -0
  1083. package/src/vite/{ast-handler-extract.ts → utils/ast-handler-extract.ts} +181 -9
  1084. package/src/vite/utils/banner.ts +36 -0
  1085. package/src/vite/utils/bundle-analysis.ts +137 -0
  1086. package/src/vite/utils/manifest-utils.ts +70 -0
  1087. package/src/vite/{package-resolution.ts → utils/package-resolution.ts} +25 -29
  1088. package/src/vite/utils/prerender-utils.ts +189 -0
  1089. package/src/vite/utils/shared-utils.ts +169 -0
  1090. package/CLAUDE.md +0 -43
  1091. package/src/browser/lru-cache.ts +0 -69
  1092. package/src/browser/request-controller.ts +0 -164
  1093. package/src/cache/memory-store.ts +0 -253
  1094. package/src/router.gen.ts +0 -6
  1095. package/src/static-handler.gen.ts +0 -5
  1096. package/src/urls.gen.ts +0 -8
  1097. package/src/vite/expose-internal-ids.ts +0 -1167
  1098. /package/src/vite/{version.d.ts → plugins/version.d.ts} +0 -0
@@ -1,5 +1,5 @@
1
1
  /// <reference types="@vitejs/plugin-rsc/types" />
2
- /// <reference path="../vite/version.d.ts" />
2
+ /// <reference path="../vite/plugins/version.d.ts" />
3
3
  /**
4
4
  * RSC Request Handler
5
5
  *
@@ -8,72 +8,80 @@
8
8
  */
9
9
 
10
10
  import { createElement } from "react";
11
- import { renderSegments } from "../segment-system.js";
12
- import { RouteNotFoundError, RouterError } from "../errors.js";
13
- import type { ResponseError } from "../urls.js";
14
- import { getLoaderLazy } from "../server/loader-registry.js";
15
- import {
16
- matchMiddleware,
17
- executeMiddleware,
18
- executeLoaderMiddleware,
19
- } from "../router/middleware.js";
11
+ import { RouteNotFoundError } from "../errors.js";
12
+ import { matchMiddleware, executeMiddleware } from "../router/middleware.js";
20
13
  import {
21
14
  runWithRequestContext,
22
15
  setRequestContextParams,
23
16
  requireRequestContext,
24
17
  createRequestContext,
25
- type ExecutionContext,
26
18
  } from "../server/request-context.js";
27
19
  import * as rscDeps from "@vitejs/plugin-rsc/rsc";
28
20
 
29
21
  import type {
30
22
  RscPayload,
31
- ReactFormState,
32
23
  CreateRSCHandlerOptions,
24
+ LoadSSRModule,
25
+ SSRModule,
33
26
  } from "./types.js";
34
- import { hasBodyContent, createResponseWithMergedHeaders } from "./helpers.js";
35
- import { generateNonce } from "./nonce.js";
27
+ import {
28
+ createResponseWithMergedHeaders,
29
+ finalizeResponse,
30
+ interceptRedirectForPartial,
31
+ buildRouteMiddlewareEntries,
32
+ } from "./helpers.js";
33
+ import {
34
+ handleResponseRoute,
35
+ type ResponseRouteMatch,
36
+ } from "./response-route-handler.js";
37
+ import { generateNonce, nonce as nonceToken } from "./nonce.js";
36
38
  import { VERSION } from "@rangojs/router:version";
37
39
  import type { ErrorPhase } from "../types.js";
40
+ import type { RouterRequestInput } from "../router/router-interfaces.js";
38
41
  import { invokeOnError } from "../router/error-handling.js";
39
42
  import {
40
- getGlobalRouteMap,
43
+ createReverseFunction,
44
+ stripInternalParams,
45
+ } from "../router/handler-context.js";
46
+ import { getRouterContext } from "../router/router-context.js";
47
+ import { resolveSink, safeEmit } from "../router/telemetry.js";
48
+ import { contextSet } from "../context-var.js";
49
+ import {
41
50
  hasCachedManifest,
42
- setCachedManifest,
43
51
  getRouteTrie,
44
- setRouteTrie,
45
52
  getPrecomputedEntries,
46
53
  waitForManifestReady,
47
54
  getRouterManifest,
48
55
  getRouterTrie,
49
- setRouterManifest,
50
- setRouterTrie,
51
56
  } from "../route-map-builder.js";
52
-
53
- /**
54
- * Build a ResponseError payload from a caught error.
55
- * RouterError messages are always exposed (developer-crafted).
56
- * Standard Error messages are hidden in production.
57
- */
58
- function createResponseErrorPayload(error: unknown, isDev: boolean): ResponseError {
59
- if (error instanceof RouterError) {
60
- return {
61
- message: error.message,
62
- code: error.code,
63
- ...(error.type ? { type: error.type } : {}),
64
- ...(isDev && error.stack ? { stack: error.stack } : {}),
65
- };
66
- }
67
- if (error instanceof Error) {
68
- return {
69
- message: isDev ? error.message : "Internal Server Error",
70
- ...(isDev && error.stack ? { stack: error.stack } : {}),
71
- };
72
- }
73
- return {
74
- message: isDev ? String(error) : "Internal Server Error",
75
- };
76
- }
57
+ import type { HandlerContext } from "./handler-context.js";
58
+ import { buildRouterTrieFromUrlpatterns } from "./manifest-init.js";
59
+ import { handleProgressiveEnhancement } from "./progressive-enhancement.js";
60
+ import {
61
+ executeServerAction,
62
+ revalidateAfterAction,
63
+ type ActionContinuation,
64
+ } from "./server-action.js";
65
+ import { handleLoaderFetch } from "./loader-fetch.js";
66
+ import { checkRequestOrigin, type OriginCheckPhase } from "./origin-guard.js";
67
+ import { handleRscRendering } from "./rsc-rendering.js";
68
+ import {
69
+ withTimeout,
70
+ RouterTimeoutError,
71
+ createDefaultTimeoutResponse,
72
+ type TimeoutPhase,
73
+ } from "../router/timeout.js";
74
+ import {
75
+ createMetricsStore,
76
+ appendMetric,
77
+ buildMetricsTiming,
78
+ } from "../router/metrics.js";
79
+ import {
80
+ startSSRSetup,
81
+ getSSRSetup,
82
+ mayNeedSSR,
83
+ SSR_SETUP_VAR,
84
+ } from "./ssr-setup.js";
77
85
 
78
86
  /**
79
87
  * Create an RSC request handler.
@@ -125,33 +133,179 @@ export function createRSCHandler<
125
133
  decodeFormState,
126
134
  } = deps;
127
135
 
128
- // Use provided loadSSRModule or default to vite RSC module loader
129
- const loadSSRModule =
136
+ // Use provided loadSSRModule or default to vite RSC module loader.
137
+ // In production the SSR module is stable across requests, so memoize
138
+ // the dynamic import to avoid repeated module resolution overhead.
139
+ // In dev mode Vite may hot-reload the module, so skip memoization.
140
+ const rawLoadSSRModule: LoadSSRModule =
130
141
  options.loadSSRModule ??
131
142
  (() => import.meta.viteRsc.loadModule("ssr", "index"));
143
+ let _ssrModulePromise: Promise<SSRModule> | undefined;
144
+ const loadSSRModule: LoadSSRModule =
145
+ process.env.NODE_ENV === "production"
146
+ ? () =>
147
+ (_ssrModulePromise ??= rawLoadSSRModule().catch((err) => {
148
+ _ssrModulePromise = undefined;
149
+ throw err;
150
+ }))
151
+ : rawLoadSSRModule;
132
152
 
133
153
  /**
134
- * Wrapper for invokeOnError that binds the router's onError callback.
135
- * Uses the shared utility from router/error-handling.ts for consistent behavior.
154
+ * Per-request error reporter that deduplicates via the ALS request context.
155
+ *
156
+ * Uses the same _reportedErrors WeakSet as the router layer so errors
157
+ * that propagate across layers are only reported once per request.
136
158
  */
137
159
  function callOnError(
138
160
  error: unknown,
139
161
  phase: ErrorPhase,
140
162
  context: Parameters<typeof invokeOnError<TEnv>>[3],
141
163
  ): void {
164
+ if (error != null && typeof error === "object") {
165
+ const reportedErrors = requireRequestContext()._reportedErrors;
166
+ if (reportedErrors.has(error)) return;
167
+ reportedErrors.add(error);
168
+ }
142
169
  invokeOnError(router.onError, error, phase, context, "RSC");
143
170
  }
144
171
 
145
- return async function handler(
172
+ function getRequiredRouteMap(): Record<string, string> {
173
+ const routeMap = getRouterManifest(router.id);
174
+ if (!routeMap) {
175
+ throw new Error(
176
+ `Route manifest for router "${router.id}" is not available.`,
177
+ );
178
+ }
179
+ return routeMap;
180
+ }
181
+
182
+ /**
183
+ * Handle a timeout by reporting the error, emitting telemetry,
184
+ * and returning either the custom onTimeout response or a default 504.
185
+ */
186
+ async function handleTimeoutResponse(
146
187
  request: Request,
147
- env: TEnv & { ctx?: ExecutionContext } = {} as TEnv & {
148
- ctx?: ExecutionContext;
188
+ env: TEnv,
189
+ url: URL,
190
+ phase: TimeoutPhase,
191
+ durationMs: number,
192
+ routeKey?: string,
193
+ actionId?: string,
194
+ ): Promise<Response> {
195
+ const timeoutError = new RouterTimeoutError(phase, durationMs);
196
+
197
+ callOnError(timeoutError, phase === "action" ? "action" : "handler", {
198
+ request,
199
+ url,
200
+ env,
201
+ routeKey,
202
+ actionId,
203
+ handledByBoundary: false,
204
+ metadata: { timeout: true, phase, durationMs },
205
+ });
206
+
207
+ try {
208
+ const routerCtx = getRouterContext();
209
+ if (routerCtx?.telemetry) {
210
+ safeEmit(resolveSink(routerCtx.telemetry), {
211
+ type: "request.timeout" as const,
212
+ timestamp: performance.now(),
213
+ requestId: routerCtx.requestId,
214
+ phase,
215
+ pathname: url.pathname,
216
+ routeKey,
217
+ actionId,
218
+ durationMs,
219
+ customHandler: !!router.onTimeout,
220
+ });
221
+ }
222
+ } catch {
223
+ // Router context may not be available
224
+ }
225
+
226
+ if (router.onTimeout) {
227
+ try {
228
+ return await router.onTimeout({
229
+ phase,
230
+ request,
231
+ url,
232
+ env,
233
+ routeKey,
234
+ actionId,
235
+ durationMs,
236
+ });
237
+ } catch (e) {
238
+ if (process.env.NODE_ENV !== "production") {
239
+ console.error("[RSC] onTimeout callback error:", e);
240
+ }
241
+ return createDefaultTimeoutResponse(phase);
242
+ }
243
+ }
244
+
245
+ return createDefaultTimeoutResponse(phase);
246
+ }
247
+
248
+ /**
249
+ * Build a 200 Flight response that carries a redirect URL and optional state.
250
+ * Used when a partial/action request results in a redirect -- fetch
251
+ * auto-follows 3xx so we send the redirect as payload metadata instead.
252
+ */
253
+ function createRedirectFlightResponse(
254
+ redirectUrl: string,
255
+ locationState?: Record<string, unknown>,
256
+ ): Response {
257
+ const redirectPayload: RscPayload = {
258
+ metadata: {
259
+ pathname: redirectUrl,
260
+ segments: [],
261
+ redirect: { url: redirectUrl },
262
+ ...(locationState && { locationState }),
263
+ },
264
+ };
265
+ const rscStream = renderToReadableStream<RscPayload>(redirectPayload);
266
+ return createResponseWithMergedHeaders(rscStream, {
267
+ status: 200,
268
+ headers: { "content-type": "text/x-component;charset=utf-8" },
269
+ });
270
+ }
271
+
272
+ // Bundle shared dependencies for extracted handler functions.
273
+ // callOnError reads from ALS so it's inherently per-request scoped.
274
+ const handlerCtx: HandlerContext<TEnv> = {
275
+ router,
276
+ version,
277
+ renderToReadableStream,
278
+ decodeReply,
279
+ createTemporaryReferenceSet,
280
+ loadServerAction,
281
+ decodeAction,
282
+ decodeFormState,
283
+ loadSSRModule,
284
+ callOnError,
285
+ getRequiredRouteMap,
286
+ createRedirectFlightResponse,
287
+ resolveStreamMode: async (request, env, url) => {
288
+ const resolver = router.ssr?.resolveStreaming;
289
+ if (!resolver) return "stream";
290
+ return resolver({ request, env, url });
149
291
  },
292
+ };
293
+
294
+ return async function handler(
295
+ request: Request,
296
+ input: RouterRequestInput<TEnv> = {},
150
297
  ): Promise<Response> {
151
298
  const handlerStart = performance.now();
299
+ // Create the metrics store at handler start so handler:total has startTime=0
300
+ // and all metrics are relative to the request entry point.
301
+ const earlyMetricsStore = router.debugPerformance
302
+ ? createMetricsStore(true, handlerStart)
303
+ : undefined;
304
+
305
+ const { env = {} as TEnv, vars: initialVars, ctx: executionCtx } = input;
152
306
 
153
307
  // Connection warmup: return 204 immediately before any processing
154
- if (router.warmupEnabled && request.method === "HEAD") {
308
+ if (router?.warmupEnabled && request.method === "HEAD") {
155
309
  const warmupUrl = new URL(request.url);
156
310
  if (warmupUrl.searchParams.has("_rsc_warmup")) {
157
311
  return new Response(null, { status: 204 });
@@ -175,13 +329,14 @@ export function createRSCHandler<
175
329
  const mwMatchDur = performance.now() - mwMatchStart;
176
330
 
177
331
  // Shared variables between middleware and route handlers
178
- // Initialize from env.Variables if provided (allows pre-seeding from worker entry)
179
- const variables: Record<string, any> = {
180
- ...((env as any)?.Variables ?? {}),
181
- };
332
+ // Initialize from input.vars if provided (allows pre-seeding from worker entry)
333
+ const variables: Record<string, any> = initialVars
334
+ ? { ...initialVars }
335
+ : {};
182
336
 
183
- // Store nonce in variables so middleware can access via ctx.get('nonce')
337
+ // Store nonce via ContextVar token and string key for backward compat
184
338
  if (nonce) {
339
+ contextSet(variables, nonceToken, nonce);
185
340
  variables.nonce = nonce;
186
341
  }
187
342
 
@@ -192,7 +347,9 @@ export function createRSCHandler<
192
347
  const cacheOption = options.cache ?? router.cache;
193
348
  if (cacheOption && !url.searchParams.has("__no_cache")) {
194
349
  const cacheConfig =
195
- typeof cacheOption === "function" ? cacheOption(env) : cacheOption;
350
+ typeof cacheOption === "function"
351
+ ? cacheOption(env, executionCtx)
352
+ : cacheOption;
196
353
 
197
354
  if (cacheConfig.enabled !== false) {
198
355
  cacheStore = cacheConfig.store;
@@ -223,56 +380,7 @@ export function createRSCHandler<
223
380
  // Cloudflare dev: generate manifest inline for this router.
224
381
  // Each router generates its own manifest independently so
225
382
  // multi-router setups (host routing) work correctly.
226
- const { generateManifest } =
227
- await import("../build/generate-manifest.js");
228
- const generated = generateManifest(router.urlpatterns);
229
- if (
230
- generated._routeAncestry &&
231
- Object.keys(generated._routeAncestry).length > 0
232
- ) {
233
- const { buildRouteTrie } = await import("../build/route-trie.js");
234
- // Map each route to its include() staticPrefix so the trie
235
- // returns the correct sp for lazy entry lookup in findMatch.
236
- const routeToStaticPrefix: Record<string, string> = {};
237
- for (const name of Object.keys(generated.routeManifest)) {
238
- routeToStaticPrefix[name] = "";
239
- }
240
- // Override with prefix from include() entries so the trie
241
- // returns the correct sp for lazy entry lookup in findMatch.
242
- // Walk recursively to include routes in nested includes.
243
- if (generated.prefixTree) {
244
- const visitPrefixNode = (node: any): void => {
245
- const sp = node.staticPrefix || "";
246
- for (const route of (node.routes || [])) {
247
- routeToStaticPrefix[route] = sp;
248
- }
249
- for (const child of Object.values(node.children || {})) {
250
- visitPrefixNode(child);
251
- }
252
- };
253
- for (const node of Object.values(generated.prefixTree)) {
254
- visitPrefixNode(node);
255
- }
256
- }
257
- const trie = buildRouteTrie(
258
- generated.routeManifest,
259
- generated._routeAncestry,
260
- routeToStaticPrefix,
261
- generated.routeTrailingSlash,
262
- generated.prerenderRoutes ? new Set(generated.prerenderRoutes) : undefined,
263
- generated.passthroughRoutes ? new Set(generated.passthroughRoutes) : undefined,
264
- generated.responseTypeRoutes,
265
- );
266
- setRouterTrie(router.id, trie);
267
- // Set global trie only if not already set by another router
268
- if (!getRouteTrie()) {
269
- setRouteTrie(trie);
270
- }
271
- }
272
- setRouterManifest(router.id, generated.routeManifest);
273
- // Merge into global manifest (needed for reverse/href across routers)
274
- const existing = hasCachedManifest() ? getGlobalRouteMap() : {};
275
- setCachedManifest({ ...existing, ...generated.routeManifest });
383
+ await buildRouterTrieFromUrlpatterns(router);
276
384
  }
277
385
  if (!getRouterManifest(router.id) && !hasCachedManifest()) {
278
386
  throw new Error(
@@ -280,10 +388,17 @@ export function createRSCHandler<
280
388
  );
281
389
  }
282
390
  }
283
- const manifestCacheDur = performance.now() - manifestCacheStart;
284
391
 
285
- // Note: Route map for useHref() is loaded lazily via getGlobalRouteMap()
286
- // This allows it to include all routes from lazy includes after manifest loading
392
+ // Rebuild the trie when the manifest exists but the per-router trie is
393
+ // missing. This happens in dev mode after HMR: the virtual module sets
394
+ // the manifest (from fresh gen files) but the trie is intentionally not
395
+ // injected to avoid stale discovery-time data. Without the trie, route
396
+ // matching falls back to regex iteration which does not handle wildcard
397
+ // priority correctly (catch-all patterns match before specific routes).
398
+ if (!getRouterTrie(router.id) && router.urlpatterns) {
399
+ await buildRouterTrieFromUrlpatterns(router);
400
+ }
401
+ const manifestCacheDur = performance.now() - manifestCacheStart;
287
402
 
288
403
  // Create unified request context with all methods
289
404
  // Includes: stub response, handle store, loader memoization, use(), cookies, headers, cache store
@@ -295,9 +410,27 @@ export function createRSCHandler<
295
410
  url,
296
411
  variables,
297
412
  cacheStore,
298
- executionContext: env.ctx,
413
+ cacheProfiles: router.cacheProfiles,
414
+ executionContext: executionCtx,
299
415
  themeConfig: router.themeConfig,
300
416
  });
417
+ if (earlyMetricsStore) {
418
+ requestContext._debugPerformance = true;
419
+ requestContext._metricsStore = earlyMetricsStore;
420
+ }
421
+ // Wire background error reporting so "use cache" and other subsystems
422
+ // can surface non-fatal errors through the router's onError callback.
423
+ requestContext._reportBackgroundError = (
424
+ error: unknown,
425
+ category: string,
426
+ ) => {
427
+ callOnError(error, "cache", {
428
+ request,
429
+ url,
430
+ metadata: { category },
431
+ });
432
+ };
433
+
301
434
  const ctxCreateDur = performance.now() - ctxCreateStart;
302
435
 
303
436
  // Accumulate handler-level timing for Server-Timing header
@@ -326,17 +459,78 @@ export function createRSCHandler<
326
459
  };
327
460
 
328
461
  // Execute middleware chain if any, otherwise call core handler directly
462
+ let response: Response;
329
463
  if (matchedMiddleware.length > 0) {
330
- return executeMiddleware(
464
+ const mwResponse = await executeMiddleware(
331
465
  matchedMiddleware,
332
466
  request,
333
467
  env,
334
468
  variables,
335
469
  coreHandler,
470
+ createReverseFunction(getRequiredRouteMap()),
471
+ );
472
+
473
+ if (
474
+ url.searchParams.has("_rsc_partial") ||
475
+ url.searchParams.has("_rsc_action")
476
+ ) {
477
+ const intercepted = interceptRedirectForPartial(
478
+ mwResponse,
479
+ createRedirectFlightResponse,
480
+ );
481
+ response = intercepted ?? finalizeResponse(mwResponse);
482
+ } else {
483
+ response = finalizeResponse(mwResponse);
484
+ }
485
+ } else {
486
+ response = await coreHandler();
487
+ }
488
+
489
+ // Finalize metrics after all middleware (including post-next work)
490
+ // has completed so :post spans are captured in the timeline.
491
+ // Handler timing parts are always emitted (even without debug metrics)
492
+ // so non-debug requests still get bootstrap Server-Timing entries.
493
+ const metricsFinStart = performance.now();
494
+ const handlerTimingArr: string[] = variables.__handlerTiming || [];
495
+ // Preserve any existing Server-Timing set by response routes or middleware
496
+ const existingTiming = response.headers.get("Server-Timing");
497
+ const timingParts = existingTiming
498
+ ? [existingTiming, ...handlerTimingArr]
499
+ : [...handlerTimingArr];
500
+
501
+ const metricsStore = requestContext._metricsStore;
502
+ if (metricsStore) {
503
+ appendMetric(
504
+ metricsStore,
505
+ "response-finalize",
506
+ metricsFinStart,
507
+ performance.now() - metricsFinStart,
508
+ );
509
+ // When the store was created at handler start (earlyMetricsStore),
510
+ // handler:total covers the full request. When ctx.debugPerformance()
511
+ // created the store mid-request, use its requestStart to avoid a
512
+ // negative startTime offset.
513
+ const totalStart = earlyMetricsStore
514
+ ? handlerStart
515
+ : metricsStore.requestStart;
516
+ appendMetric(
517
+ metricsStore,
518
+ "handler:total",
519
+ totalStart,
520
+ performance.now() - totalStart,
521
+ );
522
+ const metricsTiming = buildMetricsTiming(
523
+ request.method,
524
+ url.pathname,
525
+ metricsStore,
336
526
  );
527
+ if (metricsTiming) timingParts.push(metricsTiming);
337
528
  }
338
529
 
339
- return coreHandler();
530
+ const fullTiming = timingParts.join(", ");
531
+ if (fullTiming) response.headers.set("Server-Timing", fullTiming);
532
+
533
+ return response;
340
534
  });
341
535
  };
342
536
 
@@ -348,224 +542,314 @@ export function createRSCHandler<
348
542
  variables: Record<string, any>,
349
543
  nonce: string | undefined,
350
544
  ): Promise<Response> {
351
- // First, check for route-level middleware
352
545
  const previewStart = performance.now();
353
- const preview = await router.previewMatch(request, env);
546
+ const preview = await router.previewMatch(request, { env });
354
547
  const previewDur = performance.now() - previewStart;
355
548
  const handlerTiming: string[] = variables.__handlerTiming || [];
356
549
  handlerTiming.push(`handler-preview-match;dur=${previewDur.toFixed(2)}`);
357
550
  // Response route short-circuit: skip entire RSC pipeline
358
551
  if (preview?.responseType && preview.handler) {
359
- const isPartial = url.searchParams.has("_rsc_partial");
360
-
361
- // Partial requests (client-side navigation) to response routes
362
- // get X-RSC-Reload to trigger hard navigation in the browser
363
- if (isPartial) {
364
- const cleanUrl = new URL(url);
365
- cleanUrl.searchParams.delete("_rsc_partial");
366
- cleanUrl.searchParams.delete("_rsc_segments");
367
- cleanUrl.searchParams.delete("_rsc_v");
368
- cleanUrl.searchParams.delete("_rsc_stale");
369
- cleanUrl.searchParams.delete("_rsc_action");
370
- cleanUrl.searchParams.delete("_rsc_prev");
371
-
372
- return createResponseWithMergedHeaders(null, {
373
- status: 200,
374
- headers: {
375
- "X-RSC-Reload": cleanUrl.toString(),
376
- "content-type": "text/x-component;charset=utf-8",
377
- },
378
- });
552
+ const responseOutcome = await withTimeout(
553
+ handleResponseRoute(
554
+ handlerCtx,
555
+ preview as ResponseRouteMatch,
556
+ request,
557
+ env,
558
+ url,
559
+ variables,
560
+ ),
561
+ router.timeouts.renderStartMs,
562
+ "render-start",
563
+ );
564
+ if (responseOutcome.timedOut) {
565
+ return handleTimeoutResponse(
566
+ request,
567
+ env,
568
+ url,
569
+ "render-start",
570
+ responseOutcome.durationMs,
571
+ preview?.routeKey,
572
+ );
379
573
  }
574
+ return responseOutcome.result;
575
+ }
380
576
 
381
- // Build lightweight context for response handler
382
- const bindings = (env as any)?.Bindings ?? env;
383
- const reqCtx = requireRequestContext();
384
- const responseHandlerCtx = {
577
+ // Kick off SSR module loading + stream mode resolution in parallel with
578
+ // segment resolution. Placed after the response-route short-circuit so
579
+ // response/mime routes never pay for SSR work.
580
+ if (mayNeedSSR(request, url)) {
581
+ variables[SSR_SETUP_VAR] = startSSRSetup(
582
+ handlerCtx,
385
583
  request,
386
- params: preview.params || {},
387
- env: bindings,
388
- searchParams: url.searchParams,
584
+ env,
389
585
  url,
390
- pathname: url.pathname,
391
- href: (name: string, hrefParams?: Record<string, string>) => {
392
- if (name.startsWith("/")) {
393
- if (!hrefParams) return name;
394
- return name.replace(/:([^/]+)/g, (_, key) => {
395
- const value = hrefParams[key];
396
- if (value === undefined) throw new Error(`Missing param "${key}" for path "${name}"`);
397
- return encodeURIComponent(value);
398
- });
399
- }
400
- return name;
401
- },
402
- get: (key: string) => variables[key],
403
- header: (name: string, value: string) => reqCtx.header(name, value),
404
- setCookie: (name: string, value: string, options?: any) => reqCtx.setCookie(name, value, options),
405
- };
586
+ router.debugPerformance
587
+ ? () => requireRequestContext()._metricsStore
588
+ : undefined,
589
+ );
590
+ }
406
591
 
407
- // Call handler directly, wrapped by route middleware if present
408
- const callHandler = async () => {
409
- // JSON response routes: wrap in { data } / { error } envelope
410
- if (preview.responseType === "json") {
411
- const errorCtx = { request, url, env };
412
- try {
413
- const result = await (preview.handler as Function)(responseHandlerCtx);
414
- if (result instanceof Response) {
415
- const mergedHeaders: Record<string, string> = {};
416
- result.headers.forEach((value, key) => {
417
- mergedHeaders[key] = value;
418
- });
419
- return createResponseWithMergedHeaders(result.body, {
420
- status: result.status,
421
- headers: mergedHeaders,
422
- });
423
- }
424
- return createResponseWithMergedHeaders(
425
- JSON.stringify({ data: result }),
426
- { status: 200, headers: { "content-type": "application/json;charset=utf-8" } },
427
- );
428
- } catch (error) {
429
- callOnError(error, "handler", errorCtx);
430
- const isDev = process.env.NODE_ENV !== "production";
431
- const status = error instanceof RouterError ? error.status : 500;
432
- return createResponseWithMergedHeaders(
433
- JSON.stringify({ error: createResponseErrorPayload(error, isDev) }),
434
- { status, headers: { "content-type": "application/json;charset=utf-8" } },
435
- );
436
- }
437
- }
592
+ const routeReverse = createReverseFunction(getRequiredRouteMap());
438
593
 
439
- // Non-JSON response routes: catch errors and return plain Response
440
- const errorCtx = { request, url, env };
441
- try {
442
- const result = await (preview.handler as Function)(responseHandlerCtx);
594
+ const isAction =
595
+ request.headers.has("rsc-action") || url.searchParams.has("_rsc_action");
596
+ const isLoaderFetch = url.searchParams.has("_rsc_loader");
597
+ const actionId =
598
+ request.headers.get("rsc-action") || url.searchParams.get("_rsc_action");
443
599
 
444
- if (result instanceof Response) {
445
- // Handler returned a Response directly -- pass through
446
- const mergedHeaders: Record<string, string> = {};
447
- result.headers.forEach((value, key) => {
448
- mergedHeaders[key] = value;
449
- });
450
- return createResponseWithMergedHeaders(result.body, {
451
- status: result.status,
452
- headers: mergedHeaders,
600
+ // Origin guard: reject cross-origin actions, loader fetches, and
601
+ // PE form submissions before any execution. Regular page navigations
602
+ // (GET without _rsc_loader/_rsc_action) are not affected.
603
+ const originPhase: OriginCheckPhase | null = isAction
604
+ ? "action"
605
+ : isLoaderFetch
606
+ ? "loader"
607
+ : request.method === "POST"
608
+ ? "pe-form"
609
+ : null;
610
+ if (originPhase) {
611
+ const originResult = await checkRequestOrigin(
612
+ request,
613
+ url,
614
+ router.originCheck,
615
+ env,
616
+ router.id,
617
+ originPhase,
618
+ );
619
+ if (originResult) {
620
+ const originError = new Error(
621
+ `Origin check rejected: ${request.headers.get("origin") ?? "none"} vs ${request.headers.get("host") ?? "none"}`,
622
+ );
623
+ originError.name = "OriginCheckError";
624
+
625
+ callOnError(originError, "origin", {
626
+ request,
627
+ url,
628
+ env,
629
+ handledByBoundary: false,
630
+ metadata: {
631
+ phase: originPhase,
632
+ origin: request.headers.get("origin"),
633
+ host: request.headers.get("host"),
634
+ },
635
+ });
636
+
637
+ try {
638
+ const routerCtx = getRouterContext();
639
+ if (routerCtx?.telemetry) {
640
+ safeEmit(resolveSink(routerCtx.telemetry), {
641
+ type: "request.origin-rejected" as const,
642
+ timestamp: performance.now(),
643
+ requestId: routerCtx.requestId,
644
+ method: request.method,
645
+ pathname: url.pathname,
646
+ phase: originPhase,
647
+ origin: request.headers.get("origin"),
648
+ host: request.headers.get("host"),
453
649
  });
454
650
  }
651
+ } catch {
652
+ // Router context may not be available
653
+ }
455
654
 
456
- // Auto-wrap based on response type tag
457
- switch (preview.responseType) {
458
- case "text":
459
- return createResponseWithMergedHeaders(
460
- String(result),
461
- { status: 200, headers: { "content-type": "text/plain;charset=utf-8" } },
462
- );
463
- case "html":
464
- return createResponseWithMergedHeaders(
465
- String(result),
466
- { status: 200, headers: { "content-type": "text/html;charset=utf-8" } },
467
- );
468
- case "xml":
469
- return createResponseWithMergedHeaders(
470
- String(result),
471
- { status: 200, headers: { "content-type": "application/xml;charset=utf-8" } },
472
- );
473
- case "md":
474
- return createResponseWithMergedHeaders(
475
- String(result),
476
- { status: 200, headers: { "content-type": "text/markdown;charset=utf-8" } },
477
- );
478
- default:
479
- // image, stream, any -- must return Response
480
- throw new Error(
481
- `Response route handler for "${preview.responseType}" must return a Response object, got ${typeof result}`
482
- );
483
- }
484
- } catch (error) {
485
- callOnError(error, "handler", errorCtx);
486
- const isDev = process.env.NODE_ENV !== "production";
487
- const status = error instanceof RouterError ? error.status : 500;
488
- const message = error instanceof RouterError
489
- ? error.message
490
- : isDev && error instanceof Error
491
- ? error.message
492
- : "Internal Server Error";
493
- return createResponseWithMergedHeaders(message, {
494
- status,
495
- headers: { "content-type": "text/plain;charset=utf-8" },
655
+ return originResult;
656
+ }
657
+ }
658
+
659
+ // Get handle store from request context
660
+ const handleStore = requireRequestContext()._handleStore;
661
+
662
+ // Wire up error reporting for late streaming-handle failures
663
+ // (LateHandlePushError: handle pushed after stream completion).
664
+ // Without this, these errors are only caught by React's error boundary
665
+ // and never reach the router's onError callback or telemetry.
666
+ handleStore.onError = (error: Error) => {
667
+ const reqCtx = requireRequestContext();
668
+ callOnError(error, "handler", {
669
+ request,
670
+ url,
671
+ routeKey: reqCtx._routeName,
672
+ params: reqCtx.params as Record<string, string>,
673
+ handledByBoundary: true,
674
+ });
675
+ try {
676
+ const routerCtx = getRouterContext();
677
+ if (routerCtx?.telemetry) {
678
+ safeEmit(resolveSink(routerCtx.telemetry), {
679
+ type: "handler.error" as const,
680
+ timestamp: performance.now(),
681
+ requestId: routerCtx.requestId,
682
+ error,
683
+ handledByBoundary: true,
684
+ pathname: url.pathname,
685
+ routeKey: reqCtx._routeName,
686
+ params: reqCtx.params as Record<string, string>,
496
687
  });
497
688
  }
498
- };
689
+ } catch {
690
+ // Router context may not be available (e.g. prerender path)
691
+ }
692
+ };
499
693
 
500
- // Wrap callHandler to append Vary: Accept on content-negotiated responses
501
- const callHandlerWithVary = async () => {
502
- const response = await callHandler();
503
- if (preview.negotiated) {
504
- response.headers.append("Vary", "Accept");
505
- }
506
- return response;
507
- };
694
+ // Set route params early so all execution paths can access ctx.params.
695
+ if (preview?.params) {
696
+ setRequestContextParams(preview.params, preview.routeKey);
697
+ }
508
698
 
509
- if (preview.routeMiddleware && preview.routeMiddleware.length > 0) {
510
- const middlewareEntries = preview.routeMiddleware.map((mw) => ({
511
- entry: {
512
- pattern: null,
513
- regex: null,
514
- paramNames: [],
515
- handler: mw.handler,
516
- mountPrefix: null,
517
- },
518
- params: mw.params,
519
- }));
520
- return executeMiddleware(middlewareEntries, request, env, variables, callHandlerWithVary);
521
- }
699
+ // Progressive enhancement runs before the normal action/render paths.
700
+ // Route middleware wraps the PE re-render so handlers see the same
701
+ // context variables regardless of JS/no-JS transport.
702
+ const progressiveResult = await handleProgressiveEnhancement(
703
+ handlerCtx,
704
+ request,
705
+ env,
706
+ url,
707
+ isAction,
708
+ handleStore,
709
+ nonce,
710
+ {
711
+ routeMiddleware: preview?.routeMiddleware,
712
+ variables,
713
+ routeReverse,
714
+ },
715
+ );
716
+ if (progressiveResult) {
717
+ return progressiveResult;
718
+ }
522
719
 
523
- return callHandlerWithVary();
720
+ // --- Action execution: runs BEFORE route middleware ---
721
+ // Route middleware wraps rendering only. For actions, the action runs
722
+ // first in the global middleware context, then route middleware wraps
723
+ // the revalidation pass (identical to a normal render).
724
+ let actionContinuation: ActionContinuation | undefined;
725
+ if (isAction && actionId) {
726
+ try {
727
+ const actionOutcome = await withTimeout(
728
+ executeServerAction(
729
+ handlerCtx,
730
+ request,
731
+ env,
732
+ url,
733
+ actionId,
734
+ handleStore,
735
+ ),
736
+ router.timeouts.actionMs,
737
+ "action",
738
+ );
739
+ if (actionOutcome.timedOut) {
740
+ return handleTimeoutResponse(
741
+ request,
742
+ env,
743
+ url,
744
+ "action",
745
+ actionOutcome.durationMs,
746
+ preview?.routeKey,
747
+ actionId,
748
+ );
749
+ }
750
+ const result = actionOutcome.result;
751
+ // Response means redirect or error boundary — done.
752
+ if (result instanceof Response) return result;
753
+ actionContinuation = result;
754
+ } catch (error) {
755
+ callOnError(error, "action", {
756
+ request,
757
+ url,
758
+ env,
759
+ actionId,
760
+ handledByBoundary: false,
761
+ });
762
+ console.error(`[RSC] Action error:`, error);
763
+ throw error;
764
+ }
524
765
  }
525
766
 
526
- // Wrap RSC handler to append Vary: Accept on content-negotiated routes
527
- const rscHandler = async () => {
528
- const response = await coreRequestHandlerInner(request, env, url, variables, nonce);
767
+ // --- Rendering (action revalidation or navigation) ---
768
+ // Route middleware wraps this same code path for both cases.
769
+ const renderHandler = async () => {
770
+ const response = await coreRequestHandlerInner(
771
+ request,
772
+ env,
773
+ url,
774
+ variables,
775
+ nonce,
776
+ preview?.params,
777
+ preview?.routeKey,
778
+ handleStore,
779
+ actionContinuation,
780
+ );
529
781
  if (preview?.negotiated) {
530
782
  response.headers.append("Vary", "Accept");
531
783
  }
532
784
  return response;
533
785
  };
534
786
 
535
- if (preview?.routeMiddleware && preview.routeMiddleware.length > 0) {
536
- // Convert route middleware to app middleware format for execution
537
- const middlewareEntries = preview.routeMiddleware.map((mw) => ({
538
- entry: {
539
- pattern: null,
540
- regex: null,
541
- paramNames: [],
542
- handler: mw.handler,
543
- mountPrefix: null,
544
- },
545
- params: mw.params,
546
- }));
787
+ // Wrap the render path (with or without route middleware) in a
788
+ // renderStartMs timeout so slow renders are caught before output.
789
+ const executeRender = async (): Promise<Response> => {
790
+ if (preview?.routeMiddleware && preview.routeMiddleware.length > 0) {
791
+ const mwResponse = await executeMiddleware(
792
+ buildRouteMiddlewareEntries<TEnv>(preview.routeMiddleware),
793
+ request,
794
+ env,
795
+ variables,
796
+ renderHandler,
797
+ routeReverse,
798
+ );
547
799
 
548
- // Execute route middleware wrapping the actual request handling
549
- return executeMiddleware(middlewareEntries, request, env, variables, rscHandler);
550
- }
800
+ if (
801
+ url.searchParams.has("_rsc_partial") ||
802
+ url.searchParams.has("_rsc_action")
803
+ ) {
804
+ const intercepted = interceptRedirectForPartial(
805
+ mwResponse,
806
+ createRedirectFlightResponse,
807
+ );
808
+ if (intercepted) return intercepted;
809
+ }
551
810
 
552
- // No route middleware, proceed directly
553
- return rscHandler();
811
+ return finalizeResponse(mwResponse);
812
+ }
813
+
814
+ // No route middleware, proceed directly
815
+ return renderHandler();
816
+ };
817
+
818
+ const renderOutcome = await withTimeout(
819
+ executeRender(),
820
+ router.timeouts.renderStartMs,
821
+ "render-start",
822
+ );
823
+ if (renderOutcome.timedOut) {
824
+ return handleTimeoutResponse(
825
+ request,
826
+ env,
827
+ url,
828
+ "render-start",
829
+ renderOutcome.durationMs,
830
+ preview?.routeKey,
831
+ );
832
+ }
833
+ return renderOutcome.result;
554
834
  }
555
835
 
556
- // Inner request handler (actual RSC logic, wrapped by route middleware if any)
836
+ // Inner request handler: rendering logic wrapped by route middleware.
837
+ // Handles action revalidation (when actionContinuation is present),
838
+ // loader fetches, and regular RSC rendering.
557
839
  async function coreRequestHandlerInner(
558
840
  request: Request,
559
841
  env: TEnv,
560
842
  url: URL,
561
843
  variables: Record<string, any>,
562
844
  nonce: string | undefined,
845
+ routeParams?: Record<string, string>,
846
+ routeKey?: string,
847
+ handleStore?: ReturnType<typeof requireRequestContext>["_handleStore"],
848
+ actionContinuation?: ActionContinuation,
563
849
  ): Promise<Response> {
564
850
  const isPartial = url.searchParams.has("_rsc_partial");
565
851
  const isAction =
566
852
  request.headers.has("rsc-action") || url.searchParams.has("_rsc_action");
567
- const actionId =
568
- request.headers.get("rsc-action") || url.searchParams.get("_rsc_action");
569
853
 
570
854
  // Version mismatch detection - client may have stale code after HMR/deployment
571
855
  // If versions don't match, tell the client to reload
@@ -575,20 +859,23 @@ export function createRSCHandler<
575
859
  `[RSC] Version mismatch: client=${clientVersion}, server=${version}. Forcing reload.`,
576
860
  );
577
861
 
578
- // Clean URL by removing RSC params
579
- const cleanUrl = new URL(url);
580
- cleanUrl.searchParams.delete("_rsc_partial");
581
- cleanUrl.searchParams.delete("_rsc_segments");
582
- cleanUrl.searchParams.delete("_rsc_v");
583
- cleanUrl.searchParams.delete("_rsc_stale");
584
- cleanUrl.searchParams.delete("_rsc_action");
585
- cleanUrl.searchParams.delete("_rsc_prev");
586
-
587
- // For actions, reload current page (referer)
588
- // For navigation, load the target URL
589
- const reloadUrl = isAction
590
- ? request.headers.get("referer") || cleanUrl.toString()
591
- : cleanUrl.toString();
862
+ // For actions, reload current page (referer) if same origin.
863
+ // For navigation, load the target URL.
864
+ // Validate referer origin to prevent open redirect via crafted header.
865
+ let reloadUrl = stripInternalParams(url).toString();
866
+ if (isAction) {
867
+ const referer = request.headers.get("referer");
868
+ if (referer) {
869
+ try {
870
+ const refererUrl = new URL(referer);
871
+ if (refererUrl.origin === url.origin) {
872
+ reloadUrl = referer;
873
+ }
874
+ } catch {
875
+ // Malformed referer, fall back to cleanUrl
876
+ }
877
+ }
878
+ }
592
879
 
593
880
  // Return special response that tells client to reload
594
881
  return createResponseWithMergedHeaders(null, {
@@ -607,8 +894,9 @@ export function createRSCHandler<
607
894
  (isDev || router.allowDebugManifest)
608
895
  ) {
609
896
  const trie = getRouterTrie(router.id) ?? getRouteTrie();
610
- const routeManifest = getRouterManifest(router.id) ?? getGlobalRouteMap();
611
- const { extractAncestryFromTrie } = await import("../build/route-trie.js");
897
+ const routeManifest = getRequiredRouteMap();
898
+ const { extractAncestryFromTrie } =
899
+ await import("../build/route-trie.js");
612
900
  return new Response(
613
901
  JSON.stringify(
614
902
  {
@@ -627,30 +915,27 @@ export function createRSCHandler<
627
915
  );
628
916
  }
629
917
 
630
- // Get handle store from request context (created at start of request)
631
- const handleStore = requireRequestContext()._handleStore;
918
+ const store = handleStore ?? requireRequestContext()._handleStore;
632
919
 
633
920
  try {
634
- // ============================================================================
635
- // PROGRESSIVE ENHANCEMENT: No-JS Form Submissions
636
- // ============================================================================
637
- const progressiveResult = await handleProgressiveEnhancement(
638
- request,
639
- env,
640
- url,
641
- isAction,
642
- handleStore,
643
- nonce,
644
- );
645
- if (progressiveResult) {
646
- return progressiveResult;
921
+ // Route params were already set in coreRequestHandler, but set again
922
+ // for callers that enter coreRequestHandlerInner directly.
923
+ if (routeParams) {
924
+ setRequestContextParams(routeParams, routeKey);
647
925
  }
648
926
 
649
927
  // ============================================================================
650
- // SERVER ACTION EXECUTION (JavaScript-enabled client)
928
+ // ACTION REVALIDATION (action already executed, revalidate segments)
651
929
  // ============================================================================
652
- if (isAction && actionId) {
653
- return handleServerAction(request, env, url, actionId, handleStore);
930
+ if (actionContinuation) {
931
+ return await revalidateAfterAction(
932
+ handlerCtx,
933
+ request,
934
+ env,
935
+ url,
936
+ store,
937
+ actionContinuation,
938
+ );
654
939
  }
655
940
 
656
941
  // ============================================================================
@@ -658,7 +943,14 @@ export function createRSCHandler<
658
943
  // ============================================================================
659
944
  const isLoaderRequest = url.searchParams.has("_rsc_loader");
660
945
  if (isLoaderRequest) {
661
- return handleLoaderFetch(request, env, url, variables);
946
+ return handleLoaderFetch(
947
+ handlerCtx,
948
+ request,
949
+ env,
950
+ url,
951
+ variables,
952
+ routeParams,
953
+ );
662
954
  }
663
955
 
664
956
  // ============================================================================
@@ -666,11 +958,12 @@ export function createRSCHandler<
666
958
  // ============================================================================
667
959
  // Note: Must use "return await" for try/catch to catch async rejections
668
960
  return await handleRscRendering(
961
+ handlerCtx,
669
962
  request,
670
963
  env,
671
964
  url,
672
965
  isPartial,
673
- handleStore,
966
+ store,
674
967
  nonce,
675
968
  );
676
969
  } catch (error) {
@@ -684,23 +977,25 @@ export function createRSCHandler<
684
977
  if (isPartial && error.status === 200) {
685
978
  console.warn(
686
979
  `[RSC] Route handler at ${url.pathname} returned a Response during client-side navigation. ` +
687
- `Falling back to hard navigation. Use data-external on the <Link> to avoid the extra round-trip.`,
980
+ `Falling back to hard navigation. Use data-external on the <Link> to avoid the extra round-trip.`,
688
981
  );
689
- const cleanUrl = new URL(url);
690
- cleanUrl.searchParams.delete("_rsc_partial");
691
- cleanUrl.searchParams.delete("_rsc_segments");
692
- cleanUrl.searchParams.delete("_rsc_v");
693
- cleanUrl.searchParams.delete("_rsc_stale");
694
- cleanUrl.searchParams.delete("_rsc_action");
695
- cleanUrl.searchParams.delete("_rsc_prev");
696
982
  return createResponseWithMergedHeaders(null, {
697
983
  status: 200,
698
984
  headers: {
699
- "X-RSC-Reload": cleanUrl.toString(),
985
+ "X-RSC-Reload": stripInternalParams(url).toString(),
700
986
  "content-type": "text/x-component;charset=utf-8",
701
987
  },
702
988
  });
703
989
  }
990
+
991
+ if (isPartial) {
992
+ const intercepted = interceptRedirectForPartial(
993
+ error,
994
+ createRedirectFlightResponse,
995
+ );
996
+ if (intercepted) return intercepted;
997
+ }
998
+
704
999
  return error;
705
1000
  }
706
1001
 
@@ -734,21 +1029,15 @@ export function createRSCHandler<
734
1029
  params: {},
735
1030
  };
736
1031
 
737
- // Render with rootLayout to maintain app shell
738
- const root = await renderSegments([notFoundSegment], {
739
- rootLayout: router.rootLayout,
740
- // No routeName for not-found routes
741
- });
742
-
743
1032
  const payload: RscPayload = {
744
- root,
745
1033
  metadata: {
746
1034
  pathname: url.pathname,
747
1035
  segments: [notFoundSegment],
748
1036
  matched: [],
749
1037
  diff: [],
750
1038
  isPartial: false,
751
- handles: handleStore.stream(),
1039
+ rootLayout: router.rootLayout,
1040
+ handles: store.stream(),
752
1041
  version,
753
1042
  themeConfig: router.themeConfig,
754
1043
  warmupEnabled: router.warmupEnabled,
@@ -759,8 +1048,10 @@ export function createRSCHandler<
759
1048
 
760
1049
  const rscStream = renderToReadableStream(payload);
761
1050
 
762
- // Determine if this is an RSC request or HTML request
1051
+ // Determine if this is an RSC request or HTML request.
1052
+ // Partial requests are always RSC (see main isRscRequest comment).
763
1053
  const isRscRequest =
1054
+ isPartial ||
764
1055
  (!request.headers.get("accept")?.includes("text/html") &&
765
1056
  !url.searchParams.has("__html")) ||
766
1057
  url.searchParams.has("__rsc");
@@ -772,9 +1063,18 @@ export function createRSCHandler<
772
1063
  });
773
1064
  }
774
1065
 
775
- // Delegate to SSR for HTML response
776
- const ssrModule = await loadSSRModule();
777
- const htmlStream = await ssrModule.renderHTML(rscStream, { nonce });
1066
+ // Delegate to SSR for HTML response (reuse early setup if available)
1067
+ const [ssrModule, streamMode] = await getSSRSetup(
1068
+ handlerCtx,
1069
+ request,
1070
+ env,
1071
+ url,
1072
+ requireRequestContext()._metricsStore,
1073
+ );
1074
+ const htmlStream = await ssrModule.renderHTML(rscStream, {
1075
+ nonce,
1076
+ streamMode,
1077
+ });
778
1078
 
779
1079
  return createResponseWithMergedHeaders(htmlStream, {
780
1080
  status: 404,
@@ -793,685 +1093,4 @@ export function createRSCHandler<
793
1093
  throw error;
794
1094
  }
795
1095
  }
796
-
797
- // ============================================================================
798
- // PROGRESSIVE ENHANCEMENT HANDLER
799
- // When JavaScript is disabled, React renders forms with hidden fields
800
- // ($ACTION_REF_*, $ACTION_KEY) containing the action reference.
801
- // We detect these and return HTML instead of RSC stream.
802
- // ============================================================================
803
- async function handleProgressiveEnhancement(
804
- request: Request,
805
- env: TEnv,
806
- url: URL,
807
- isAction: boolean,
808
- handleStore: ReturnType<typeof requireRequestContext>["_handleStore"],
809
- nonce: string | undefined,
810
- ): Promise<Response | null> {
811
- const contentType = request.headers.get("content-type") || "";
812
- const isFormSubmission =
813
- contentType.includes("multipart/form-data") ||
814
- contentType.includes("application/x-www-form-urlencoded");
815
-
816
- if (request.method !== "POST" || isAction || !isFormSubmission) {
817
- return null;
818
- }
819
-
820
- // Clone the request to read FormData without consuming it
821
- const formData = await request.clone().formData();
822
-
823
- // Look for React's progressive enhancement hidden fields
824
- let isDirectAction = false;
825
- let isUseActionState = false;
826
- let directActionId: string | null = null;
827
-
828
- formData.forEach((_value, key) => {
829
- if (key.startsWith("$ACTION_ID_")) {
830
- isDirectAction = true;
831
- directActionId = key.slice("$ACTION_ID_".length);
832
- } else if (key.startsWith("$ACTION_REF_")) {
833
- isUseActionState = true;
834
- }
835
- });
836
-
837
- if (!isDirectAction && !isUseActionState) {
838
- return null;
839
- }
840
-
841
- // Execute action and return HTML
842
- let actionResult: unknown = undefined;
843
- let reactFormState: ReactFormState | null = null;
844
-
845
- if (isUseActionState) {
846
- try {
847
- const boundAction = await decodeAction(formData);
848
- actionResult = await boundAction();
849
- } catch (error) {
850
- callOnError(error, "action", {
851
- request,
852
- url,
853
- env,
854
- handledByBoundary: false,
855
- });
856
- console.error("[RSC] Progressive enhancement action error:", error);
857
- }
858
- } else if (isDirectAction && directActionId) {
859
- const temporaryReferences = createTemporaryReferenceSet();
860
-
861
- let args: unknown[] = [];
862
- try {
863
- args = await decodeReply(formData, { temporaryReferences });
864
- } catch {
865
- args = [formData];
866
- }
867
-
868
- try {
869
- const loadedAction = await loadServerAction(directActionId);
870
- actionResult = await loadedAction.apply(null, args);
871
- } catch (error) {
872
- callOnError(error, "action", {
873
- request,
874
- url,
875
- env,
876
- actionId: directActionId,
877
- handledByBoundary: false,
878
- });
879
- console.error("[RSC] Progressive enhancement action error:", error);
880
- }
881
- }
882
-
883
- // Decode form state for useActionState progressive enhancement
884
- try {
885
- reactFormState = await decodeFormState(actionResult, formData);
886
- } catch (error) {
887
- callOnError(error, "action", {
888
- request,
889
- url,
890
- env,
891
- handledByBoundary: false,
892
- });
893
- console.error("[RSC] Failed to decode form state:", error);
894
- }
895
-
896
- // Re-render the page and return HTML
897
- const renderRequest = new Request(url.toString(), {
898
- method: "GET",
899
- headers: new Headers({ accept: "text/html" }),
900
- });
901
-
902
- const match = await router.match(renderRequest, env);
903
-
904
- if (match.redirect) {
905
- return new Response(null, {
906
- status: 308,
907
- headers: { Location: match.redirect },
908
- });
909
- }
910
-
911
- const root = renderSegments(match.segments, {
912
- rootLayout: router.rootLayout,
913
- });
914
-
915
- const payload: RscPayload = {
916
- root,
917
- metadata: {
918
- pathname: url.pathname,
919
- segments: match.segments,
920
- matched: match.matched,
921
- diff: match.diff,
922
- isPartial: false,
923
- rootLayout: router.rootLayout,
924
- handles: handleStore.stream(),
925
- version,
926
- themeConfig: router.themeConfig,
927
- warmupEnabled: router.warmupEnabled,
928
- initialTheme: requireRequestContext().theme,
929
- },
930
- formState: actionResult,
931
- };
932
-
933
- const rscStream = renderToReadableStream<RscPayload>(payload);
934
- const ssrModule = await loadSSRModule();
935
- const htmlStream = await ssrModule.renderHTML(rscStream, {
936
- formState: reactFormState,
937
- nonce,
938
- });
939
-
940
- return new Response(htmlStream, {
941
- headers: { "content-type": "text/html;charset=utf-8" },
942
- });
943
- }
944
-
945
- // ============================================================================
946
- // SERVER ACTION HANDLER
947
- // ============================================================================
948
- async function handleServerAction(
949
- request: Request,
950
- env: TEnv,
951
- url: URL,
952
- actionId: string,
953
- handleStore: ReturnType<typeof requireRequestContext>["_handleStore"],
954
- ): Promise<Response> {
955
- const temporaryReferences = createTemporaryReferenceSet();
956
-
957
- // Decode action arguments from request body
958
- const contentType = request.headers.get("content-type") || "";
959
- let args: unknown[] = [];
960
- let actionFormData: FormData | undefined;
961
-
962
- try {
963
- const body = contentType.includes("multipart/form-data")
964
- ? await request.formData()
965
- : await request.text();
966
-
967
- if (body instanceof FormData) {
968
- actionFormData = body;
969
- }
970
-
971
- if (hasBodyContent(body)) {
972
- args = await decodeReply(body, { temporaryReferences });
973
- }
974
- } catch (error) {
975
- callOnError(error, "action", {
976
- request,
977
- url,
978
- env,
979
- actionId,
980
- handledByBoundary: false,
981
- });
982
- throw new Error(`Failed to decode action arguments: ${error}`, {
983
- cause: error,
984
- });
985
- }
986
-
987
- // Execute the server action
988
- let returnValue: { ok: boolean; data: unknown };
989
- let actionStatus = 200;
990
- let loadedAction: Function | undefined;
991
-
992
- try {
993
- loadedAction = await loadServerAction(actionId);
994
- const data = await loadedAction!.apply(null, args);
995
- returnValue = { ok: true, data };
996
- } catch (error) {
997
- returnValue = { ok: false, data: error };
998
- actionStatus = 500;
999
-
1000
- // Try to render error boundary
1001
- const errorResult = await router.matchError(request, env, error, "route");
1002
-
1003
- // Report the action error (handledByBoundary indicates if error boundary will render)
1004
- callOnError(error, "action", {
1005
- request,
1006
- url,
1007
- env,
1008
- actionId,
1009
- handledByBoundary: !!errorResult,
1010
- });
1011
-
1012
- if (errorResult) {
1013
- setRequestContextParams(errorResult.params);
1014
-
1015
- const payload: RscPayload = {
1016
- root: null,
1017
- metadata: {
1018
- pathname: url.pathname,
1019
- segments: errorResult.segments,
1020
- isPartial: true,
1021
- matched: errorResult.matched,
1022
- diff: errorResult.diff,
1023
- isError: true,
1024
- handles: handleStore.stream(),
1025
- version,
1026
- },
1027
- returnValue,
1028
- };
1029
-
1030
- const rscStream = renderToReadableStream<RscPayload>(payload, {
1031
- temporaryReferences,
1032
- });
1033
-
1034
- return createResponseWithMergedHeaders(rscStream, {
1035
- status: actionStatus,
1036
- headers: { "content-type": "text/x-component;charset=utf-8" },
1037
- });
1038
- }
1039
- }
1040
-
1041
- // Revalidate after action
1042
- const resolvedActionId =
1043
- (loadedAction as { $id?: string; $$id?: string } | undefined)?.$id ??
1044
- (loadedAction as { $$id?: string } | undefined)?.$$id ??
1045
- actionId;
1046
- const actionContext = {
1047
- actionId: resolvedActionId,
1048
- actionUrl: new URL(request.url),
1049
- actionResult: returnValue.data,
1050
- formData: actionFormData,
1051
- };
1052
-
1053
- const matchResult = await router.matchPartial(request, env, actionContext);
1054
-
1055
- if (!matchResult) {
1056
- // Fall back to full render
1057
- const fullMatch = await router.match(request, env);
1058
- setRequestContextParams(fullMatch.params);
1059
-
1060
- if (fullMatch.redirect) {
1061
- return createResponseWithMergedHeaders(null, {
1062
- status: 308,
1063
- headers: { Location: fullMatch.redirect },
1064
- });
1065
- }
1066
-
1067
- const renderStart = performance.now();
1068
- const root = renderSegments(fullMatch.segments, {
1069
- rootLayout: router.rootLayout,
1070
- isAction: true,
1071
- });
1072
- const renderDuration = performance.now() - renderStart;
1073
- const serverTiming = fullMatch.serverTiming
1074
- ? `${fullMatch.serverTiming}, rendering;dur=${renderDuration.toFixed(2)}`
1075
- : `rendering;dur=${renderDuration.toFixed(2)}`;
1076
-
1077
- const payload: RscPayload = {
1078
- root,
1079
- metadata: {
1080
- pathname: url.pathname,
1081
- segments: fullMatch.segments,
1082
- matched: fullMatch.matched,
1083
- diff: fullMatch.diff,
1084
- handles: handleStore.stream(),
1085
- version,
1086
- },
1087
- returnValue,
1088
- };
1089
-
1090
- const rscStream = renderToReadableStream<RscPayload>(payload, {
1091
- temporaryReferences,
1092
- });
1093
-
1094
- const headers: Record<string, string> = {
1095
- "content-type": "text/x-component;charset=utf-8",
1096
- };
1097
- if (serverTiming) {
1098
- headers["Server-Timing"] = serverTiming;
1099
- }
1100
-
1101
- return createResponseWithMergedHeaders(rscStream, {
1102
- status: actionStatus,
1103
- headers,
1104
- });
1105
- }
1106
-
1107
- // Return updated segments
1108
- setRequestContextParams(matchResult.params);
1109
-
1110
- const renderStart = performance.now();
1111
-
1112
- const renderDuration = performance.now() - renderStart;
1113
- const serverTiming = matchResult.serverTiming
1114
- ? `${matchResult.serverTiming}, rendering;dur=${renderDuration.toFixed(2)}`
1115
- : `rendering;dur=${renderDuration.toFixed(2)}`;
1116
-
1117
- const payload: RscPayload = {
1118
- root: null,
1119
- metadata: {
1120
- pathname: url.pathname,
1121
- segments: matchResult.segments,
1122
- isPartial: true,
1123
- matched: matchResult.matched,
1124
- diff: matchResult.diff,
1125
- slots: matchResult.slots,
1126
- handles: handleStore.stream(),
1127
- version,
1128
- },
1129
- returnValue,
1130
- };
1131
-
1132
- const rscStream = renderToReadableStream<RscPayload>(payload, {
1133
- temporaryReferences,
1134
- });
1135
-
1136
- const actionHeaders: Record<string, string> = {
1137
- "content-type": "text/x-component;charset=utf-8",
1138
- };
1139
- if (serverTiming) {
1140
- actionHeaders["Server-Timing"] = serverTiming;
1141
- }
1142
-
1143
- return createResponseWithMergedHeaders(rscStream, {
1144
- status: actionStatus,
1145
- headers: actionHeaders,
1146
- });
1147
- }
1148
-
1149
- // ============================================================================
1150
- // LOADER FETCH HANDLER
1151
- // Supports GET (params in query string) and POST/PUT/PATCH/DELETE (JSON body)
1152
- // ============================================================================
1153
- async function handleLoaderFetch(
1154
- request: Request,
1155
- env: TEnv,
1156
- url: URL,
1157
- variables: Record<string, any>,
1158
- ): Promise<Response> {
1159
- const loaderId = url.searchParams.get("_rsc_loader");
1160
-
1161
- if (!loaderId) {
1162
- return createResponseWithMergedHeaders("Missing _rsc_loader parameter", {
1163
- status: 400,
1164
- });
1165
- }
1166
-
1167
- // Look up loader lazily
1168
- const registeredLoader = await getLoaderLazy(loaderId);
1169
- if (!registeredLoader) {
1170
- return createResponseWithMergedHeaders(
1171
- `Loader "${loaderId}" not found in registry`,
1172
- { status: 404 },
1173
- );
1174
- }
1175
-
1176
- // Parse params and body based on request method
1177
- let loaderParams: Record<string, string> = {};
1178
- let loaderBody: unknown = undefined;
1179
- const isBodyMethod = request.method !== "GET" && request.method !== "HEAD";
1180
-
1181
- if (isBodyMethod) {
1182
- try {
1183
- const contentType = request.headers.get("content-type") || "";
1184
- if (contentType.includes("application/json")) {
1185
- const jsonBody = (await request.json()) as {
1186
- params?: Record<string, string>;
1187
- body?: unknown;
1188
- };
1189
- loaderParams = jsonBody.params ?? {};
1190
- loaderBody = jsonBody.body;
1191
- }
1192
- } catch {
1193
- return createResponseWithMergedHeaders("Invalid JSON body", {
1194
- status: 400,
1195
- });
1196
- }
1197
- } else {
1198
- const loaderParamsJson = url.searchParams.get("_rsc_loader_params");
1199
- if (loaderParamsJson) {
1200
- try {
1201
- loaderParams = JSON.parse(loaderParamsJson);
1202
- } catch {
1203
- return createResponseWithMergedHeaders(
1204
- "Invalid _rsc_loader_params JSON",
1205
- { status: 400 },
1206
- );
1207
- }
1208
- }
1209
- }
1210
-
1211
- // Execute the loader with middleware
1212
- try {
1213
- const { fn, middleware } = registeredLoader;
1214
-
1215
- return await executeLoaderMiddleware(
1216
- middleware,
1217
- request,
1218
- env,
1219
- loaderParams,
1220
- variables,
1221
- async () => {
1222
- const ctx = requireRequestContext();
1223
- const loaderCtx: any = {
1224
- ...ctx,
1225
- params: loaderParams,
1226
- body: loaderBody,
1227
- };
1228
-
1229
- const result = await fn(loaderCtx);
1230
-
1231
- interface LoaderPayload {
1232
- loaderResult: unknown;
1233
- }
1234
- const loaderPayload: LoaderPayload = { loaderResult: result };
1235
- const rscStream =
1236
- renderToReadableStream<LoaderPayload>(loaderPayload);
1237
-
1238
- return createResponseWithMergedHeaders(rscStream, {
1239
- headers: { "content-type": "text/x-component;charset=utf-8" },
1240
- });
1241
- },
1242
- );
1243
- } catch (error) {
1244
- const err = error instanceof Error ? error : new Error(String(error));
1245
- const isDev = process.env.NODE_ENV !== "production";
1246
-
1247
- console.error("[RSC] Loader error:", error);
1248
-
1249
- callOnError(error, "loader", {
1250
- request,
1251
- url,
1252
- env,
1253
- loaderName: loaderId,
1254
- handledByBoundary: false,
1255
- });
1256
-
1257
- const errorPayload = {
1258
- loaderResult: null,
1259
- loaderError: {
1260
- message: isDev ? err.message : "An error occurred",
1261
- name: err.name,
1262
- },
1263
- };
1264
- const rscStream = renderToReadableStream(errorPayload);
1265
-
1266
- return createResponseWithMergedHeaders(rscStream, {
1267
- status: 500,
1268
- headers: { "content-type": "text/x-component;charset=utf-8" },
1269
- });
1270
- }
1271
- }
1272
-
1273
- // ============================================================================
1274
- // RSC RENDERING HANDLER (Navigation)
1275
- // ============================================================================
1276
- async function handleRscRendering(
1277
- request: Request,
1278
- env: TEnv,
1279
- url: URL,
1280
- isPartial: boolean,
1281
- handleStore: ReturnType<typeof requireRequestContext>["_handleStore"],
1282
- nonce: string | undefined,
1283
- ): Promise<Response> {
1284
- // Retrieve handler-level timing from variables
1285
- const reqCtx = requireRequestContext();
1286
- const handlerTimingArr: string[] = reqCtx.var.__handlerTiming || [];
1287
- const handlerStart: number = reqCtx.var.__handlerStart || 0;
1288
-
1289
- let payload: RscPayload;
1290
- let serverTiming: string | undefined;
1291
-
1292
- if (isPartial) {
1293
- // Partial render (navigation)
1294
- const result = await router.matchPartial(request, env);
1295
-
1296
- if (!result) {
1297
- // Fall back to full render
1298
- const match = await router.match(request, env);
1299
- setRequestContextParams(match.params);
1300
-
1301
- if (match.redirect) {
1302
- return createResponseWithMergedHeaders(null, {
1303
- status: 308,
1304
- headers: { Location: match.redirect },
1305
- });
1306
- }
1307
-
1308
- const renderStart = performance.now();
1309
- const root = renderSegments(match.segments, {
1310
- rootLayout: router.rootLayout,
1311
- });
1312
- const renderDuration = performance.now() - renderStart;
1313
- serverTiming = match.serverTiming
1314
- ? `${match.serverTiming}, rendering;dur=${renderDuration.toFixed(2)}`
1315
- : `rendering;dur=${renderDuration.toFixed(2)}`;
1316
-
1317
- payload = {
1318
- root,
1319
- metadata: {
1320
- pathname: url.pathname,
1321
- segments: match.segments,
1322
- matched: match.matched,
1323
- diff: match.diff,
1324
- isPartial: false,
1325
- handles: handleStore.stream(),
1326
- version,
1327
- themeConfig: router.themeConfig,
1328
- initialTheme: reqCtx.theme,
1329
- },
1330
- };
1331
- } else {
1332
- setRequestContextParams(result.params);
1333
- serverTiming = result.serverTiming;
1334
-
1335
- payload = {
1336
- root: null,
1337
- metadata: {
1338
- pathname: url.pathname,
1339
- segments: result.segments,
1340
- matched: result.matched,
1341
- diff: result.diff,
1342
- isPartial: true,
1343
- slots: result.slots,
1344
- handles: handleStore.stream(),
1345
- version,
1346
- },
1347
- };
1348
- }
1349
- } else {
1350
- // Full render (initial page load)
1351
- const match = await router.match(request, env);
1352
- setRequestContextParams(match.params);
1353
-
1354
- if (match.redirect) {
1355
- return createResponseWithMergedHeaders(null, {
1356
- status: 308,
1357
- headers: { Location: match.redirect },
1358
- });
1359
- }
1360
-
1361
- // Caching is now handled in router.match() via cache provider in request context
1362
- // match.segments already contains cached or fresh segments as appropriate
1363
-
1364
- if (url.searchParams.has("__prerender_collect")) {
1365
- // Build-time prerender collection: serialize segments and handle data
1366
- // to JSON for storage as build artifacts. At runtime the worker
1367
- // deserializes these and feeds them through the normal segment pipeline.
1368
- const nonLoaderSegments = match.segments.filter((s) => s.type !== "loader");
1369
- await handleStore.settled;
1370
- const { serializeSegments } = await import("../cache/cache-scope.js");
1371
- const serializedSegments = await serializeSegments(nonLoaderSegments);
1372
- const handles: Record<string, Record<string, unknown[]>> = {};
1373
- for (const seg of nonLoaderSegments) {
1374
- const segHandles = handleStore.getDataForSegment(seg.id);
1375
- if (Object.keys(segHandles).length > 0) {
1376
- handles[seg.id] = segHandles;
1377
- }
1378
- }
1379
- return new Response(
1380
- JSON.stringify({
1381
- segments: serializedSegments,
1382
- handles,
1383
- routeName: match.routeName,
1384
- params: match.params,
1385
- }),
1386
- { headers: { "Content-Type": "application/json" } },
1387
- );
1388
- } else {
1389
- const renderStart = performance.now();
1390
- const root = renderSegments(match.segments, {
1391
- rootLayout: router.rootLayout,
1392
- });
1393
- const renderDuration = performance.now() - renderStart;
1394
- serverTiming = match.serverTiming
1395
- ? `${match.serverTiming}, rendering;dur=${renderDuration.toFixed(2)}`
1396
- : `rendering;dur=${renderDuration.toFixed(2)}`;
1397
-
1398
- payload = {
1399
- root,
1400
- metadata: {
1401
- pathname: url.pathname,
1402
- segments: match.segments,
1403
- matched: match.matched,
1404
- diff: match.diff,
1405
- isPartial: false,
1406
- rootLayout: router.rootLayout,
1407
- handles: handleStore.stream(),
1408
- version,
1409
- themeConfig: router.themeConfig,
1410
- initialTheme: reqCtx.theme,
1411
- },
1412
- };
1413
- }
1414
- }
1415
-
1416
- // Serialize to RSC stream
1417
- const rscSerializeStart = performance.now();
1418
- const rscStream = renderToReadableStream<RscPayload>(payload);
1419
- const rscSerializeDur = performance.now() - rscSerializeStart;
1420
-
1421
- // Determine if this is an RSC request or HTML request
1422
- const isRscRequest =
1423
- (!request.headers.get("accept")?.includes("text/html") &&
1424
- !url.searchParams.has("__html")) ||
1425
- url.searchParams.has("__rsc");
1426
-
1427
- // Build complete Server-Timing: handler phases + match/manifest + rendering + RSC serialize
1428
- const timingParts: string[] = [...handlerTimingArr];
1429
- if (serverTiming) {
1430
- timingParts.push(serverTiming);
1431
- }
1432
- timingParts.push(`rsc-serialize;dur=${rscSerializeDur.toFixed(2)}`);
1433
-
1434
- if (isRscRequest) {
1435
- const fullTiming = timingParts.join(", ");
1436
- const rscHeaders: Record<string, string> = {
1437
- "content-type": "text/x-component;charset=utf-8",
1438
- vary: "accept",
1439
- };
1440
- if (fullTiming) {
1441
- rscHeaders["Server-Timing"] = fullTiming;
1442
- }
1443
- return createResponseWithMergedHeaders(rscStream, {
1444
- headers: rscHeaders,
1445
- });
1446
- }
1447
-
1448
- // Delegate to SSR for HTML response
1449
- const ssrModuleStart = performance.now();
1450
- const ssrModule = await loadSSRModule();
1451
- const ssrModuleDur = performance.now() - ssrModuleStart;
1452
- timingParts.push(`ssr-module-load;dur=${ssrModuleDur.toFixed(2)}`);
1453
-
1454
- const ssrRenderStart = performance.now();
1455
- const htmlStream = await ssrModule.renderHTML(rscStream, { nonce });
1456
- const ssrRenderDur = performance.now() - ssrRenderStart;
1457
- timingParts.push(`ssr-render-html;dur=${ssrRenderDur.toFixed(2)}`);
1458
-
1459
- // Add total handler duration
1460
- if (handlerStart) {
1461
- const totalHandler = performance.now() - handlerStart;
1462
- timingParts.push(`handler-total;dur=${totalHandler.toFixed(2)}`);
1463
- }
1464
-
1465
- const fullTiming = timingParts.join(", ");
1466
- const htmlHeaders: Record<string, string> = {
1467
- "content-type": "text/html;charset=utf-8",
1468
- };
1469
- if (fullTiming) {
1470
- htmlHeaders["Server-Timing"] = fullTiming;
1471
- }
1472
-
1473
- return createResponseWithMergedHeaders(htmlStream, {
1474
- headers: htmlHeaders,
1475
- });
1476
- }
1477
1096
  }