@rangojs/router 0.0.0-experimental.9 → 0.0.0-experimental.a06372ef

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