@rangojs/router 0.0.0-experimental.8ff1c5d → 0.0.0-experimental.90

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 (1126) hide show
  1. package/AGENTS.md +9 -0
  2. package/README.md +972 -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 +1689 -0
  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 +5643 -981
  798. package/dist/vite/index.js.bak +5448 -0
  799. package/dist/vite/index.js.map +1 -0
  800. package/dist/vite/index.named-routes.gen.ts +103 -0
  801. package/dist/vite/package-resolution.d.ts +43 -0
  802. package/dist/vite/package-resolution.d.ts.map +1 -0
  803. package/{src/vite/package-resolution.ts → dist/vite/package-resolution.js} +53 -66
  804. package/dist/vite/package-resolution.js.map +1 -0
  805. package/dist/vite/plugins/cloudflare-protocol-loader-hook.mjs +76 -0
  806. package/dist/vite/virtual-entries.d.ts +25 -0
  807. package/dist/vite/virtual-entries.d.ts.map +1 -0
  808. package/{src/vite/virtual-entries.ts → dist/vite/virtual-entries.js} +12 -16
  809. package/dist/vite/virtual-entries.js.map +1 -0
  810. package/package.json +72 -52
  811. package/skills/breadcrumbs/SKILL.md +252 -0
  812. package/skills/cache-guide/SKILL.md +294 -0
  813. package/skills/caching/SKILL.md +93 -23
  814. package/skills/composability/SKILL.md +172 -0
  815. package/skills/debug-manifest/SKILL.md +12 -8
  816. package/skills/document-cache/SKILL.md +18 -16
  817. package/skills/fonts/SKILL.md +167 -0
  818. package/skills/handler-use/SKILL.md +362 -0
  819. package/skills/hooks/SKILL.md +341 -71
  820. package/skills/host-router/SKILL.md +218 -0
  821. package/skills/intercept/SKILL.md +151 -8
  822. package/skills/layout/SKILL.md +122 -3
  823. package/skills/links/SKILL.md +166 -33
  824. package/skills/loader/SKILL.md +439 -46
  825. package/skills/middleware/SKILL.md +205 -37
  826. package/skills/migrate-nextjs/SKILL.md +560 -0
  827. package/skills/migrate-react-router/SKILL.md +765 -0
  828. package/skills/mime-routes/SKILL.md +128 -0
  829. package/skills/parallel/SKILL.md +263 -1
  830. package/skills/prerender/SKILL.md +685 -0
  831. package/skills/rango/SKILL.md +87 -16
  832. package/skills/response-routes/SKILL.md +419 -0
  833. package/skills/route/SKILL.md +281 -14
  834. package/skills/router-setup/SKILL.md +210 -32
  835. package/skills/streams-and-websockets/SKILL.md +283 -0
  836. package/skills/tailwind/SKILL.md +129 -0
  837. package/skills/theme/SKILL.md +9 -8
  838. package/skills/typesafety/SKILL.md +329 -88
  839. package/skills/use-cache/SKILL.md +324 -0
  840. package/src/__internal.ts +102 -4
  841. package/src/bin/rango.ts +321 -0
  842. package/src/browser/action-coordinator.ts +97 -0
  843. package/src/browser/action-response-classifier.ts +99 -0
  844. package/src/browser/app-shell.ts +52 -0
  845. package/src/browser/app-version.ts +14 -0
  846. package/src/browser/event-controller.ts +92 -64
  847. package/src/browser/history-state.ts +80 -0
  848. package/src/browser/intercept-utils.ts +52 -0
  849. package/src/browser/link-interceptor.ts +24 -4
  850. package/src/browser/logging.ts +55 -0
  851. package/src/browser/merge-segment-loaders.ts +20 -12
  852. package/src/browser/navigation-bridge.ts +367 -561
  853. package/src/browser/navigation-client.ts +229 -68
  854. package/src/browser/navigation-store.ts +97 -55
  855. package/src/browser/navigation-transaction.ts +297 -0
  856. package/src/browser/network-error-handler.ts +61 -0
  857. package/src/browser/partial-update.ts +362 -316
  858. package/src/browser/prefetch/cache.ts +314 -0
  859. package/src/browser/prefetch/fetch.ts +282 -0
  860. package/src/browser/prefetch/observer.ts +65 -0
  861. package/src/browser/prefetch/policy.ts +48 -0
  862. package/src/browser/prefetch/queue.ts +191 -0
  863. package/src/browser/prefetch/resource-ready.ts +77 -0
  864. package/src/browser/rango-state.ts +152 -0
  865. package/src/browser/react/Link.tsx +258 -74
  866. package/src/browser/react/NavigationProvider.tsx +132 -17
  867. package/src/browser/react/context.ts +11 -0
  868. package/src/browser/react/filter-segment-order.ts +11 -0
  869. package/src/browser/react/index.ts +12 -12
  870. package/src/browser/react/location-state-shared.ts +95 -53
  871. package/src/browser/react/location-state.ts +60 -15
  872. package/src/browser/react/mount-context.ts +6 -1
  873. package/src/browser/react/nonce-context.ts +23 -0
  874. package/src/browser/react/shallow-equal.ts +27 -0
  875. package/src/browser/react/use-action.ts +29 -51
  876. package/src/browser/react/use-client-cache.ts +5 -3
  877. package/src/browser/react/use-handle.ts +30 -126
  878. package/src/browser/react/use-href.tsx +2 -2
  879. package/src/browser/react/use-link-status.ts +6 -5
  880. package/src/browser/react/use-navigation.ts +44 -65
  881. package/src/browser/react/use-params.ts +75 -0
  882. package/src/browser/react/use-pathname.ts +47 -0
  883. package/src/browser/react/use-router.ts +83 -0
  884. package/src/browser/react/use-search-params.ts +56 -0
  885. package/src/browser/react/use-segments.ts +80 -97
  886. package/src/browser/response-adapter.ts +73 -0
  887. package/src/browser/rsc-router.tsx +246 -62
  888. package/src/browser/scroll-restoration.ts +127 -52
  889. package/src/browser/segment-reconciler.ts +243 -0
  890. package/src/browser/segment-structure-assert.ts +16 -0
  891. package/src/browser/server-action-bridge.ts +510 -603
  892. package/src/browser/shallow.ts +6 -1
  893. package/src/browser/types.ts +154 -48
  894. package/src/browser/validate-redirect-origin.ts +29 -0
  895. package/src/build/generate-manifest.ts +235 -24
  896. package/src/build/generate-route-types.ts +39 -0
  897. package/src/build/index.ts +13 -0
  898. package/src/build/route-trie.ts +291 -0
  899. package/src/build/route-types/ast-helpers.ts +25 -0
  900. package/src/build/route-types/ast-route-extraction.ts +98 -0
  901. package/src/build/route-types/codegen.ts +102 -0
  902. package/src/build/route-types/include-resolution.ts +418 -0
  903. package/src/build/route-types/param-extraction.ts +48 -0
  904. package/src/build/route-types/per-module-writer.ts +128 -0
  905. package/src/build/route-types/router-processing.ts +618 -0
  906. package/src/build/route-types/scan-filter.ts +85 -0
  907. package/src/build/runtime-discovery.ts +231 -0
  908. package/src/cache/background-task.ts +34 -0
  909. package/src/cache/cache-key-utils.ts +44 -0
  910. package/src/cache/cache-policy.ts +125 -0
  911. package/src/cache/cache-runtime.ts +342 -0
  912. package/src/cache/cache-scope.ts +167 -309
  913. package/src/cache/cf/cf-cache-store.ts +573 -21
  914. package/src/cache/cf/index.ts +13 -3
  915. package/src/cache/document-cache.ts +116 -77
  916. package/src/cache/handle-capture.ts +81 -0
  917. package/src/cache/handle-snapshot.ts +41 -0
  918. package/src/cache/index.ts +1 -15
  919. package/src/cache/memory-segment-store.ts +191 -13
  920. package/src/cache/profile-registry.ts +73 -0
  921. package/src/cache/read-through-swr.ts +134 -0
  922. package/src/cache/segment-codec.ts +256 -0
  923. package/src/cache/taint.ts +153 -0
  924. package/src/cache/types.ts +72 -122
  925. package/src/client.rsc.tsx +3 -1
  926. package/src/client.tsx +135 -301
  927. package/src/component-utils.ts +4 -4
  928. package/src/components/DefaultDocument.tsx +5 -1
  929. package/src/context-var.ts +156 -0
  930. package/src/debug.ts +19 -9
  931. package/src/errors.ts +108 -2
  932. package/src/handle.ts +55 -29
  933. package/src/handles/MetaTags.tsx +73 -20
  934. package/src/handles/breadcrumbs.ts +66 -0
  935. package/src/handles/index.ts +1 -0
  936. package/src/handles/meta.ts +30 -13
  937. package/src/host/cookie-handler.ts +165 -0
  938. package/src/host/errors.ts +97 -0
  939. package/src/host/index.ts +53 -0
  940. package/src/host/pattern-matcher.ts +214 -0
  941. package/src/host/router.ts +352 -0
  942. package/src/host/testing.ts +79 -0
  943. package/src/host/types.ts +146 -0
  944. package/src/host/utils.ts +25 -0
  945. package/src/href-client.ts +119 -29
  946. package/src/index.rsc.ts +158 -19
  947. package/src/index.ts +254 -30
  948. package/src/internal-debug.ts +11 -0
  949. package/src/loader.rsc.ts +26 -157
  950. package/src/loader.ts +27 -10
  951. package/src/network-error-thrower.tsx +3 -1
  952. package/src/outlet-context.ts +1 -1
  953. package/src/outlet-provider.tsx +45 -0
  954. package/src/prerender/param-hash.ts +37 -0
  955. package/src/prerender/store.ts +186 -0
  956. package/src/prerender.ts +524 -0
  957. package/src/response-utils.ts +28 -0
  958. package/src/reverse.ts +355 -0
  959. package/src/root-error-boundary.tsx +41 -29
  960. package/src/route-content-wrapper.tsx +7 -4
  961. package/src/route-definition/dsl-helpers.ts +1134 -0
  962. package/src/route-definition/helper-factories.ts +200 -0
  963. package/src/route-definition/helpers-types.ts +478 -0
  964. package/src/route-definition/index.ts +55 -0
  965. package/src/route-definition/redirect.ts +101 -0
  966. package/src/route-definition/resolve-handler-use.ts +155 -0
  967. package/src/route-definition.ts +1 -1428
  968. package/src/route-map-builder.ts +217 -123
  969. package/src/route-name.ts +53 -0
  970. package/src/route-types.ts +77 -8
  971. package/src/router/content-negotiation.ts +215 -0
  972. package/src/router/debug-manifest.ts +72 -0
  973. package/src/router/error-handling.ts +9 -9
  974. package/src/router/find-match.ts +160 -0
  975. package/src/router/handler-context.ts +455 -86
  976. package/src/router/intercept-resolution.ts +402 -0
  977. package/src/router/lazy-includes.ts +237 -0
  978. package/src/router/loader-resolution.ts +359 -128
  979. package/src/router/logging.ts +251 -0
  980. package/src/router/manifest.ts +163 -35
  981. package/src/router/match-api.ts +555 -0
  982. package/src/router/match-context.ts +5 -3
  983. package/src/router/match-handlers.ts +440 -0
  984. package/src/router/match-middleware/background-revalidation.ts +108 -93
  985. package/src/router/match-middleware/cache-lookup.ts +460 -10
  986. package/src/router/match-middleware/cache-store.ts +98 -26
  987. package/src/router/match-middleware/intercept-resolution.ts +57 -17
  988. package/src/router/match-middleware/segment-resolution.ts +80 -6
  989. package/src/router/match-pipelines.ts +10 -45
  990. package/src/router/match-result.ts +135 -35
  991. package/src/router/metrics.ts +240 -15
  992. package/src/router/middleware-cookies.ts +55 -0
  993. package/src/router/middleware-types.ts +200 -0
  994. package/src/router/middleware.ts +373 -371
  995. package/src/router/navigation-snapshot.ts +182 -0
  996. package/src/router/pattern-matching.ts +265 -46
  997. package/src/router/prerender-match.ts +502 -0
  998. package/src/router/preview-match.ts +98 -0
  999. package/src/router/request-classification.ts +310 -0
  1000. package/src/router/revalidation.ts +137 -38
  1001. package/src/router/route-snapshot.ts +245 -0
  1002. package/src/router/router-context.ts +41 -21
  1003. package/src/router/router-interfaces.ts +484 -0
  1004. package/src/router/router-options.ts +618 -0
  1005. package/src/router/router-registry.ts +24 -0
  1006. package/src/router/segment-resolution/fresh.ts +748 -0
  1007. package/src/router/segment-resolution/helpers.ts +268 -0
  1008. package/src/router/segment-resolution/loader-cache.ts +199 -0
  1009. package/src/router/segment-resolution/revalidation.ts +1379 -0
  1010. package/src/router/segment-resolution/static-store.ts +67 -0
  1011. package/src/router/segment-resolution.ts +21 -0
  1012. package/src/router/segment-wrappers.ts +291 -0
  1013. package/src/router/telemetry-otel.ts +299 -0
  1014. package/src/router/telemetry.ts +300 -0
  1015. package/src/router/timeout.ts +148 -0
  1016. package/src/router/trie-matching.ts +245 -0
  1017. package/src/router/types.ts +78 -3
  1018. package/src/router/url-params.ts +49 -0
  1019. package/src/router.ts +741 -4254
  1020. package/src/rsc/handler-context.ts +45 -0
  1021. package/src/rsc/handler.ts +912 -798
  1022. package/src/rsc/helpers.ts +181 -19
  1023. package/src/rsc/index.ts +0 -20
  1024. package/src/rsc/loader-fetch.ts +229 -0
  1025. package/src/rsc/manifest-init.ts +90 -0
  1026. package/src/rsc/nonce.ts +14 -0
  1027. package/src/rsc/origin-guard.ts +141 -0
  1028. package/src/rsc/progressive-enhancement.ts +393 -0
  1029. package/src/rsc/response-error.ts +37 -0
  1030. package/src/rsc/response-route-handler.ts +360 -0
  1031. package/src/rsc/rsc-rendering.ts +253 -0
  1032. package/src/rsc/runtime-warnings.ts +42 -0
  1033. package/src/rsc/server-action.ts +358 -0
  1034. package/src/rsc/ssr-setup.ts +128 -0
  1035. package/src/rsc/types.ts +46 -11
  1036. package/src/search-params.ts +230 -0
  1037. package/src/segment-content-promise.ts +67 -0
  1038. package/src/segment-loader-promise.ts +122 -0
  1039. package/src/segment-system.tsx +134 -36
  1040. package/src/server/context.ts +341 -61
  1041. package/src/server/cookie-store.ts +190 -0
  1042. package/src/server/fetchable-loader-store.ts +37 -0
  1043. package/src/server/handle-store.ts +113 -15
  1044. package/src/server/loader-registry.ts +24 -64
  1045. package/src/server/request-context.ts +603 -109
  1046. package/src/server.ts +35 -130
  1047. package/src/ssr/index.tsx +103 -30
  1048. package/src/static-handler.ts +126 -0
  1049. package/src/theme/ThemeProvider.tsx +21 -15
  1050. package/src/theme/ThemeScript.tsx +5 -5
  1051. package/src/theme/constants.ts +5 -2
  1052. package/src/theme/index.ts +4 -14
  1053. package/src/theme/theme-context.ts +4 -30
  1054. package/src/theme/theme-script.ts +21 -18
  1055. package/src/types/boundaries.ts +158 -0
  1056. package/src/types/cache-types.ts +198 -0
  1057. package/src/types/error-types.ts +192 -0
  1058. package/src/types/global-namespace.ts +100 -0
  1059. package/src/types/handler-context.ts +759 -0
  1060. package/src/types/index.ts +88 -0
  1061. package/src/types/loader-types.ts +209 -0
  1062. package/src/types/request-scope.ts +126 -0
  1063. package/src/types/route-config.ts +170 -0
  1064. package/src/types/route-entry.ts +120 -0
  1065. package/src/types/segments.ts +150 -0
  1066. package/src/types.ts +1 -1623
  1067. package/src/urls/include-helper.ts +207 -0
  1068. package/src/urls/index.ts +53 -0
  1069. package/src/urls/path-helper-types.ts +372 -0
  1070. package/src/urls/path-helper.ts +364 -0
  1071. package/src/urls/pattern-types.ts +107 -0
  1072. package/src/urls/response-types.ts +108 -0
  1073. package/src/urls/type-extraction.ts +372 -0
  1074. package/src/urls/urls-function.ts +98 -0
  1075. package/src/urls.ts +1 -802
  1076. package/src/use-loader.tsx +161 -81
  1077. package/src/vite/debug.ts +184 -0
  1078. package/src/vite/discovery/bundle-postprocess.ts +181 -0
  1079. package/src/vite/discovery/discover-routers.ts +376 -0
  1080. package/src/vite/discovery/prerender-collection.ts +486 -0
  1081. package/src/vite/discovery/route-types-writer.ts +258 -0
  1082. package/src/vite/discovery/self-gen-tracking.ts +47 -0
  1083. package/src/vite/discovery/state.ts +117 -0
  1084. package/src/vite/discovery/virtual-module-codegen.ts +203 -0
  1085. package/src/vite/index.ts +15 -1076
  1086. package/src/vite/plugin-types.ts +103 -0
  1087. package/src/vite/plugins/cjs-to-esm.ts +98 -0
  1088. package/src/vite/plugins/client-ref-dedup.ts +131 -0
  1089. package/src/vite/plugins/client-ref-hashing.ts +117 -0
  1090. package/src/vite/plugins/cloudflare-protocol-loader-hook.d.mts +23 -0
  1091. package/src/vite/plugins/cloudflare-protocol-loader-hook.mjs +76 -0
  1092. package/src/vite/plugins/cloudflare-protocol-stub.ts +214 -0
  1093. package/src/vite/{expose-action-id.ts → plugins/expose-action-id.ts} +107 -64
  1094. package/src/vite/plugins/expose-id-utils.ts +299 -0
  1095. package/src/vite/plugins/expose-ids/export-analysis.ts +296 -0
  1096. package/src/vite/plugins/expose-ids/handler-transform.ts +209 -0
  1097. package/src/vite/plugins/expose-ids/loader-transform.ts +74 -0
  1098. package/src/vite/plugins/expose-ids/router-transform.ts +127 -0
  1099. package/src/vite/plugins/expose-ids/types.ts +45 -0
  1100. package/src/vite/plugins/expose-internal-ids.ts +816 -0
  1101. package/src/vite/plugins/performance-tracks.ts +96 -0
  1102. package/src/vite/plugins/refresh-cmd.ts +127 -0
  1103. package/src/vite/plugins/use-cache-transform.ts +336 -0
  1104. package/src/vite/plugins/version-injector.ts +83 -0
  1105. package/src/vite/plugins/version-plugin.ts +266 -0
  1106. package/src/vite/plugins/virtual-entries.ts +123 -0
  1107. package/src/vite/plugins/virtual-stub-plugin.ts +29 -0
  1108. package/src/vite/rango.ts +497 -0
  1109. package/src/vite/router-discovery.ts +1111 -0
  1110. package/src/vite/utils/ast-handler-extract.ts +517 -0
  1111. package/src/vite/utils/banner.ts +36 -0
  1112. package/src/vite/utils/bundle-analysis.ts +137 -0
  1113. package/src/vite/utils/manifest-utils.ts +70 -0
  1114. package/src/vite/utils/package-resolution.ts +161 -0
  1115. package/src/vite/utils/prerender-utils.ts +221 -0
  1116. package/src/vite/utils/shared-utils.ts +170 -0
  1117. package/CLAUDE.md +0 -43
  1118. package/src/browser/lru-cache.ts +0 -69
  1119. package/src/browser/request-controller.ts +0 -164
  1120. package/src/cache/memory-store.ts +0 -253
  1121. package/src/href.ts +0 -255
  1122. package/src/server/route-manifest-cache.ts +0 -173
  1123. package/src/vite/expose-handle-id.ts +0 -209
  1124. package/src/vite/expose-loader-id.ts +0 -426
  1125. package/src/vite/expose-location-state-id.ts +0 -177
  1126. /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,36 +8,88 @@
8
8
  */
9
9
 
10
10
  import { createElement } from "react";
11
- import { renderSegments } from "../segment-system.js";
12
11
  import { RouteNotFoundError } from "../errors.js";
13
- import { getLoaderLazy } from "../server/loader-registry.js";
14
- import {
15
- matchMiddleware,
16
- executeMiddleware,
17
- executeLoaderMiddleware,
18
- } from "../router/middleware.js";
12
+ import { matchMiddleware, executeMiddleware } from "../router/middleware.js";
19
13
  import {
20
14
  runWithRequestContext,
21
15
  setRequestContextParams,
22
16
  requireRequestContext,
17
+ getRequestContext,
18
+ _getRequestContext,
23
19
  createRequestContext,
24
- type ExecutionContext,
25
20
  } from "../server/request-context.js";
26
21
  import * as rscDeps from "@vitejs/plugin-rsc/rsc";
27
-
28
22
  import type {
29
23
  RscPayload,
30
- ReactFormState,
31
24
  CreateRSCHandlerOptions,
25
+ LoadSSRModule,
26
+ SSRModule,
32
27
  } from "./types.js";
33
- import { hasBodyContent, createResponseWithMergedHeaders } from "./helpers.js";
34
- import { generateNonce } from "./nonce.js";
28
+ import {
29
+ createResponseWithMergedHeaders,
30
+ finalizeResponse,
31
+ interceptRedirectForPartial,
32
+ buildRouteMiddlewareEntries,
33
+ } from "./helpers.js";
34
+ import { isWebSocketUpgradeResponse } from "../response-utils.js";
35
+ import {
36
+ handleResponseRoute,
37
+ type ResponseRouteMatch,
38
+ } from "./response-route-handler.js";
39
+ import { generateNonce, nonce as nonceToken } from "./nonce.js";
35
40
  import { VERSION } from "@rangojs/router:version";
36
41
  import type { ErrorPhase } from "../types.js";
42
+ import type { RouterRequestInput } from "../router/router-interfaces.js";
37
43
  import { invokeOnError } from "../router/error-handling.js";
38
- import { getGlobalRouteMap, hasCachedManifest } from "../route-map-builder.js";
39
- import { getRouteManifestData } from "../server/route-manifest-cache.js";
40
- import { generateManifest } from "../build/generate-manifest.js";
44
+ import {
45
+ createReverseFunction,
46
+ stripInternalParams,
47
+ } from "../router/handler-context.js";
48
+ import { getRouterContext } from "../router/router-context.js";
49
+ import { resolveSink, safeEmit } from "../router/telemetry.js";
50
+ import { contextSet } from "../context-var.js";
51
+ import {
52
+ hasCachedManifest,
53
+ getRouteTrie,
54
+ getPrecomputedEntries,
55
+ waitForManifestReady,
56
+ getRouterManifest,
57
+ getRouterTrie,
58
+ } from "../route-map-builder.js";
59
+ import type { HandlerContext } from "./handler-context.js";
60
+ import type { SegmentCacheStore } from "../cache/types.js";
61
+ import { buildRouterTrieFromUrlpatterns } from "./manifest-init.js";
62
+ import { handleProgressiveEnhancement } from "./progressive-enhancement.js";
63
+ import {
64
+ executeServerAction,
65
+ revalidateAfterAction,
66
+ type ActionContinuation,
67
+ } from "./server-action.js";
68
+ import { handleLoaderFetch } from "./loader-fetch.js";
69
+ import { checkRequestOrigin, type OriginCheckPhase } from "./origin-guard.js";
70
+ import { handleRscRendering } from "./rsc-rendering.js";
71
+ import {
72
+ withTimeout,
73
+ RouterTimeoutError,
74
+ createDefaultTimeoutResponse,
75
+ type TimeoutPhase,
76
+ } from "../router/timeout.js";
77
+ import {
78
+ createMetricsStore,
79
+ appendMetric,
80
+ buildMetricsTiming,
81
+ } from "../router/metrics.js";
82
+ import {
83
+ startSSRSetup,
84
+ getSSRSetup,
85
+ mayNeedSSR,
86
+ SSR_SETUP_VAR,
87
+ } from "./ssr-setup.js";
88
+ import {
89
+ classifyRequest,
90
+ type RequestPlan,
91
+ type ExecutableRequestPlan,
92
+ } from "../router/request-classification.js";
41
93
 
42
94
  /**
43
95
  * Create an RSC request handler.
@@ -89,31 +141,182 @@ export function createRSCHandler<
89
141
  decodeFormState,
90
142
  } = deps;
91
143
 
92
- // Use provided loadSSRModule or default to vite RSC module loader
93
- const loadSSRModule =
144
+ // Use provided loadSSRModule or default to vite RSC module loader.
145
+ // In production the SSR module is stable across requests, so memoize
146
+ // the dynamic import to avoid repeated module resolution overhead.
147
+ // In dev mode Vite may hot-reload the module, so skip memoization.
148
+ const rawLoadSSRModule: LoadSSRModule =
94
149
  options.loadSSRModule ??
95
150
  (() => import.meta.viteRsc.loadModule("ssr", "index"));
151
+ let _ssrModulePromise: Promise<SSRModule> | undefined;
152
+ const loadSSRModule: LoadSSRModule =
153
+ process.env.NODE_ENV === "production"
154
+ ? () =>
155
+ (_ssrModulePromise ??= rawLoadSSRModule().catch((err) => {
156
+ _ssrModulePromise = undefined;
157
+ throw err;
158
+ }))
159
+ : rawLoadSSRModule;
96
160
 
97
161
  /**
98
- * Wrapper for invokeOnError that binds the router's onError callback.
99
- * Uses the shared utility from router/error-handling.ts for consistent behavior.
162
+ * Per-request error reporter that deduplicates via the ALS request context.
163
+ *
164
+ * Uses the same _reportedErrors WeakSet as the router layer so errors
165
+ * that propagate across layers are only reported once per request.
100
166
  */
101
167
  function callOnError(
102
168
  error: unknown,
103
169
  phase: ErrorPhase,
104
170
  context: Parameters<typeof invokeOnError<TEnv>>[3],
105
171
  ): void {
172
+ // Guard: abort signal handlers fire asynchronously outside the ALS
173
+ // request scope, so the context may be gone. Skip dedup in that
174
+ // case — the error is from a cancelled stream, not a real failure.
175
+ const reqCtx = _getRequestContext();
176
+ if (error != null && typeof error === "object" && reqCtx) {
177
+ if (reqCtx._reportedErrors.has(error)) return;
178
+ reqCtx._reportedErrors.add(error);
179
+ }
106
180
  invokeOnError(router.onError, error, phase, context, "RSC");
107
181
  }
108
182
 
109
- return async function handler(
183
+ function getRequiredRouteMap(): Record<string, string> {
184
+ const routeMap = getRouterManifest(router.id);
185
+ if (!routeMap) {
186
+ throw new Error(
187
+ `Route manifest for router "${router.id}" is not available.`,
188
+ );
189
+ }
190
+ return routeMap;
191
+ }
192
+
193
+ /**
194
+ * Handle a timeout by reporting the error, emitting telemetry,
195
+ * and returning either the custom onTimeout response or a default 504.
196
+ */
197
+ async function handleTimeoutResponse(
110
198
  request: Request,
111
- env: TEnv & { ctx?: ExecutionContext } = {} as TEnv & {
112
- ctx?: ExecutionContext;
199
+ env: TEnv,
200
+ url: URL,
201
+ phase: TimeoutPhase,
202
+ durationMs: number,
203
+ routeKey?: string,
204
+ actionId?: string,
205
+ ): Promise<Response> {
206
+ const timeoutError = new RouterTimeoutError(phase, durationMs);
207
+
208
+ callOnError(timeoutError, phase === "action" ? "action" : "handler", {
209
+ request,
210
+ url,
211
+ env,
212
+ routeKey,
213
+ actionId,
214
+ handledByBoundary: false,
215
+ metadata: { timeout: true, phase, durationMs },
216
+ });
217
+
218
+ try {
219
+ const routerCtx = getRouterContext();
220
+ if (routerCtx?.telemetry) {
221
+ safeEmit(resolveSink(routerCtx.telemetry), {
222
+ type: "request.timeout" as const,
223
+ timestamp: performance.now(),
224
+ requestId: routerCtx.requestId,
225
+ phase,
226
+ pathname: url.pathname,
227
+ routeKey,
228
+ actionId,
229
+ durationMs,
230
+ customHandler: !!router.onTimeout,
231
+ });
232
+ }
233
+ } catch {
234
+ // Router context may not be available
235
+ }
236
+
237
+ if (router.onTimeout) {
238
+ try {
239
+ return await router.onTimeout({
240
+ phase,
241
+ request,
242
+ url,
243
+ env,
244
+ routeKey,
245
+ actionId,
246
+ durationMs,
247
+ });
248
+ } catch (e) {
249
+ if (process.env.NODE_ENV !== "production") {
250
+ console.error("[RSC] onTimeout callback error:", e);
251
+ }
252
+ return createDefaultTimeoutResponse(phase);
253
+ }
254
+ }
255
+
256
+ return createDefaultTimeoutResponse(phase);
257
+ }
258
+
259
+ /**
260
+ * Build a 200 Flight response that carries a redirect URL and optional state.
261
+ * Used when a partial/action request results in a redirect -- fetch
262
+ * auto-follows 3xx so we send the redirect as payload metadata instead.
263
+ */
264
+ function createRedirectFlightResponse(
265
+ redirectUrl: string,
266
+ locationState?: Record<string, unknown>,
267
+ ): Response {
268
+ const redirectPayload: RscPayload = {
269
+ metadata: {
270
+ pathname: redirectUrl,
271
+ segments: [],
272
+ redirect: { url: redirectUrl },
273
+ ...(locationState && { locationState }),
274
+ },
275
+ };
276
+ const rscStream = renderToReadableStream<RscPayload>(redirectPayload);
277
+ return createResponseWithMergedHeaders(rscStream, {
278
+ status: 200,
279
+ headers: { "content-type": "text/x-component;charset=utf-8" },
280
+ });
281
+ }
282
+
283
+ // Bundle shared dependencies for extracted handler functions.
284
+ // callOnError reads from ALS so it's inherently per-request scoped.
285
+ const handlerCtx: HandlerContext<TEnv> = {
286
+ router,
287
+ version,
288
+ renderToReadableStream,
289
+ decodeReply,
290
+ createTemporaryReferenceSet,
291
+ loadServerAction,
292
+ decodeAction,
293
+ decodeFormState,
294
+ loadSSRModule,
295
+ callOnError,
296
+ getRequiredRouteMap,
297
+ createRedirectFlightResponse,
298
+ resolveStreamMode: async (request, env, url) => {
299
+ const resolver = router.ssr?.resolveStreaming;
300
+ if (!resolver) return "stream";
301
+ return resolver({ request, env, url });
113
302
  },
303
+ };
304
+
305
+ return async function handler(
306
+ request: Request,
307
+ input: RouterRequestInput<TEnv> = {},
114
308
  ): Promise<Response> {
309
+ const handlerStart = performance.now();
310
+ // Create the metrics store at handler start so handler:total has startTime=0
311
+ // and all metrics are relative to the request entry point.
312
+ const earlyMetricsStore = router.debugPerformance
313
+ ? createMetricsStore(true, handlerStart)
314
+ : undefined;
315
+
316
+ const { env = {} as TEnv, vars: initialVars, ctx: executionCtx } = input;
317
+
115
318
  // Connection warmup: return 204 immediately before any processing
116
- if (router.warmupEnabled && request.method === "HEAD") {
319
+ if (router?.warmupEnabled && request.method === "HEAD") {
117
320
  const warmupUrl = new URL(request.url);
118
321
  if (warmupUrl.searchParams.has("_rsc_warmup")) {
119
322
  return new Response(null, { status: 204 });
@@ -121,72 +324,137 @@ export function createRSCHandler<
121
324
  }
122
325
 
123
326
  // Resolve nonce if provider is set
327
+ const nonceStart = performance.now();
124
328
  let nonce: string | undefined;
125
329
  if (nonceProvider) {
126
330
  const result = await nonceProvider(request, env);
127
331
  nonce = result === true ? generateNonce() : result;
128
332
  }
333
+ const nonceDur = performance.now() - nonceStart;
129
334
 
130
335
  const url = new URL(request.url);
131
336
 
132
337
  // Match global middleware
338
+ const mwMatchStart = performance.now();
133
339
  const matchedMiddleware = matchMiddleware(url.pathname, router.middleware);
340
+ const mwMatchDur = performance.now() - mwMatchStart;
134
341
 
135
342
  // Shared variables between middleware and route handlers
136
- // Initialize from env.Variables if provided (allows pre-seeding from worker entry)
137
- const variables: Record<string, any> = {
138
- ...((env as any)?.Variables ?? {}),
139
- };
343
+ // Initialize from input.vars if provided (allows pre-seeding from worker entry)
344
+ const variables: Record<string, any> = initialVars
345
+ ? { ...initialVars }
346
+ : {};
140
347
 
141
- // Store nonce in variables so middleware can access via ctx.get('nonce')
348
+ // Store nonce via ContextVar token and string key for backward compat
142
349
  if (nonce) {
350
+ contextSet(variables, nonceToken, nonce);
143
351
  variables.nonce = nonce;
144
352
  }
145
353
 
146
354
  // Resolve cache store configuration
147
355
  // Priority: options.cache (handler override) > router.cache (router default)
148
356
  // Store is enabled only if: config provided, enabled, and no ?__no_cache query param
149
- let cacheStore = undefined;
357
+ let cacheStore: SegmentCacheStore | undefined;
150
358
  const cacheOption = options.cache ?? router.cache;
151
359
  if (cacheOption && !url.searchParams.has("__no_cache")) {
152
360
  const cacheConfig =
153
- typeof cacheOption === "function" ? cacheOption(env) : cacheOption;
361
+ typeof cacheOption === "function"
362
+ ? cacheOption(env, executionCtx)
363
+ : cacheOption;
154
364
 
155
365
  if (cacheConfig.enabled !== false) {
156
366
  cacheStore = cacheConfig.store;
157
367
  }
158
368
  }
159
369
 
160
- // Load route manifest on first request (always enabled when urlpatterns exist)
161
- // This enables href() for all routes including lazy includes
162
- // Manifest is regenerated when version changes (HMR in dev mode)
163
- // Skip when already cached in memory to avoid async overhead on every request
164
- if (router.urlpatterns && !hasCachedManifest()) {
165
- await getRouteManifestData(
166
- () => generateManifest(router.urlpatterns!),
167
- version,
168
- {
169
- store: cacheStore,
170
- waitUntil: env.ctx?.waitUntil.bind(env.ctx),
171
- },
172
- );
370
+ // Route manifest is populated at startup via the virtual module
371
+ // (virtual:rsc-router/routes-manifest). In build/production, it's inlined
372
+ // into the bundle. In dev mode (Node), the discovery plugin populates it
373
+ // via setManifestReadyPromise(). In dev mode (Cloudflare), Miniflare runs
374
+ // in a separate isolate where module-level state doesn't carry over, so
375
+ // we generate inline from the router's urlpatterns.
376
+ //
377
+ // In multi-router setups (e.g. createHostRouter), each router must have
378
+ // its own per-router manifest. We check per-router data first: even if
379
+ // the global manifest was set by a different router, this router still
380
+ // needs its own trie and manifest for correct matching.
381
+ const manifestCacheStart = performance.now();
382
+ const hasRouterData = getRouterManifest(router.id) !== undefined;
383
+ if (!hasRouterData) {
384
+ if (!hasCachedManifest()) {
385
+ const readyPromise = waitForManifestReady();
386
+ if (readyPromise) {
387
+ await readyPromise;
388
+ }
389
+ }
390
+ if (!getRouterManifest(router.id) && router.urlpatterns) {
391
+ // Cloudflare dev: generate manifest inline for this router.
392
+ // Each router generates its own manifest independently so
393
+ // multi-router setups (host routing) work correctly.
394
+ await buildRouterTrieFromUrlpatterns(router);
395
+ }
396
+ if (!getRouterManifest(router.id) && !hasCachedManifest()) {
397
+ throw new Error(
398
+ 'Route manifest not available. Ensure "virtual:rsc-router/routes-manifest" is imported in your entry file.',
399
+ );
400
+ }
173
401
  }
174
402
 
175
- // Note: Route map for useHref() is loaded lazily via getGlobalRouteMap()
176
- // This allows it to include all routes from lazy includes after manifest loading
403
+ // Rebuild the trie when the manifest exists but the per-router trie is
404
+ // missing. This happens in dev mode after HMR: the virtual module sets
405
+ // the manifest (from fresh gen files) but the trie is intentionally not
406
+ // injected to avoid stale discovery-time data. Without the trie, route
407
+ // matching falls back to regex iteration which does not handle wildcard
408
+ // priority correctly (catch-all patterns match before specific routes).
409
+ if (!getRouterTrie(router.id) && router.urlpatterns) {
410
+ await buildRouterTrieFromUrlpatterns(router);
411
+ }
412
+ const manifestCacheDur = performance.now() - manifestCacheStart;
177
413
 
178
414
  // Create unified request context with all methods
179
415
  // Includes: stub response, handle store, loader memoization, use(), cookies, headers, cache store
180
416
  // params starts empty, populated after route matching via setRequestContextParams
417
+ const ctxCreateStart = performance.now();
181
418
  const requestContext = createRequestContext({
182
419
  env,
183
420
  request,
184
421
  url,
185
422
  variables,
186
423
  cacheStore,
187
- executionContext: env.ctx,
424
+ cacheProfiles: router.cacheProfiles,
425
+ executionContext: executionCtx,
188
426
  themeConfig: router.themeConfig,
189
427
  });
428
+ if (earlyMetricsStore) {
429
+ requestContext._debugPerformance = true;
430
+ requestContext._metricsStore = earlyMetricsStore;
431
+ }
432
+ // Wire background error reporting so "use cache" and other subsystems
433
+ // can surface non-fatal errors through the router's onError callback.
434
+ requestContext._reportBackgroundError = (
435
+ error: unknown,
436
+ category: string,
437
+ ) => {
438
+ callOnError(error, "cache", {
439
+ request,
440
+ url,
441
+ metadata: { category },
442
+ });
443
+ };
444
+
445
+ const ctxCreateDur = performance.now() - ctxCreateStart;
446
+
447
+ // Accumulate handler-level timing for Server-Timing header
448
+ const handlerTiming = [
449
+ `handler-nonce;dur=${nonceDur.toFixed(2)}`,
450
+ `handler-mw-match;dur=${mwMatchDur.toFixed(2)}`,
451
+ `handler-manifest-cache;dur=${manifestCacheDur.toFixed(2)}`,
452
+ `handler-ctx-create;dur=${ctxCreateDur.toFixed(2)}`,
453
+ ];
454
+
455
+ // Store timing data in variables for downstream access
456
+ variables.__handlerTiming = handlerTiming;
457
+ variables.__handlerStart = handlerStart;
190
458
 
191
459
  // Wrap entire request handling in request context
192
460
  // Makes context available via getRequestContext() throughout:
@@ -195,6 +463,9 @@ export function createRSCHandler<
195
463
  // - Server components during rendering
196
464
  // - Error boundaries
197
465
  // - Streaming
466
+ // Store basename on request context (scoped per-request via existing ALS)
467
+ requestContext._basename = router.basename;
468
+
198
469
  return runWithRequestContext(requestContext, async () => {
199
470
  // Core handler logic (wrapped by middleware)
200
471
  const coreHandler = async (): Promise<Response> => {
@@ -202,21 +473,79 @@ export function createRSCHandler<
202
473
  };
203
474
 
204
475
  // Execute middleware chain if any, otherwise call core handler directly
476
+ let response: Response;
205
477
  if (matchedMiddleware.length > 0) {
206
- return executeMiddleware(
478
+ const mwResponse = await executeMiddleware(
207
479
  matchedMiddleware,
208
480
  request,
209
481
  env,
210
482
  variables,
211
483
  coreHandler,
484
+ createReverseFunction(getRequiredRouteMap()),
485
+ );
486
+
487
+ if (
488
+ url.searchParams.has("_rsc_partial") ||
489
+ url.searchParams.has("_rsc_action")
490
+ ) {
491
+ const intercepted = interceptRedirectForPartial(
492
+ mwResponse,
493
+ createRedirectFlightResponse,
494
+ );
495
+ response = intercepted ?? finalizeResponse(mwResponse);
496
+ } else {
497
+ response = finalizeResponse(mwResponse);
498
+ }
499
+ } else {
500
+ response = await coreHandler();
501
+ }
502
+
503
+ // Finalize metrics after all middleware (including post-next work)
504
+ // has completed so :post spans are captured in the timeline.
505
+ // Handler timing parts are always emitted (even without debug metrics)
506
+ // so non-debug requests still get bootstrap Server-Timing entries.
507
+ const handlerTimingArr: string[] = variables.__handlerTiming || [];
508
+ // Preserve any existing Server-Timing set by response routes or middleware
509
+ const existingTiming = response.headers.get("Server-Timing");
510
+ const timingParts = existingTiming
511
+ ? [existingTiming, ...handlerTimingArr]
512
+ : [...handlerTimingArr];
513
+
514
+ const metricsStore = requestContext._metricsStore;
515
+ if (metricsStore) {
516
+ // When the store was created at handler start (earlyMetricsStore),
517
+ // handler:total covers the full request. When ctx.debugPerformance()
518
+ // created the store mid-request, use its requestStart to avoid a
519
+ // negative startTime offset.
520
+ const totalStart = earlyMetricsStore
521
+ ? handlerStart
522
+ : metricsStore.requestStart;
523
+ appendMetric(
524
+ metricsStore,
525
+ "handler:total",
526
+ totalStart,
527
+ performance.now() - totalStart,
528
+ );
529
+ const metricsTiming = buildMetricsTiming(
530
+ request.method,
531
+ url.pathname,
532
+ metricsStore,
212
533
  );
534
+ if (metricsTiming) timingParts.push(metricsTiming);
535
+ }
536
+
537
+ const fullTiming = timingParts.join(", ");
538
+ if (fullTiming && !isWebSocketUpgradeResponse(response)) {
539
+ response.headers.set("Server-Timing", fullTiming);
213
540
  }
214
541
 
215
- return coreHandler();
542
+ return response;
216
543
  });
217
544
  };
218
545
 
219
- // Core request handling logic (separated for middleware wrapping)
546
+ // Core request handling logic (separated for middleware wrapping).
547
+ // Uses the classify → execute model: classifyRequest produces a RequestPlan,
548
+ // then execution dispatches on the plan mode.
220
549
  async function coreRequestHandler(
221
550
  request: Request,
222
551
  env: TEnv,
@@ -224,856 +553,641 @@ export function createRSCHandler<
224
553
  variables: Record<string, any>,
225
554
  nonce: string | undefined,
226
555
  ): Promise<Response> {
227
- // First, check for route-level middleware
228
- const preview = await router.previewMatch(request, env);
229
- if (preview?.routeMiddleware && preview.routeMiddleware.length > 0) {
230
- // Convert route middleware to app middleware format for execution
231
- const middlewareEntries = preview.routeMiddleware.map((mw) => ({
232
- entry: {
233
- pattern: null,
234
- regex: null,
235
- paramNames: [],
236
- handler: mw.handler,
237
- mountPrefix: null,
556
+ const handlerTiming: string[] = variables.__handlerTiming || [];
557
+
558
+ // Debug manifest endpoint: handled before classification since it
559
+ // doesn't need a route match and needs trie access from the closure.
560
+ const isDev = process.env.NODE_ENV !== "production";
561
+ if (
562
+ url.searchParams.has("__debug_manifest") &&
563
+ (isDev || router.allowDebugManifest)
564
+ ) {
565
+ const trie = getRouterTrie(router.id) ?? getRouteTrie();
566
+ const routeManifest = getRequiredRouteMap();
567
+ const { extractAncestryFromTrie } =
568
+ await import("../build/route-trie.js");
569
+ return new Response(
570
+ JSON.stringify(
571
+ {
572
+ routerId: router.id,
573
+ routeManifest,
574
+ routeAncestry: trie ? extractAncestryFromTrie(trie) : {},
575
+ routeTrie: trie,
576
+ precomputedEntries: getPrecomputedEntries(),
577
+ },
578
+ null,
579
+ 2,
580
+ ),
581
+ {
582
+ headers: { "Content-Type": "application/json" },
238
583
  },
239
- params: mw.params,
240
- }));
241
-
242
- // Execute route middleware wrapping the actual request handling
243
- return executeMiddleware(middlewareEntries, request, env, variables, () =>
244
- coreRequestHandlerInner(request, env, url, variables, nonce),
245
584
  );
246
585
  }
247
586
 
248
- // No route middleware, proceed directly
249
- return coreRequestHandlerInner(request, env, url, variables, nonce);
250
- }
251
-
252
- // Inner request handler (actual RSC logic, wrapped by route middleware if any)
253
- async function coreRequestHandlerInner(
254
- request: Request,
255
- env: TEnv,
256
- url: URL,
257
- variables: Record<string, any>,
258
- nonce: string | undefined,
259
- ): Promise<Response> {
260
- // Early return for static file requests that don't need RSC handling
261
- if (url.pathname === "/favicon.ico" || url.pathname === "/robots.txt") {
262
- return new Response(null, { status: 404 });
263
- }
264
-
265
- // Debug endpoint - only in development
266
- if (url.pathname === "/__debug_manifest" && process.env.NODE_ENV !== "production") {
267
- const manifest = await router.debugManifest();
268
- return new Response(JSON.stringify(manifest, null, 2), {
269
- headers: { "Content-Type": "application/json" },
587
+ // ---- 1. Classify ----
588
+ // classifyRequest may throw RouteNotFoundError for unknown routes.
589
+ // In that case, fall through to a full-render plan so the pipeline
590
+ // can render the 404 page via the existing error handling path.
591
+ const classifyStart = performance.now();
592
+ let plan: RequestPlan<TEnv>;
593
+ try {
594
+ plan = await classifyRequest<TEnv>(request, url, {
595
+ findMatch: router.findMatch,
596
+ routerVersion: version,
597
+ routerId: router.id,
270
598
  });
599
+ } catch (error) {
600
+ if (
601
+ error instanceof RouteNotFoundError ||
602
+ (error instanceof Error && error.name === "RouteNotFoundError")
603
+ ) {
604
+ // Let the render path handle 404 — match()/matchPartial() will
605
+ // re-throw RouteNotFoundError and the catch block in
606
+ // executeRenderWithMiddleware renders the not-found page.
607
+ plan = {
608
+ mode: "full-render",
609
+ route: {
610
+ matched: null as any,
611
+ manifestEntry: null as any,
612
+ entries: [],
613
+ routeKey: "",
614
+ localRouteName: "",
615
+ params: {},
616
+ routeMiddleware: [],
617
+ cacheScope: null,
618
+ isPassthrough: false,
619
+ },
620
+ negotiated: false,
621
+ };
622
+ } else {
623
+ throw error;
624
+ }
625
+ }
626
+ const classifyDur = performance.now() - classifyStart;
627
+ handlerTiming.push(`handler-classify;dur=${classifyDur.toFixed(2)}`);
628
+
629
+ // ---- 2. Terminal plans (no execution needed) ----
630
+ if (plan.mode === "redirect") {
631
+ // Redirects are handled by the pipeline (match/matchPartial),
632
+ // but for partial requests we short-circuit with a Flight redirect.
633
+ if (url.searchParams.has("_rsc_partial")) {
634
+ return createRedirectFlightResponse(plan.redirectUrl);
635
+ }
636
+ // Full requests: let the pipeline handle the redirect via match()
637
+ // which returns { redirect: url }. Fall through to full-render.
271
638
  }
272
639
 
273
- const isPartial = url.searchParams.has("_rsc_partial");
274
- const isAction =
275
- request.headers.has("rsc-action") || url.searchParams.has("_rsc_action");
276
- const actionId =
277
- request.headers.get("rsc-action") || url.searchParams.get("_rsc_action");
278
-
279
- // Version mismatch detection - client may have stale code after HMR/deployment
280
- // If versions don't match, tell the client to reload
281
- const clientVersion = url.searchParams.get("_rsc_v");
282
- if (version && clientVersion && clientVersion !== version) {
640
+ if (plan.mode === "version-mismatch") {
283
641
  console.log(
284
- `[RSC] Version mismatch: client=${clientVersion}, server=${version}. Forcing reload.`,
642
+ `[RSC] Version mismatch: client=${url.searchParams.get("_rsc_v")}, server=${version}. Forcing reload.`,
285
643
  );
286
-
287
- // Clean URL by removing RSC params
288
- const cleanUrl = new URL(url);
289
- cleanUrl.searchParams.delete("_rsc_partial");
290
- cleanUrl.searchParams.delete("_rsc_segments");
291
- cleanUrl.searchParams.delete("_rsc_v");
292
- cleanUrl.searchParams.delete("_rsc_stale");
293
- cleanUrl.searchParams.delete("_rsc_action");
294
- cleanUrl.searchParams.delete("_rsc_prev");
295
-
296
- // For actions, reload current page (referer)
297
- // For navigation, load the target URL
298
- const reloadUrl = isAction
299
- ? request.headers.get("referer") || cleanUrl.toString()
300
- : cleanUrl.toString();
301
-
302
- // Return special response that tells client to reload
303
644
  return createResponseWithMergedHeaders(null, {
304
645
  status: 200,
305
646
  headers: {
306
- "X-RSC-Reload": reloadUrl,
647
+ "X-RSC-Reload": plan.reloadUrl,
307
648
  "content-type": "text/x-component;charset=utf-8",
308
649
  },
309
650
  });
310
651
  }
311
652
 
312
- // Get handle store from request context (created at start of request)
313
- const handleStore = requireRequestContext()._handleStore;
314
-
315
- try {
316
- // ============================================================================
317
- // PROGRESSIVE ENHANCEMENT: No-JS Form Submissions
318
- // ============================================================================
319
- const progressiveResult = await handleProgressiveEnhancement(
653
+ // ---- 3. Origin guard (gate for action/loader/PE modes) ----
654
+ const originPhase: OriginCheckPhase | null =
655
+ plan.mode === "action"
656
+ ? "action"
657
+ : plan.mode === "loader"
658
+ ? "loader"
659
+ : plan.mode === "pe-render"
660
+ ? "pe-form"
661
+ : null;
662
+ if (originPhase) {
663
+ const originResult = await checkRequestOrigin(
320
664
  request,
321
- env,
322
665
  url,
323
- isAction,
324
- handleStore,
325
- nonce,
326
- );
327
- if (progressiveResult) {
328
- return progressiveResult;
329
- }
330
-
331
- // ============================================================================
332
- // SERVER ACTION EXECUTION (JavaScript-enabled client)
333
- // ============================================================================
334
- if (isAction && actionId) {
335
- return handleServerAction(request, env, url, actionId, handleStore);
336
- }
337
-
338
- // ============================================================================
339
- // LOADER FETCH EXECUTION (data fetching with RSC serialization)
340
- // ============================================================================
341
- const isLoaderRequest = url.searchParams.has("_rsc_loader");
342
- if (isLoaderRequest) {
343
- return handleLoaderFetch(request, env, url, variables);
344
- }
345
-
346
- // ============================================================================
347
- // REGULAR RSC RENDERING (Navigation)
348
- // ============================================================================
349
- // Note: Must use "return await" for try/catch to catch async rejections
350
- return await handleRscRendering(
351
- request,
666
+ router.originCheck,
352
667
  env,
353
- url,
354
- isPartial,
355
- handleStore,
356
- nonce,
668
+ router.id,
669
+ originPhase,
357
670
  );
358
- } catch (error) {
359
- // Check if middleware/handler returned Response
360
- if (error instanceof Response) {
361
- return error;
362
- }
671
+ if (originResult) {
672
+ const originError = new Error(
673
+ `Origin check rejected: ${request.headers.get("origin") ?? "none"} vs ${request.headers.get("host") ?? "none"}`,
674
+ );
675
+ originError.name = "OriginCheckError";
363
676
 
364
- // Render 404 page for unmatched routes
365
- // Check both instanceof and error.name for cross-bundle compatibility
366
- const isRouteNotFound =
367
- error instanceof RouteNotFoundError ||
368
- (error instanceof Error && error.name === "RouteNotFoundError");
369
- if (isRouteNotFound) {
370
- callOnError(error, "routing", {
677
+ callOnError(originError, "origin", {
371
678
  request,
372
679
  url,
373
680
  env,
374
- handledByBoundary: true, // Handled by notFound component
375
- });
376
-
377
- // Get notFound component from router options or use default
378
- const notFoundOption = router.notFound;
379
- const notFoundComponent =
380
- typeof notFoundOption === "function"
381
- ? notFoundOption({ pathname: url.pathname })
382
- : (notFoundOption ?? createElement("h1", null, "Not Found"));
383
-
384
- // Create a simple segment for the 404 page
385
- const notFoundSegment = {
386
- id: "notFound",
387
- namespace: "notFound",
388
- type: "route" as const,
389
- index: 0,
390
- component: notFoundComponent,
391
- params: {},
392
- };
393
-
394
- // Render with rootLayout to maintain app shell
395
- const root = await renderSegments([notFoundSegment], {
396
- rootLayout: router.rootLayout,
397
- // No routeName for not-found routes
398
- });
399
-
400
- const payload: RscPayload = {
401
- root,
681
+ handledByBoundary: false,
402
682
  metadata: {
403
- pathname: url.pathname,
404
- segments: [notFoundSegment],
405
- matched: [],
406
- diff: [],
407
- isPartial: false,
408
- handles: handleStore.stream(),
409
- version,
410
- themeConfig: router.themeConfig,
411
- warmupEnabled: router.warmupEnabled,
412
- initialTheme: requireRequestContext().theme,
413
- // No routeName for not-found routes
683
+ phase: originPhase,
684
+ origin: request.headers.get("origin"),
685
+ host: request.headers.get("host"),
414
686
  },
415
- };
416
-
417
- const rscStream = renderToReadableStream(payload);
418
-
419
- // Determine if this is an RSC request or HTML request
420
- const isRscRequest =
421
- (!request.headers.get("accept")?.includes("text/html") &&
422
- !url.searchParams.has("__html")) ||
423
- url.searchParams.has("__rsc");
687
+ });
424
688
 
425
- if (isRscRequest) {
426
- return createResponseWithMergedHeaders(rscStream, {
427
- status: 404,
428
- headers: { "content-type": "text/x-component;charset=utf-8" },
429
- });
689
+ try {
690
+ const routerCtx = getRouterContext();
691
+ if (routerCtx?.telemetry) {
692
+ safeEmit(resolveSink(routerCtx.telemetry), {
693
+ type: "request.origin-rejected" as const,
694
+ timestamp: performance.now(),
695
+ requestId: routerCtx.requestId,
696
+ method: request.method,
697
+ pathname: url.pathname,
698
+ phase: originPhase,
699
+ origin: request.headers.get("origin"),
700
+ host: request.headers.get("host"),
701
+ });
702
+ }
703
+ } catch {
704
+ // Router context may not be available
430
705
  }
431
706
 
432
- // Delegate to SSR for HTML response
433
- const ssrModule = await loadSSRModule();
434
- const htmlStream = await ssrModule.renderHTML(rscStream, { nonce });
435
-
436
- return createResponseWithMergedHeaders(htmlStream, {
437
- status: 404,
438
- headers: { "content-type": "text/html;charset=utf-8" },
439
- });
707
+ return originResult;
440
708
  }
441
-
442
- // Report unhandled errors
443
- callOnError(error, "routing", {
444
- request,
445
- url,
446
- env,
447
- handledByBoundary: false,
448
- });
449
- console.error(`[RSC] Error:`, error);
450
- throw error;
451
709
  }
710
+
711
+ // ---- 4. Execute ----
712
+ return executeRequest(
713
+ plan as ExecutableRequestPlan<TEnv>,
714
+ request,
715
+ env,
716
+ url,
717
+ variables,
718
+ nonce,
719
+ );
452
720
  }
453
721
 
454
- // ============================================================================
455
- // PROGRESSIVE ENHANCEMENT HANDLER
456
- // When JavaScript is disabled, React renders forms with hidden fields
457
- // ($ACTION_REF_*, $ACTION_KEY) containing the action reference.
458
- // We detect these and return HTML instead of RSC stream.
459
- // ============================================================================
460
- async function handleProgressiveEnhancement(
722
+ // Execute a classified request plan. Dispatches to the appropriate handler
723
+ // based on plan.mode. Lives in the createRSCHandler closure for access to
724
+ // handlerCtx, router, callOnError, etc.
725
+ // Only receives executable plans (version-mismatch is handled above).
726
+ async function executeRequest(
727
+ plan: ExecutableRequestPlan<TEnv>,
461
728
  request: Request,
462
729
  env: TEnv,
463
730
  url: URL,
464
- isAction: boolean,
465
- handleStore: ReturnType<typeof requireRequestContext>["_handleStore"],
731
+ variables: Record<string, any>,
466
732
  nonce: string | undefined,
467
- ): Promise<Response | null> {
468
- const contentType = request.headers.get("content-type") || "";
469
- const isFormSubmission =
470
- contentType.includes("multipart/form-data") ||
471
- contentType.includes("application/x-www-form-urlencoded");
472
-
473
- if (request.method !== "POST" || isAction || !isFormSubmission) {
474
- return null;
475
- }
476
-
477
- // Clone the request to read FormData without consuming it
478
- const formData = await request.clone().formData();
479
-
480
- // Look for React's progressive enhancement hidden fields
481
- let isDirectAction = false;
482
- let isUseActionState = false;
483
- let directActionId: string | null = null;
733
+ ): Promise<Response> {
734
+ // Common setup
735
+ const handleStore = requireRequestContext()._handleStore;
484
736
 
485
- formData.forEach((_value, key) => {
486
- if (key.startsWith("$ACTION_ID_")) {
487
- isDirectAction = true;
488
- directActionId = key.slice("$ACTION_ID_".length);
489
- } else if (key.startsWith("$ACTION_REF_")) {
490
- isUseActionState = true;
737
+ // Wire up error reporting for late streaming-handle failures
738
+ handleStore.onError = (error: Error) => {
739
+ const reqCtx = requireRequestContext();
740
+ callOnError(error, "handler", {
741
+ request,
742
+ url,
743
+ routeKey: reqCtx._routeName,
744
+ params: reqCtx.params as Record<string, string>,
745
+ handledByBoundary: true,
746
+ });
747
+ try {
748
+ const routerCtx = getRouterContext();
749
+ if (routerCtx?.telemetry) {
750
+ safeEmit(resolveSink(routerCtx.telemetry), {
751
+ type: "handler.error" as const,
752
+ timestamp: performance.now(),
753
+ requestId: routerCtx.requestId,
754
+ error,
755
+ handledByBoundary: true,
756
+ pathname: url.pathname,
757
+ routeKey: reqCtx._routeName,
758
+ params: reqCtx.params as Record<string, string>,
759
+ });
760
+ }
761
+ } catch {
762
+ // Router context may not be available (e.g. prerender path)
491
763
  }
492
- });
764
+ };
493
765
 
494
- if (!isDirectAction && !isUseActionState) {
495
- return null;
766
+ // Set route params early so all execution paths can access ctx.params.
767
+ // Also store the classified snapshot so match/matchPartial can reuse it
768
+ // instead of calling resolveRoute again.
769
+ if (plan.mode !== "redirect") {
770
+ setRequestContextParams(plan.route.params, plan.route.routeKey);
771
+ requireRequestContext()._classifiedRoute = plan.route;
496
772
  }
497
773
 
498
- // Execute action and return HTML
499
- let actionResult: unknown = undefined;
500
- let reactFormState: ReactFormState | null = null;
501
-
502
- if (isUseActionState) {
503
- try {
504
- const boundAction = await decodeAction(formData);
505
- actionResult = await boundAction();
506
- } catch (error) {
507
- callOnError(error, "action", {
774
+ const routeReverse = createReverseFunction(getRequiredRouteMap());
775
+
776
+ // ---- Response route: skip entire RSC pipeline ----
777
+ if (plan.mode === "response") {
778
+ // Build ResponseRouteMatch from plan fields. handleResponseRoute
779
+ // expects a flat object with params at the top level.
780
+ const responseMatch: ResponseRouteMatch = {
781
+ responseType: plan.responseType,
782
+ handler: plan.handler,
783
+ params: plan.route.params,
784
+ negotiated: plan.negotiated,
785
+ manifestEntry: plan.manifestEntry,
786
+ routeMiddleware: plan.routeMiddleware,
787
+ };
788
+ const responseOutcome = await withTimeout(
789
+ handleResponseRoute(
790
+ handlerCtx,
791
+ responseMatch,
508
792
  request,
793
+ env,
509
794
  url,
795
+ variables,
796
+ ),
797
+ router.timeouts.renderStartMs,
798
+ "render-start",
799
+ );
800
+ if (responseOutcome.timedOut) {
801
+ return handleTimeoutResponse(
802
+ request,
510
803
  env,
511
- handledByBoundary: false,
512
- });
513
- console.error("[RSC] Progressive enhancement action error:", error);
804
+ url,
805
+ "render-start",
806
+ responseOutcome.durationMs,
807
+ plan.route.routeKey,
808
+ );
514
809
  }
515
- } else if (isDirectAction && directActionId) {
516
- const temporaryReferences = createTemporaryReferenceSet();
517
-
518
- let args: unknown[] = [];
519
- try {
520
- args = await decodeReply(formData, { temporaryReferences });
521
- } catch {
522
- args = [formData];
810
+ const response = responseOutcome.result;
811
+ if (plan.negotiated && !isWebSocketUpgradeResponse(response)) {
812
+ response.headers.append("Vary", "Accept");
523
813
  }
814
+ return response;
815
+ }
816
+
817
+ // SSR setup: kick off in parallel for modes that need HTML rendering.
818
+ // Placed after response-route short-circuit so response/mime routes
819
+ // never pay for SSR work.
820
+ if (plan.mode !== "loader" && mayNeedSSR(request, url)) {
821
+ variables[SSR_SETUP_VAR] = startSSRSetup(
822
+ handlerCtx,
823
+ request,
824
+ env,
825
+ url,
826
+ router.debugPerformance
827
+ ? () => requireRequestContext()._metricsStore
828
+ : undefined,
829
+ );
830
+ }
831
+
832
+ // ---- Loader fetch ----
833
+ if (plan.mode === "loader") {
834
+ return handleLoaderFetch(
835
+ handlerCtx,
836
+ request,
837
+ env,
838
+ url,
839
+ variables,
840
+ plan.route.params,
841
+ );
842
+ }
524
843
 
844
+ // ---- Progressive enhancement ----
845
+ if (plan.mode === "pe-render") {
846
+ const peResult = await handleProgressiveEnhancement(
847
+ handlerCtx,
848
+ request,
849
+ env,
850
+ url,
851
+ false, // isAction = false for PE
852
+ handleStore,
853
+ nonce,
854
+ {
855
+ routeMiddleware: plan.route.routeMiddleware,
856
+ variables,
857
+ routeReverse,
858
+ },
859
+ );
860
+ if (peResult) return peResult;
861
+ // PE handler returned null (not a PE form) — fall through to render
862
+ }
863
+
864
+ // ---- Action: execute action, then revalidate wrapped in route middleware ----
865
+ if (plan.mode === "action") {
866
+ let actionContinuation: ActionContinuation | undefined;
525
867
  try {
526
- const loadedAction = await loadServerAction(directActionId);
527
- actionResult = await loadedAction.apply(null, args);
868
+ const actionOutcome = await withTimeout(
869
+ executeServerAction(
870
+ handlerCtx,
871
+ request,
872
+ env,
873
+ url,
874
+ plan.actionId,
875
+ handleStore,
876
+ ),
877
+ router.timeouts.actionMs,
878
+ "action",
879
+ );
880
+ if (actionOutcome.timedOut) {
881
+ return handleTimeoutResponse(
882
+ request,
883
+ env,
884
+ url,
885
+ "action",
886
+ actionOutcome.durationMs,
887
+ plan.route.routeKey,
888
+ plan.actionId,
889
+ );
890
+ }
891
+ const result = actionOutcome.result;
892
+ // Response means redirect or error boundary — done.
893
+ if (result instanceof Response) return result;
894
+ actionContinuation = result;
528
895
  } catch (error) {
529
896
  callOnError(error, "action", {
530
897
  request,
531
898
  url,
532
899
  env,
533
- actionId: directActionId,
900
+ actionId: plan.actionId,
534
901
  handledByBoundary: false,
535
902
  });
536
- console.error("[RSC] Progressive enhancement action error:", error);
903
+ console.error(`[RSC] Action error:`, error);
904
+ throw error;
537
905
  }
538
- }
539
906
 
540
- // Decode form state for useActionState progressive enhancement
541
- try {
542
- reactFormState = await decodeFormState(actionResult, formData);
543
- } catch (error) {
544
- callOnError(error, "action", {
907
+ // Revalidation render wrapped in route middleware.
908
+ // Actions from client-side navigation include _rsc_partial — preserve
909
+ // the partial flag so the revalidation returns a Flight stream, not HTML.
910
+ // App-switch is already excluded by classifyRequest (would be full-render).
911
+ const isPartialAction = url.searchParams.has("_rsc_partial");
912
+ return executeRenderWithMiddleware(
913
+ plan.route.routeMiddleware,
914
+ plan.negotiated,
915
+ plan.route.routeKey,
916
+ routeReverse,
545
917
  request,
546
- url,
547
918
  env,
548
- handledByBoundary: false,
549
- });
550
- console.error("[RSC] Failed to decode form state:", error);
551
- }
552
-
553
- // Re-render the page and return HTML
554
- const renderRequest = new Request(url.toString(), {
555
- method: "GET",
556
- headers: new Headers({ accept: "text/html" }),
557
- });
558
-
559
- const match = await router.match(renderRequest, env);
560
-
561
- if (match.redirect) {
562
- return new Response(null, {
563
- status: 308,
564
- headers: { Location: match.redirect },
565
- });
919
+ url,
920
+ variables,
921
+ nonce,
922
+ handleStore,
923
+ isPartialAction,
924
+ actionContinuation,
925
+ );
566
926
  }
567
927
 
568
- const root = renderSegments(match.segments, {
569
- rootLayout: router.rootLayout,
570
- });
571
-
572
- const payload: RscPayload = {
573
- root,
574
- metadata: {
575
- pathname: url.pathname,
576
- segments: match.segments,
577
- matched: match.matched,
578
- diff: match.diff,
579
- isPartial: false,
580
- rootLayout: router.rootLayout,
581
- handles: handleStore.stream(),
582
- version,
583
- themeConfig: router.themeConfig,
584
- warmupEnabled: router.warmupEnabled,
585
- initialTheme: requireRequestContext().theme,
586
- },
587
- formState: actionResult,
588
- };
589
-
590
- const rscStream = renderToReadableStream<RscPayload>(payload);
591
- const ssrModule = await loadSSRModule();
592
- const htmlStream = await ssrModule.renderHTML(rscStream, {
593
- formState: reactFormState,
594
- nonce,
595
- });
596
-
597
- return new Response(htmlStream, {
598
- headers: { "content-type": "text/html;charset=utf-8" },
599
- });
600
- }
601
-
602
- // ============================================================================
603
- // SERVER ACTION HANDLER
604
- // ============================================================================
605
- async function handleServerAction(
606
- request: Request,
607
- env: TEnv,
608
- url: URL,
609
- actionId: string,
610
- handleStore: ReturnType<typeof requireRequestContext>["_handleStore"],
611
- ): Promise<Response> {
612
- const temporaryReferences = createTemporaryReferenceSet();
613
-
614
- // Decode action arguments from request body
615
- const contentType = request.headers.get("content-type") || "";
616
- let args: unknown[] = [];
617
- let actionFormData: FormData | undefined;
618
-
619
- try {
620
- const body = contentType.includes("multipart/form-data")
621
- ? await request.formData()
622
- : await request.text();
623
-
624
- if (body instanceof FormData) {
625
- actionFormData = body;
626
- }
627
-
628
- if (hasBodyContent(body)) {
629
- args = await decodeReply(body, { temporaryReferences });
630
- }
631
- } catch (error) {
632
- callOnError(error, "action", {
928
+ // ---- Full render / Partial render (or PE that fell through) ----
929
+ if (plan.mode === "full-render" || plan.mode === "partial-render") {
930
+ const isPartial = plan.mode === "partial-render";
931
+ return executeRenderWithMiddleware(
932
+ plan.route.routeMiddleware,
933
+ plan.negotiated,
934
+ plan.route.routeKey,
935
+ routeReverse,
633
936
  request,
634
- url,
635
937
  env,
636
- actionId,
637
- handledByBoundary: false,
638
- });
639
- throw new Error(`Failed to decode action arguments: ${error}`, {
640
- cause: error,
641
- });
938
+ url,
939
+ variables,
940
+ nonce,
941
+ handleStore,
942
+ isPartial,
943
+ );
642
944
  }
643
945
 
644
- // Execute the server action
645
- let returnValue: { ok: boolean; data: unknown };
646
- let actionStatus = 200;
647
- let loadedAction: Function | undefined;
648
-
649
- try {
650
- loadedAction = await loadServerAction(actionId);
651
- const data = await loadedAction!.apply(null, args);
652
- returnValue = { ok: true, data };
653
- } catch (error) {
654
- returnValue = { ok: false, data: error };
655
- actionStatus = 500;
656
-
657
- // Try to render error boundary
658
- const errorResult = await router.matchError(request, env, error, "route");
659
-
660
- // Report the action error (handledByBoundary indicates if error boundary will render)
661
- callOnError(error, "action", {
946
+ // PE that fell through (handleProgressiveEnhancement returned null)
947
+ // falls back to full render
948
+ if (plan.mode === "pe-render") {
949
+ return executeRenderWithMiddleware(
950
+ plan.route.routeMiddleware,
951
+ false,
952
+ plan.route.routeKey,
953
+ routeReverse,
662
954
  request,
663
- url,
664
955
  env,
665
- actionId,
666
- handledByBoundary: !!errorResult,
667
- });
668
-
669
- if (errorResult) {
670
- setRequestContextParams(errorResult.params);
671
-
672
- const payload: RscPayload = {
673
- root: null,
674
- metadata: {
675
- pathname: url.pathname,
676
- segments: errorResult.segments,
677
- isPartial: true,
678
- matched: errorResult.matched,
679
- diff: errorResult.diff,
680
- isError: true,
681
- handles: handleStore.stream(),
682
- version,
683
- },
684
- returnValue,
685
- };
686
-
687
- const rscStream = renderToReadableStream<RscPayload>(payload, {
688
- temporaryReferences,
689
- });
690
-
691
- return createResponseWithMergedHeaders(rscStream, {
692
- status: actionStatus,
693
- headers: { "content-type": "text/x-component;charset=utf-8" },
694
- });
695
- }
696
- }
697
-
698
- // Revalidate after action
699
- const resolvedActionId =
700
- (loadedAction as { $id?: string; $$id?: string } | undefined)?.$id ??
701
- (loadedAction as { $$id?: string } | undefined)?.$$id ??
702
- actionId;
703
- const actionContext = {
704
- actionId: resolvedActionId,
705
- actionUrl: new URL(request.url),
706
- actionResult: returnValue.data,
707
- formData: actionFormData,
708
- };
709
-
710
- const matchResult = await router.matchPartial(request, env, actionContext);
711
-
712
- if (!matchResult) {
713
- // Fall back to full render
714
- const fullMatch = await router.match(request, env);
715
- setRequestContextParams(fullMatch.params);
716
-
717
- if (fullMatch.redirect) {
718
- return createResponseWithMergedHeaders(null, {
719
- status: 308,
720
- headers: { Location: fullMatch.redirect },
721
- });
722
- }
723
-
724
- const renderStart = performance.now();
725
- const root = renderSegments(fullMatch.segments, {
726
- rootLayout: router.rootLayout,
727
- isAction: true,
728
- });
729
- const renderDuration = performance.now() - renderStart;
730
- const serverTiming = fullMatch.serverTiming
731
- ? `${fullMatch.serverTiming}, rendering;dur=${renderDuration.toFixed(2)}`
732
- : `rendering;dur=${renderDuration.toFixed(2)}`;
733
-
734
- const payload: RscPayload = {
735
- root,
736
- metadata: {
737
- pathname: url.pathname,
738
- segments: fullMatch.segments,
739
- matched: fullMatch.matched,
740
- diff: fullMatch.diff,
741
- handles: handleStore.stream(),
742
- version,
743
- },
744
- returnValue,
745
- };
746
-
747
- const rscStream = renderToReadableStream<RscPayload>(payload, {
748
- temporaryReferences,
749
- });
750
-
751
- const headers: Record<string, string> = {
752
- "content-type": "text/x-component;charset=utf-8",
753
- };
754
- if (serverTiming) {
755
- headers["Server-Timing"] = serverTiming;
756
- }
757
-
758
- return createResponseWithMergedHeaders(rscStream, {
759
- status: actionStatus,
760
- headers,
761
- });
762
- }
763
-
764
- // Return updated segments
765
- setRequestContextParams(matchResult.params);
766
-
767
- const renderStart = performance.now();
768
-
769
- const renderDuration = performance.now() - renderStart;
770
- const serverTiming = matchResult.serverTiming
771
- ? `${matchResult.serverTiming}, rendering;dur=${renderDuration.toFixed(2)}`
772
- : `rendering;dur=${renderDuration.toFixed(2)}`;
773
-
774
- const payload: RscPayload = {
775
- root: null,
776
- metadata: {
777
- pathname: url.pathname,
778
- segments: matchResult.segments,
779
- isPartial: true,
780
- matched: matchResult.matched,
781
- diff: matchResult.diff,
782
- slots: matchResult.slots,
783
- handles: handleStore.stream(),
784
- version,
785
- },
786
- returnValue,
787
- };
788
-
789
- const rscStream = renderToReadableStream<RscPayload>(payload, {
790
- temporaryReferences,
791
- });
792
-
793
- const actionHeaders: Record<string, string> = {
794
- "content-type": "text/x-component;charset=utf-8",
795
- };
796
- if (serverTiming) {
797
- actionHeaders["Server-Timing"] = serverTiming;
956
+ url,
957
+ variables,
958
+ nonce,
959
+ handleStore,
960
+ false,
961
+ );
798
962
  }
799
963
 
800
- return createResponseWithMergedHeaders(rscStream, {
801
- status: actionStatus,
802
- headers: actionHeaders,
803
- });
964
+ // Redirect plan that wasn't handled above (full-page redirect — let
965
+ // the pipeline handle it via match() which returns { redirect: url })
966
+ return executeRenderWithMiddleware(
967
+ plan.route.routeMiddleware,
968
+ false,
969
+ plan.route.routeKey,
970
+ routeReverse,
971
+ request,
972
+ env,
973
+ url,
974
+ variables,
975
+ nonce,
976
+ handleStore,
977
+ false,
978
+ );
804
979
  }
805
980
 
806
- // ============================================================================
807
- // LOADER FETCH HANDLER
808
- // Supports GET (params in query string) and POST/PUT/PATCH/DELETE (JSON body)
809
- // ============================================================================
810
- async function handleLoaderFetch(
981
+ // Shared render execution: wraps handleRscRendering (or revalidateAfterAction)
982
+ // in route middleware and timeout handling. Consolidates the pattern used by
983
+ // action-revalidate, full-render, and partial-render modes.
984
+ async function executeRenderWithMiddleware(
985
+ routeMiddleware: import("../router/middleware-types.js").CollectedMiddleware[],
986
+ negotiated: boolean,
987
+ routeKey: string,
988
+ routeReverse: ReturnType<typeof createReverseFunction>,
811
989
  request: Request,
812
990
  env: TEnv,
813
991
  url: URL,
814
992
  variables: Record<string, any>,
993
+ nonce: string | undefined,
994
+ handleStore: ReturnType<typeof requireRequestContext>["_handleStore"],
995
+ isPartial: boolean,
996
+ actionContinuation?: ActionContinuation,
815
997
  ): Promise<Response> {
816
- const loaderId = url.searchParams.get("_rsc_loader");
998
+ const renderHandler = async (): Promise<Response> => {
999
+ try {
1000
+ let response: Response;
1001
+ if (actionContinuation) {
1002
+ response = await revalidateAfterAction(
1003
+ handlerCtx,
1004
+ request,
1005
+ env,
1006
+ url,
1007
+ handleStore,
1008
+ actionContinuation,
1009
+ );
1010
+ } else {
1011
+ response = await handleRscRendering(
1012
+ handlerCtx,
1013
+ request,
1014
+ env,
1015
+ url,
1016
+ isPartial,
1017
+ handleStore,
1018
+ nonce,
1019
+ );
1020
+ }
1021
+ if (negotiated && !isWebSocketUpgradeResponse(response)) {
1022
+ response.headers.append("Vary", "Accept");
1023
+ }
1024
+ return response;
1025
+ } catch (error) {
1026
+ // Check if middleware/handler returned Response
1027
+ if (error instanceof Response) {
1028
+ // During partial (client-side navigation), a 200 Response from a handler
1029
+ // means the route serves raw content (JSON, text, etc.), not JSX.
1030
+ // Signal the browser to hard-navigate so it renders the raw response.
1031
+ if (isPartial && error.status === 200) {
1032
+ console.warn(
1033
+ `[RSC] Route handler at ${url.pathname} returned a Response during client-side navigation. ` +
1034
+ `Falling back to hard navigation. Use data-external on the <Link> to avoid the extra round-trip.`,
1035
+ );
1036
+ return createResponseWithMergedHeaders(null, {
1037
+ status: 200,
1038
+ headers: {
1039
+ "X-RSC-Reload": stripInternalParams(url).toString(),
1040
+ "content-type": "text/x-component;charset=utf-8",
1041
+ },
1042
+ });
1043
+ }
817
1044
 
818
- if (!loaderId) {
819
- return createResponseWithMergedHeaders("Missing _rsc_loader parameter", {
820
- status: 400,
821
- });
822
- }
1045
+ if (isPartial) {
1046
+ const intercepted = interceptRedirectForPartial(
1047
+ error,
1048
+ createRedirectFlightResponse,
1049
+ );
1050
+ if (intercepted) return intercepted;
1051
+ }
823
1052
 
824
- // Look up loader lazily
825
- const registeredLoader = await getLoaderLazy(loaderId);
826
- if (!registeredLoader) {
827
- return createResponseWithMergedHeaders(
828
- `Loader "${loaderId}" not found in registry`,
829
- { status: 404 },
830
- );
831
- }
1053
+ return error;
1054
+ }
832
1055
 
833
- // Parse params and body based on request method
834
- let loaderParams: Record<string, string> = {};
835
- let loaderBody: unknown = undefined;
836
- const isBodyMethod = request.method !== "GET" && request.method !== "HEAD";
1056
+ // Render 404 page for unmatched routes
1057
+ const isRouteNotFound =
1058
+ error instanceof RouteNotFoundError ||
1059
+ (error instanceof Error && error.name === "RouteNotFoundError");
1060
+ if (isRouteNotFound) {
1061
+ callOnError(error, "routing", {
1062
+ request,
1063
+ url,
1064
+ env,
1065
+ handledByBoundary: true,
1066
+ });
837
1067
 
838
- if (isBodyMethod) {
839
- try {
840
- const contentType = request.headers.get("content-type") || "";
841
- if (contentType.includes("application/json")) {
842
- const jsonBody = (await request.json()) as {
843
- params?: Record<string, string>;
844
- body?: unknown;
1068
+ const notFoundOption = router.notFound;
1069
+ const notFoundComponent =
1070
+ typeof notFoundOption === "function"
1071
+ ? notFoundOption({ pathname: url.pathname })
1072
+ : (notFoundOption ?? createElement("h1", null, "Not Found"));
1073
+
1074
+ const notFoundSegment = {
1075
+ id: "notFound",
1076
+ namespace: "notFound",
1077
+ type: "route" as const,
1078
+ index: 0,
1079
+ component: notFoundComponent,
1080
+ params: {},
845
1081
  };
846
- loaderParams = jsonBody.params ?? {};
847
- loaderBody = jsonBody.body;
848
- }
849
- } catch {
850
- return createResponseWithMergedHeaders("Invalid JSON body", {
851
- status: 400,
852
- });
853
- }
854
- } else {
855
- const loaderParamsJson = url.searchParams.get("_rsc_loader_params");
856
- if (loaderParamsJson) {
857
- try {
858
- loaderParams = JSON.parse(loaderParamsJson);
859
- } catch {
860
- return createResponseWithMergedHeaders(
861
- "Invalid _rsc_loader_params JSON",
862
- { status: 400 },
863
- );
864
- }
865
- }
866
- }
867
-
868
- // Execute the loader with middleware
869
- try {
870
- const { fn, middleware } = registeredLoader;
871
1082
 
872
- return await executeLoaderMiddleware(
873
- middleware,
874
- request,
875
- env,
876
- loaderParams,
877
- variables,
878
- async () => {
879
- const ctx = requireRequestContext();
880
- const loaderCtx: any = {
881
- ...ctx,
882
- params: loaderParams,
883
- body: loaderBody,
1083
+ const payload: RscPayload = {
1084
+ metadata: {
1085
+ pathname: url.pathname,
1086
+ routerId: router.id,
1087
+ basename: router.basename,
1088
+ segments: [notFoundSegment],
1089
+ matched: [],
1090
+ diff: [],
1091
+ isPartial: false,
1092
+ rootLayout: router.rootLayout,
1093
+ handles: handleStore.stream(),
1094
+ version,
1095
+ themeConfig: router.themeConfig,
1096
+ warmupEnabled: router.warmupEnabled,
1097
+ initialTheme: requireRequestContext().theme,
1098
+ },
884
1099
  };
885
1100
 
886
- const result = await fn(loaderCtx);
1101
+ const rscStream = renderToReadableStream(payload, {
1102
+ onError: (error: unknown) => {
1103
+ callOnError(error, "rendering", { request, url, env });
1104
+ },
1105
+ });
887
1106
 
888
- interface LoaderPayload {
889
- loaderResult: unknown;
1107
+ const isRscRequest =
1108
+ isPartial ||
1109
+ (!request.headers.get("accept")?.includes("text/html") &&
1110
+ !url.searchParams.has("__html")) ||
1111
+ url.searchParams.has("__rsc");
1112
+
1113
+ if (isRscRequest) {
1114
+ return createResponseWithMergedHeaders(rscStream, {
1115
+ status: 404,
1116
+ headers: { "content-type": "text/x-component;charset=utf-8" },
1117
+ });
890
1118
  }
891
- const loaderPayload: LoaderPayload = { loaderResult: result };
892
- const rscStream =
893
- renderToReadableStream<LoaderPayload>(loaderPayload);
894
1119
 
895
- return createResponseWithMergedHeaders(rscStream, {
896
- headers: { "content-type": "text/x-component;charset=utf-8" },
1120
+ const [ssrModule, streamMode] = await getSSRSetup(
1121
+ handlerCtx,
1122
+ request,
1123
+ env,
1124
+ url,
1125
+ requireRequestContext()._metricsStore,
1126
+ );
1127
+ const htmlStream = await ssrModule.renderHTML(rscStream, {
1128
+ nonce,
1129
+ streamMode,
897
1130
  });
898
- },
899
- );
900
- } catch (error) {
901
- const err = error instanceof Error ? error : new Error(String(error));
902
- const isDev = process.env.NODE_ENV !== "production";
903
-
904
- console.error("[RSC] Loader error:", error);
905
-
906
- callOnError(error, "loader", {
907
- request,
908
- url,
909
- env,
910
- loaderName: loaderId,
911
- handledByBoundary: false,
912
- });
913
-
914
- const errorPayload = {
915
- loaderResult: null,
916
- loaderError: {
917
- message: isDev ? err.message : "An error occurred",
918
- name: err.name,
919
- },
920
- };
921
- const rscStream = renderToReadableStream(errorPayload);
922
1131
 
923
- return createResponseWithMergedHeaders(rscStream, {
924
- status: 500,
925
- headers: { "content-type": "text/x-component;charset=utf-8" },
926
- });
927
- }
928
- }
929
-
930
- // ============================================================================
931
- // RSC RENDERING HANDLER (Navigation)
932
- // ============================================================================
933
- async function handleRscRendering(
934
- request: Request,
935
- env: TEnv,
936
- url: URL,
937
- isPartial: boolean,
938
- handleStore: ReturnType<typeof requireRequestContext>["_handleStore"],
939
- nonce: string | undefined,
940
- ): Promise<Response> {
941
- let payload: RscPayload;
942
- let serverTiming: string | undefined;
943
-
944
- if (isPartial) {
945
- // Partial render (navigation)
946
- const result = await router.matchPartial(request, env);
947
-
948
- if (!result) {
949
- // Fall back to full render
950
- const match = await router.match(request, env);
951
- setRequestContextParams(match.params);
952
-
953
- if (match.redirect) {
954
- return createResponseWithMergedHeaders(null, {
955
- status: 308,
956
- headers: { Location: match.redirect },
1132
+ return createResponseWithMergedHeaders(htmlStream, {
1133
+ status: 404,
1134
+ headers: { "content-type": "text/html;charset=utf-8" },
957
1135
  });
958
1136
  }
959
1137
 
960
- const renderStart = performance.now();
961
- const root = renderSegments(match.segments, {
962
- rootLayout: router.rootLayout,
963
- });
964
- const renderDuration = performance.now() - renderStart;
965
- serverTiming = match.serverTiming
966
- ? `${match.serverTiming}, rendering;dur=${renderDuration.toFixed(2)}`
967
- : `rendering;dur=${renderDuration.toFixed(2)}`;
968
-
969
- payload = {
970
- root,
971
- metadata: {
972
- pathname: url.pathname,
973
- segments: match.segments,
974
- matched: match.matched,
975
- diff: match.diff,
976
- isPartial: false,
977
- handles: handleStore.stream(),
978
- version,
979
- themeConfig: router.themeConfig,
980
- initialTheme: requireRequestContext().theme,
981
- },
982
- };
983
- } else {
984
- setRequestContextParams(result.params);
985
- serverTiming = result.serverTiming;
986
-
987
- payload = {
988
- root: null,
989
- metadata: {
990
- pathname: url.pathname,
991
- segments: result.segments,
992
- matched: result.matched,
993
- diff: result.diff,
994
- isPartial: true,
995
- slots: result.slots,
996
- handles: handleStore.stream(),
997
- version,
998
- },
999
- };
1000
- }
1001
- } else {
1002
- // Full render (initial page load)
1003
- const match = await router.match(request, env);
1004
- setRequestContextParams(match.params);
1005
-
1006
- if (match.redirect) {
1007
- return createResponseWithMergedHeaders(null, {
1008
- status: 308,
1009
- headers: { Location: match.redirect },
1138
+ // Report unhandled errors
1139
+ callOnError(error, "routing", {
1140
+ request,
1141
+ url,
1142
+ env,
1143
+ handledByBoundary: false,
1010
1144
  });
1145
+ console.error(`[RSC] Error:`, error);
1146
+ throw error;
1011
1147
  }
1148
+ };
1012
1149
 
1013
- // Caching is now handled in router.match() via cache provider in request context
1014
- // match.segments already contains cached or fresh segments as appropriate
1015
-
1016
- const renderStart = performance.now();
1017
- const root = renderSegments(match.segments, {
1018
- rootLayout: router.rootLayout,
1019
- });
1020
- const renderDuration = performance.now() - renderStart;
1021
- serverTiming = match.serverTiming
1022
- ? `${match.serverTiming}, rendering;dur=${renderDuration.toFixed(2)}`
1023
- : `rendering;dur=${renderDuration.toFixed(2)}`;
1024
-
1025
- payload = {
1026
- root,
1027
- metadata: {
1028
- pathname: url.pathname,
1029
- segments: match.segments,
1030
- matched: match.matched,
1031
- diff: match.diff,
1032
- isPartial: false,
1033
- rootLayout: router.rootLayout,
1034
- handles: handleStore.stream(),
1035
- version,
1036
- themeConfig: router.themeConfig,
1037
- initialTheme: requireRequestContext().theme,
1038
- },
1039
- };
1040
- }
1041
-
1042
- // Serialize to RSC stream
1043
- const rscStream = renderToReadableStream<RscPayload>(payload);
1150
+ // Wrap the render path in a renderStartMs timeout
1151
+ const executeRender = async (): Promise<Response> => {
1152
+ if (routeMiddleware.length > 0) {
1153
+ const mwResponse = await executeMiddleware(
1154
+ buildRouteMiddlewareEntries<TEnv>(routeMiddleware),
1155
+ request,
1156
+ env,
1157
+ variables,
1158
+ renderHandler,
1159
+ routeReverse,
1160
+ );
1044
1161
 
1045
- // Determine if this is an RSC request or HTML request
1046
- const isRscRequest =
1047
- (!request.headers.get("accept")?.includes("text/html") &&
1048
- !url.searchParams.has("__html")) ||
1049
- url.searchParams.has("__rsc");
1162
+ if (isPartial || actionContinuation) {
1163
+ const intercepted = interceptRedirectForPartial(
1164
+ mwResponse,
1165
+ createRedirectFlightResponse,
1166
+ );
1167
+ if (intercepted) return intercepted;
1168
+ }
1050
1169
 
1051
- if (isRscRequest) {
1052
- const rscHeaders: Record<string, string> = {
1053
- "content-type": "text/x-component;charset=utf-8",
1054
- vary: "accept",
1055
- };
1056
- if (serverTiming) {
1057
- rscHeaders["Server-Timing"] = serverTiming;
1170
+ return finalizeResponse(mwResponse);
1058
1171
  }
1059
- return createResponseWithMergedHeaders(rscStream, {
1060
- headers: rscHeaders,
1061
- });
1062
- }
1063
-
1064
- // Delegate to SSR for HTML response
1065
- const ssrModule = await loadSSRModule();
1066
- const htmlStream = await ssrModule.renderHTML(rscStream, { nonce });
1067
1172
 
1068
- const htmlHeaders: Record<string, string> = {
1069
- "content-type": "text/html;charset=utf-8",
1173
+ return renderHandler();
1070
1174
  };
1071
- if (serverTiming) {
1072
- htmlHeaders["Server-Timing"] = serverTiming;
1073
- }
1074
1175
 
1075
- return createResponseWithMergedHeaders(htmlStream, {
1076
- headers: htmlHeaders,
1077
- });
1176
+ const renderOutcome = await withTimeout(
1177
+ executeRender(),
1178
+ router.timeouts.renderStartMs,
1179
+ "render-start",
1180
+ );
1181
+ if (renderOutcome.timedOut) {
1182
+ return handleTimeoutResponse(
1183
+ request,
1184
+ env,
1185
+ url,
1186
+ "render-start",
1187
+ renderOutcome.durationMs,
1188
+ routeKey,
1189
+ );
1190
+ }
1191
+ return renderOutcome.result;
1078
1192
  }
1079
1193
  }