@rangojs/router 0.0.0-experimental.debug-cache-fix → 0.0.0-experimental.df410dd5

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 (1077) hide show
  1. package/README.md +196 -43
  2. package/dist/__internal.d.ts +83 -0
  3. package/dist/__internal.d.ts.map +1 -0
  4. package/dist/__internal.js +19 -0
  5. package/dist/__internal.js.map +1 -0
  6. package/dist/__mocks__/version.d.ts +7 -0
  7. package/dist/__mocks__/version.d.ts.map +1 -0
  8. package/dist/__mocks__/version.js +7 -0
  9. package/dist/__mocks__/version.js.map +1 -0
  10. package/dist/__tests__/client-href.test.d.ts +2 -0
  11. package/dist/__tests__/client-href.test.d.ts.map +1 -0
  12. package/dist/__tests__/client-href.test.js +74 -0
  13. package/dist/__tests__/client-href.test.js.map +1 -0
  14. package/dist/__tests__/component-utils.test.d.ts +2 -0
  15. package/dist/__tests__/component-utils.test.d.ts.map +1 -0
  16. package/dist/__tests__/component-utils.test.js +51 -0
  17. package/dist/__tests__/component-utils.test.js.map +1 -0
  18. package/dist/__tests__/event-controller.test.d.ts +2 -0
  19. package/dist/__tests__/event-controller.test.d.ts.map +1 -0
  20. package/dist/__tests__/event-controller.test.js +538 -0
  21. package/dist/__tests__/event-controller.test.js.map +1 -0
  22. package/dist/__tests__/helpers/route-tree.d.ts +118 -0
  23. package/dist/__tests__/helpers/route-tree.d.ts.map +1 -0
  24. package/dist/__tests__/helpers/route-tree.js +374 -0
  25. package/dist/__tests__/helpers/route-tree.js.map +1 -0
  26. package/dist/__tests__/match-result.test.d.ts +2 -0
  27. package/dist/__tests__/match-result.test.d.ts.map +1 -0
  28. package/dist/__tests__/match-result.test.js +154 -0
  29. package/dist/__tests__/match-result.test.js.map +1 -0
  30. package/dist/__tests__/navigation-store.test.d.ts +2 -0
  31. package/dist/__tests__/navigation-store.test.d.ts.map +1 -0
  32. package/dist/__tests__/navigation-store.test.js +440 -0
  33. package/dist/__tests__/navigation-store.test.js.map +1 -0
  34. package/dist/__tests__/partial-update.test.d.ts +2 -0
  35. package/dist/__tests__/partial-update.test.d.ts.map +1 -0
  36. package/dist/__tests__/partial-update.test.js +1009 -0
  37. package/dist/__tests__/partial-update.test.js.map +1 -0
  38. package/dist/__tests__/reverse-types.test.d.ts +8 -0
  39. package/dist/__tests__/reverse-types.test.d.ts.map +1 -0
  40. package/dist/__tests__/reverse-types.test.js +656 -0
  41. package/dist/__tests__/reverse-types.test.js.map +1 -0
  42. package/dist/__tests__/route-definition.test.d.ts +2 -0
  43. package/dist/__tests__/route-definition.test.d.ts.map +1 -0
  44. package/dist/__tests__/route-definition.test.js +55 -0
  45. package/dist/__tests__/route-definition.test.js.map +1 -0
  46. package/dist/__tests__/router-helpers.test.d.ts +2 -0
  47. package/dist/__tests__/router-helpers.test.d.ts.map +1 -0
  48. package/dist/__tests__/router-helpers.test.js +377 -0
  49. package/dist/__tests__/router-helpers.test.js.map +1 -0
  50. package/dist/__tests__/router-integration-2.test.d.ts +2 -0
  51. package/dist/__tests__/router-integration-2.test.d.ts.map +1 -0
  52. package/dist/__tests__/router-integration-2.test.js +426 -0
  53. package/dist/__tests__/router-integration-2.test.js.map +1 -0
  54. package/dist/__tests__/router-integration.test.d.ts +2 -0
  55. package/dist/__tests__/router-integration.test.d.ts.map +1 -0
  56. package/dist/__tests__/router-integration.test.js +1051 -0
  57. package/dist/__tests__/router-integration.test.js.map +1 -0
  58. package/dist/__tests__/search-params.test.d.ts +5 -0
  59. package/dist/__tests__/search-params.test.d.ts.map +1 -0
  60. package/dist/__tests__/search-params.test.js +306 -0
  61. package/dist/__tests__/search-params.test.js.map +1 -0
  62. package/dist/__tests__/segment-system.test.d.ts +2 -0
  63. package/dist/__tests__/segment-system.test.d.ts.map +1 -0
  64. package/dist/__tests__/segment-system.test.js +627 -0
  65. package/dist/__tests__/segment-system.test.js.map +1 -0
  66. package/dist/__tests__/static-handler-types.test.d.ts +8 -0
  67. package/dist/__tests__/static-handler-types.test.d.ts.map +1 -0
  68. package/dist/__tests__/static-handler-types.test.js +63 -0
  69. package/dist/__tests__/static-handler-types.test.js.map +1 -0
  70. package/dist/__tests__/urls.test.d.ts +2 -0
  71. package/dist/__tests__/urls.test.d.ts.map +1 -0
  72. package/dist/__tests__/urls.test.js +421 -0
  73. package/dist/__tests__/urls.test.js.map +1 -0
  74. package/dist/__tests__/use-mount.test.d.ts +2 -0
  75. package/dist/__tests__/use-mount.test.d.ts.map +1 -0
  76. package/dist/__tests__/use-mount.test.js +35 -0
  77. package/dist/__tests__/use-mount.test.js.map +1 -0
  78. package/dist/bin/rango.d.ts +2 -0
  79. package/dist/bin/rango.d.ts.map +1 -0
  80. package/dist/bin/rango.js +269 -96
  81. package/dist/bin/rango.js.map +1 -0
  82. package/dist/browser/event-controller.d.ts +191 -0
  83. package/dist/browser/event-controller.d.ts.map +1 -0
  84. package/dist/browser/event-controller.js +559 -0
  85. package/dist/browser/event-controller.js.map +1 -0
  86. package/dist/browser/index.d.ts +2 -0
  87. package/dist/browser/index.d.ts.map +1 -0
  88. package/dist/browser/index.js +14 -0
  89. package/dist/browser/index.js.map +1 -0
  90. package/dist/browser/link-interceptor.d.ts +38 -0
  91. package/dist/browser/link-interceptor.d.ts.map +1 -0
  92. package/dist/browser/link-interceptor.js +99 -0
  93. package/dist/browser/link-interceptor.js.map +1 -0
  94. package/dist/browser/logging.d.ts +10 -0
  95. package/dist/browser/logging.d.ts.map +1 -0
  96. package/dist/browser/logging.js +29 -0
  97. package/dist/browser/logging.js.map +1 -0
  98. package/dist/browser/lru-cache.d.ts +17 -0
  99. package/dist/browser/lru-cache.d.ts.map +1 -0
  100. package/dist/browser/lru-cache.js +50 -0
  101. package/dist/browser/lru-cache.js.map +1 -0
  102. package/dist/browser/merge-segment-loaders.d.ts +39 -0
  103. package/dist/browser/merge-segment-loaders.d.ts.map +1 -0
  104. package/dist/browser/merge-segment-loaders.js +102 -0
  105. package/dist/browser/merge-segment-loaders.js.map +1 -0
  106. package/dist/browser/navigation-bridge.d.ts +102 -0
  107. package/dist/browser/navigation-bridge.d.ts.map +1 -0
  108. package/dist/browser/navigation-bridge.js +708 -0
  109. package/dist/browser/navigation-bridge.js.map +1 -0
  110. package/dist/browser/navigation-client.d.ts +25 -0
  111. package/dist/browser/navigation-client.d.ts.map +1 -0
  112. package/dist/browser/navigation-client.js +157 -0
  113. package/dist/browser/navigation-client.js.map +1 -0
  114. package/dist/browser/navigation-store.d.ts +101 -0
  115. package/dist/browser/navigation-store.d.ts.map +1 -0
  116. package/dist/browser/navigation-store.js +625 -0
  117. package/dist/browser/navigation-store.js.map +1 -0
  118. package/dist/browser/partial-update.d.ts +75 -0
  119. package/dist/browser/partial-update.d.ts.map +1 -0
  120. package/dist/browser/partial-update.js +426 -0
  121. package/dist/browser/partial-update.js.map +1 -0
  122. package/dist/browser/react/Link.d.ts +86 -0
  123. package/dist/browser/react/Link.d.ts.map +1 -0
  124. package/dist/browser/react/Link.js +128 -0
  125. package/dist/browser/react/Link.js.map +1 -0
  126. package/dist/browser/react/NavigationProvider.d.ts +63 -0
  127. package/dist/browser/react/NavigationProvider.d.ts.map +1 -0
  128. package/dist/browser/react/NavigationProvider.js +216 -0
  129. package/dist/browser/react/NavigationProvider.js.map +1 -0
  130. package/dist/browser/react/ScrollRestoration.d.ts +75 -0
  131. package/dist/browser/react/ScrollRestoration.d.ts.map +1 -0
  132. package/dist/browser/react/ScrollRestoration.js +57 -0
  133. package/dist/browser/react/ScrollRestoration.js.map +1 -0
  134. package/dist/browser/react/context.d.ts +46 -0
  135. package/dist/browser/react/context.d.ts.map +1 -0
  136. package/dist/browser/react/context.js +10 -0
  137. package/dist/browser/react/context.js.map +1 -0
  138. package/dist/browser/react/index.d.ts +11 -0
  139. package/dist/browser/react/index.d.ts.map +1 -0
  140. package/dist/browser/react/index.js +22 -0
  141. package/dist/browser/react/index.js.map +1 -0
  142. package/dist/browser/react/location-state-shared.d.ts +63 -0
  143. package/dist/browser/react/location-state-shared.d.ts.map +1 -0
  144. package/dist/browser/react/location-state-shared.js +81 -0
  145. package/dist/browser/react/location-state-shared.js.map +1 -0
  146. package/dist/browser/react/location-state.d.ts +23 -0
  147. package/dist/browser/react/location-state.d.ts.map +1 -0
  148. package/dist/browser/react/location-state.js +29 -0
  149. package/dist/browser/react/location-state.js.map +1 -0
  150. package/dist/browser/react/mount-context.d.ts +24 -0
  151. package/dist/browser/react/mount-context.d.ts.map +1 -0
  152. package/dist/browser/react/mount-context.js +24 -0
  153. package/dist/browser/react/mount-context.js.map +1 -0
  154. package/dist/browser/react/use-action.d.ts +64 -0
  155. package/dist/browser/react/use-action.d.ts.map +1 -0
  156. package/dist/browser/react/use-action.js +134 -0
  157. package/dist/browser/react/use-action.js.map +1 -0
  158. package/dist/browser/react/use-client-cache.d.ts +41 -0
  159. package/dist/browser/react/use-client-cache.d.ts.map +1 -0
  160. package/dist/browser/react/use-client-cache.js +39 -0
  161. package/dist/browser/react/use-client-cache.js.map +1 -0
  162. package/dist/browser/react/use-handle.d.ts +31 -0
  163. package/dist/browser/react/use-handle.d.ts.map +1 -0
  164. package/dist/browser/react/use-handle.js +144 -0
  165. package/dist/browser/react/use-handle.js.map +1 -0
  166. package/dist/browser/react/use-href.d.ts +33 -0
  167. package/dist/browser/react/use-href.d.ts.map +1 -0
  168. package/dist/browser/react/use-href.js +39 -0
  169. package/dist/browser/react/use-href.js.map +1 -0
  170. package/dist/browser/react/use-link-status.d.ts +37 -0
  171. package/dist/browser/react/use-link-status.d.ts.map +1 -0
  172. package/dist/browser/react/use-link-status.js +99 -0
  173. package/dist/browser/react/use-link-status.js.map +1 -0
  174. package/dist/browser/react/use-mount.d.ts +25 -0
  175. package/dist/browser/react/use-mount.d.ts.map +1 -0
  176. package/dist/browser/react/use-mount.js +30 -0
  177. package/dist/browser/react/use-mount.js.map +1 -0
  178. package/dist/browser/react/use-navigation.d.ts +27 -0
  179. package/dist/browser/react/use-navigation.d.ts.map +1 -0
  180. package/dist/browser/react/use-navigation.js +87 -0
  181. package/dist/browser/react/use-navigation.js.map +1 -0
  182. package/dist/browser/react/use-segments.d.ts +38 -0
  183. package/dist/browser/react/use-segments.d.ts.map +1 -0
  184. package/dist/browser/react/use-segments.js +130 -0
  185. package/dist/browser/react/use-segments.js.map +1 -0
  186. package/dist/browser/request-controller.d.ts +26 -0
  187. package/dist/browser/request-controller.d.ts.map +1 -0
  188. package/dist/browser/request-controller.js +147 -0
  189. package/dist/browser/request-controller.js.map +1 -0
  190. package/dist/browser/rsc-router.d.ts +129 -0
  191. package/dist/browser/rsc-router.d.ts.map +1 -0
  192. package/dist/browser/rsc-router.js +195 -0
  193. package/dist/browser/rsc-router.js.map +1 -0
  194. package/dist/browser/scroll-restoration.d.ts +93 -0
  195. package/dist/browser/scroll-restoration.d.ts.map +1 -0
  196. package/dist/browser/scroll-restoration.js +321 -0
  197. package/dist/browser/scroll-restoration.js.map +1 -0
  198. package/dist/browser/segment-structure-assert.d.ts +17 -0
  199. package/dist/browser/segment-structure-assert.d.ts.map +1 -0
  200. package/dist/browser/segment-structure-assert.js +59 -0
  201. package/dist/browser/segment-structure-assert.js.map +1 -0
  202. package/dist/browser/server-action-bridge.d.ts +26 -0
  203. package/dist/browser/server-action-bridge.d.ts.map +1 -0
  204. package/dist/browser/server-action-bridge.js +668 -0
  205. package/dist/browser/server-action-bridge.js.map +1 -0
  206. package/dist/browser/shallow.d.ts +12 -0
  207. package/dist/browser/shallow.d.ts.map +1 -0
  208. package/dist/browser/shallow.js +34 -0
  209. package/dist/browser/shallow.js.map +1 -0
  210. package/dist/browser/types.d.ts +369 -0
  211. package/dist/browser/types.d.ts.map +1 -0
  212. package/dist/browser/types.js +2 -0
  213. package/dist/browser/types.js.map +1 -0
  214. package/dist/build/__tests__/generate-cli.test.d.ts +2 -0
  215. package/dist/build/__tests__/generate-cli.test.d.ts.map +1 -0
  216. package/dist/build/__tests__/generate-cli.test.js +237 -0
  217. package/dist/build/__tests__/generate-cli.test.js.map +1 -0
  218. package/dist/build/__tests__/generate-manifest.test.d.ts +2 -0
  219. package/dist/build/__tests__/generate-manifest.test.d.ts.map +1 -0
  220. package/dist/build/__tests__/generate-manifest.test.js +119 -0
  221. package/dist/build/__tests__/generate-manifest.test.js.map +1 -0
  222. package/dist/build/__tests__/generate-route-types.test.d.ts +2 -0
  223. package/dist/build/__tests__/generate-route-types.test.d.ts.map +1 -0
  224. package/dist/build/__tests__/generate-route-types.test.js +620 -0
  225. package/dist/build/__tests__/generate-route-types.test.js.map +1 -0
  226. package/dist/build/__tests__/per-router-manifest.test.d.ts +2 -0
  227. package/dist/build/__tests__/per-router-manifest.test.d.ts.map +1 -0
  228. package/dist/build/__tests__/per-router-manifest.test.js +308 -0
  229. package/dist/build/__tests__/per-router-manifest.test.js.map +1 -0
  230. package/dist/build/generate-manifest.d.ts +81 -0
  231. package/dist/build/generate-manifest.d.ts.map +1 -0
  232. package/dist/build/generate-manifest.js +276 -0
  233. package/dist/build/generate-manifest.js.map +1 -0
  234. package/dist/build/generate-route-types.d.ts +115 -0
  235. package/dist/build/generate-route-types.d.ts.map +1 -0
  236. package/dist/build/generate-route-types.js +740 -0
  237. package/dist/build/generate-route-types.js.map +1 -0
  238. package/dist/build/index.d.ts +21 -0
  239. package/dist/build/index.d.ts.map +1 -0
  240. package/dist/build/index.js +21 -0
  241. package/dist/build/index.js.map +1 -0
  242. package/dist/build/route-trie.d.ts +71 -0
  243. package/dist/build/route-trie.d.ts.map +1 -0
  244. package/dist/build/route-trie.js +175 -0
  245. package/dist/build/route-trie.js.map +1 -0
  246. package/dist/cache/__tests__/cache-scope.test.d.ts +2 -0
  247. package/dist/cache/__tests__/cache-scope.test.d.ts.map +1 -0
  248. package/dist/cache/__tests__/cache-scope.test.js +208 -0
  249. package/dist/cache/__tests__/cache-scope.test.js.map +1 -0
  250. package/dist/cache/__tests__/document-cache.test.d.ts +2 -0
  251. package/dist/cache/__tests__/document-cache.test.d.ts.map +1 -0
  252. package/dist/cache/__tests__/document-cache.test.js +345 -0
  253. package/dist/cache/__tests__/document-cache.test.js.map +1 -0
  254. package/dist/cache/__tests__/memory-segment-store.test.d.ts +2 -0
  255. package/dist/cache/__tests__/memory-segment-store.test.d.ts.map +1 -0
  256. package/dist/cache/__tests__/memory-segment-store.test.js +425 -0
  257. package/dist/cache/__tests__/memory-segment-store.test.js.map +1 -0
  258. package/dist/cache/__tests__/memory-store.test.d.ts +2 -0
  259. package/dist/cache/__tests__/memory-store.test.d.ts.map +1 -0
  260. package/dist/cache/__tests__/memory-store.test.js +367 -0
  261. package/dist/cache/__tests__/memory-store.test.js.map +1 -0
  262. package/dist/cache/cache-scope.d.ts +102 -0
  263. package/dist/cache/cache-scope.d.ts.map +1 -0
  264. package/dist/cache/cache-scope.js +440 -0
  265. package/dist/cache/cache-scope.js.map +1 -0
  266. package/dist/cache/cf/__tests__/cf-cache-store.test.d.ts +2 -0
  267. package/dist/cache/cf/__tests__/cf-cache-store.test.d.ts.map +1 -0
  268. package/dist/cache/cf/__tests__/cf-cache-store.test.js +330 -0
  269. package/dist/cache/cf/__tests__/cf-cache-store.test.js.map +1 -0
  270. package/dist/cache/cf/cf-cache-store.d.ts +165 -0
  271. package/dist/cache/cf/cf-cache-store.d.ts.map +1 -0
  272. package/dist/cache/cf/cf-cache-store.js +242 -0
  273. package/dist/cache/cf/cf-cache-store.js.map +1 -0
  274. package/dist/cache/cf/index.d.ts +14 -0
  275. package/dist/cache/cf/index.d.ts.map +1 -0
  276. package/dist/cache/cf/index.js +17 -0
  277. package/dist/cache/cf/index.js.map +1 -0
  278. package/dist/cache/document-cache.d.ts +64 -0
  279. package/dist/cache/document-cache.d.ts.map +1 -0
  280. package/dist/cache/document-cache.js +228 -0
  281. package/dist/cache/document-cache.js.map +1 -0
  282. package/dist/cache/index.d.ts +19 -0
  283. package/dist/cache/index.d.ts.map +1 -0
  284. package/dist/cache/index.js +21 -0
  285. package/dist/cache/index.js.map +1 -0
  286. package/dist/cache/memory-segment-store.d.ts +110 -0
  287. package/dist/cache/memory-segment-store.d.ts.map +1 -0
  288. package/dist/cache/memory-segment-store.js +117 -0
  289. package/dist/cache/memory-segment-store.js.map +1 -0
  290. package/dist/cache/memory-store.d.ts +41 -0
  291. package/dist/cache/memory-store.d.ts.map +1 -0
  292. package/dist/cache/memory-store.js +191 -0
  293. package/dist/cache/memory-store.js.map +1 -0
  294. package/dist/cache/types.d.ts +317 -0
  295. package/dist/cache/types.d.ts.map +1 -0
  296. package/dist/cache/types.js +12 -0
  297. package/dist/cache/types.js.map +1 -0
  298. package/dist/client.d.ts +248 -0
  299. package/dist/client.d.ts.map +1 -0
  300. package/dist/client.js +367 -0
  301. package/dist/client.js.map +1 -0
  302. package/dist/client.rsc.d.ts +26 -0
  303. package/dist/client.rsc.d.ts.map +1 -0
  304. package/dist/client.rsc.js +46 -0
  305. package/dist/client.rsc.js.map +1 -0
  306. package/dist/component-utils.d.ts +36 -0
  307. package/dist/component-utils.d.ts.map +1 -0
  308. package/dist/component-utils.js +61 -0
  309. package/dist/component-utils.js.map +1 -0
  310. package/dist/components/DefaultDocument.d.ts +13 -0
  311. package/dist/components/DefaultDocument.d.ts.map +1 -0
  312. package/dist/components/DefaultDocument.js +15 -0
  313. package/dist/components/DefaultDocument.js.map +1 -0
  314. package/dist/debug.d.ts +58 -0
  315. package/dist/debug.d.ts.map +1 -0
  316. package/dist/debug.js +157 -0
  317. package/dist/debug.js.map +1 -0
  318. package/dist/default-error-boundary.d.ts +11 -0
  319. package/dist/default-error-boundary.d.ts.map +1 -0
  320. package/dist/default-error-boundary.js +45 -0
  321. package/dist/default-error-boundary.js.map +1 -0
  322. package/dist/deps/browser.d.ts +2 -0
  323. package/dist/deps/browser.d.ts.map +1 -0
  324. package/dist/deps/browser.js +3 -0
  325. package/dist/deps/browser.js.map +1 -0
  326. package/dist/deps/html-stream-client.d.ts +2 -0
  327. package/dist/deps/html-stream-client.d.ts.map +1 -0
  328. package/dist/deps/html-stream-client.js +3 -0
  329. package/dist/deps/html-stream-client.js.map +1 -0
  330. package/dist/deps/html-stream-server.d.ts +2 -0
  331. package/dist/deps/html-stream-server.d.ts.map +1 -0
  332. package/dist/deps/html-stream-server.js +3 -0
  333. package/dist/deps/html-stream-server.js.map +1 -0
  334. package/dist/deps/rsc.d.ts +2 -0
  335. package/dist/deps/rsc.d.ts.map +1 -0
  336. package/dist/deps/rsc.js +4 -0
  337. package/dist/deps/rsc.js.map +1 -0
  338. package/dist/deps/ssr.d.ts +2 -0
  339. package/dist/deps/ssr.d.ts.map +1 -0
  340. package/dist/deps/ssr.js +3 -0
  341. package/dist/deps/ssr.js.map +1 -0
  342. package/dist/errors.d.ts +174 -0
  343. package/dist/errors.d.ts.map +1 -0
  344. package/dist/errors.js +241 -0
  345. package/dist/errors.js.map +1 -0
  346. package/dist/handle.d.ts +78 -0
  347. package/dist/handle.d.ts.map +1 -0
  348. package/dist/handle.js +82 -0
  349. package/dist/handle.js.map +1 -0
  350. package/dist/handles/MetaTags.d.ts +14 -0
  351. package/dist/handles/MetaTags.d.ts.map +1 -0
  352. package/dist/handles/MetaTags.js +136 -0
  353. package/dist/handles/MetaTags.js.map +1 -0
  354. package/dist/handles/index.d.ts +6 -0
  355. package/dist/handles/index.d.ts.map +1 -0
  356. package/dist/handles/index.js +6 -0
  357. package/dist/handles/index.js.map +1 -0
  358. package/dist/handles/meta.d.ts +39 -0
  359. package/dist/handles/meta.d.ts.map +1 -0
  360. package/dist/handles/meta.js +202 -0
  361. package/dist/handles/meta.js.map +1 -0
  362. package/dist/host/__tests__/errors.test.d.ts +2 -0
  363. package/dist/host/__tests__/errors.test.d.ts.map +1 -0
  364. package/dist/host/__tests__/errors.test.js +76 -0
  365. package/dist/host/__tests__/errors.test.js.map +1 -0
  366. package/dist/host/__tests__/pattern-comprehensive.test.d.ts +2 -0
  367. package/dist/host/__tests__/pattern-comprehensive.test.d.ts.map +1 -0
  368. package/dist/host/__tests__/pattern-comprehensive.test.js +732 -0
  369. package/dist/host/__tests__/pattern-comprehensive.test.js.map +1 -0
  370. package/dist/host/__tests__/pattern-matcher.test.d.ts +2 -0
  371. package/dist/host/__tests__/pattern-matcher.test.d.ts.map +1 -0
  372. package/dist/host/__tests__/pattern-matcher.test.js +251 -0
  373. package/dist/host/__tests__/pattern-matcher.test.js.map +1 -0
  374. package/dist/host/__tests__/router.test.d.ts +2 -0
  375. package/dist/host/__tests__/router.test.d.ts.map +1 -0
  376. package/dist/host/__tests__/router.test.js +241 -0
  377. package/dist/host/__tests__/router.test.js.map +1 -0
  378. package/dist/host/__tests__/testing.test.d.ts +2 -0
  379. package/dist/host/__tests__/testing.test.d.ts.map +1 -0
  380. package/dist/host/__tests__/testing.test.js +64 -0
  381. package/dist/host/__tests__/testing.test.js.map +1 -0
  382. package/dist/host/__tests__/utils.test.d.ts +2 -0
  383. package/dist/host/__tests__/utils.test.d.ts.map +1 -0
  384. package/dist/host/__tests__/utils.test.js +29 -0
  385. package/dist/host/__tests__/utils.test.js.map +1 -0
  386. package/dist/host/cookie-handler.d.ts +34 -0
  387. package/dist/host/cookie-handler.d.ts.map +1 -0
  388. package/dist/host/cookie-handler.js +124 -0
  389. package/dist/host/cookie-handler.js.map +1 -0
  390. package/dist/host/errors.d.ts +56 -0
  391. package/dist/host/errors.d.ts.map +1 -0
  392. package/dist/host/errors.js +79 -0
  393. package/dist/host/errors.js.map +1 -0
  394. package/dist/host/index.d.ts +29 -0
  395. package/dist/host/index.d.ts.map +1 -0
  396. package/dist/host/index.js +32 -0
  397. package/dist/host/index.js.map +1 -0
  398. package/dist/host/pattern-matcher.d.ts +36 -0
  399. package/dist/host/pattern-matcher.d.ts.map +1 -0
  400. package/dist/host/pattern-matcher.js +172 -0
  401. package/dist/host/pattern-matcher.js.map +1 -0
  402. package/dist/host/router.d.ts +26 -0
  403. package/dist/host/router.d.ts.map +1 -0
  404. package/dist/host/router.js +218 -0
  405. package/dist/host/router.js.map +1 -0
  406. package/dist/host/testing.d.ts +36 -0
  407. package/dist/host/testing.d.ts.map +1 -0
  408. package/dist/host/testing.js +55 -0
  409. package/dist/host/testing.js.map +1 -0
  410. package/dist/host/types.d.ts +115 -0
  411. package/dist/host/types.d.ts.map +1 -0
  412. package/dist/host/types.js +7 -0
  413. package/dist/host/types.js.map +1 -0
  414. package/dist/host/utils.d.ts +21 -0
  415. package/dist/host/utils.d.ts.map +1 -0
  416. package/dist/host/utils.js +23 -0
  417. package/dist/host/utils.js.map +1 -0
  418. package/dist/href-client.d.ts +131 -0
  419. package/dist/href-client.d.ts.map +1 -0
  420. package/dist/href-client.js +64 -0
  421. package/dist/href-client.js.map +1 -0
  422. package/dist/href-context.d.ts +29 -0
  423. package/dist/href-context.d.ts.map +1 -0
  424. package/dist/href-context.js +21 -0
  425. package/dist/href-context.js.map +1 -0
  426. package/dist/index.d.ts +73 -0
  427. package/dist/index.d.ts.map +1 -0
  428. package/dist/index.js +91 -0
  429. package/dist/index.js.map +1 -0
  430. package/dist/index.rsc.d.ts +32 -0
  431. package/dist/index.rsc.d.ts.map +1 -0
  432. package/dist/index.rsc.js +40 -0
  433. package/dist/index.rsc.js.map +1 -0
  434. package/dist/internal-debug.d.ts +2 -0
  435. package/dist/internal-debug.d.ts.map +1 -0
  436. package/dist/internal-debug.js +5 -0
  437. package/dist/internal-debug.js.map +1 -0
  438. package/dist/loader.d.ts +14 -0
  439. package/dist/loader.d.ts.map +1 -0
  440. package/dist/loader.js +20 -0
  441. package/dist/loader.js.map +1 -0
  442. package/dist/loader.rsc.d.ts +19 -0
  443. package/dist/loader.rsc.d.ts.map +1 -0
  444. package/dist/loader.rsc.js +99 -0
  445. package/dist/loader.rsc.js.map +1 -0
  446. package/dist/network-error-thrower.d.ts +17 -0
  447. package/dist/network-error-thrower.d.ts.map +1 -0
  448. package/dist/network-error-thrower.js +14 -0
  449. package/dist/network-error-thrower.js.map +1 -0
  450. package/dist/outlet-context.d.ts +13 -0
  451. package/dist/outlet-context.d.ts.map +1 -0
  452. package/dist/outlet-context.js +3 -0
  453. package/dist/outlet-context.js.map +1 -0
  454. package/dist/prerender/__tests__/param-hash.test.d.ts +2 -0
  455. package/dist/prerender/__tests__/param-hash.test.d.ts.map +1 -0
  456. package/dist/prerender/__tests__/param-hash.test.js +148 -0
  457. package/dist/prerender/__tests__/param-hash.test.js.map +1 -0
  458. package/dist/prerender/param-hash.d.ts +16 -0
  459. package/dist/prerender/param-hash.d.ts.map +1 -0
  460. package/dist/prerender/param-hash.js +36 -0
  461. package/dist/prerender/param-hash.js.map +1 -0
  462. package/dist/prerender/store.d.ts +38 -0
  463. package/dist/prerender/store.d.ts.map +1 -0
  464. package/dist/prerender/store.js +61 -0
  465. package/dist/prerender/store.js.map +1 -0
  466. package/dist/prerender.d.ts +66 -0
  467. package/dist/prerender.d.ts.map +1 -0
  468. package/dist/prerender.js +57 -0
  469. package/dist/prerender.js.map +1 -0
  470. package/dist/reverse.d.ts +196 -0
  471. package/dist/reverse.d.ts.map +1 -0
  472. package/dist/reverse.js +78 -0
  473. package/dist/reverse.js.map +1 -0
  474. package/dist/root-error-boundary.d.ts +33 -0
  475. package/dist/root-error-boundary.d.ts.map +1 -0
  476. package/dist/root-error-boundary.js +165 -0
  477. package/dist/root-error-boundary.js.map +1 -0
  478. package/dist/route-content-wrapper.d.ts +46 -0
  479. package/dist/route-content-wrapper.d.ts.map +1 -0
  480. package/dist/route-content-wrapper.js +77 -0
  481. package/dist/route-content-wrapper.js.map +1 -0
  482. package/dist/route-definition.d.ts +421 -0
  483. package/dist/route-definition.d.ts.map +1 -0
  484. package/dist/route-definition.js +868 -0
  485. package/dist/route-definition.js.map +1 -0
  486. package/dist/route-map-builder.d.ts +155 -0
  487. package/dist/route-map-builder.d.ts.map +1 -0
  488. package/dist/route-map-builder.js +237 -0
  489. package/dist/route-map-builder.js.map +1 -0
  490. package/dist/route-types.d.ts +165 -0
  491. package/dist/route-types.d.ts.map +1 -0
  492. package/dist/route-types.js +7 -0
  493. package/dist/route-types.js.map +1 -0
  494. package/dist/router/__tests__/handler-context.test.d.ts +2 -0
  495. package/dist/router/__tests__/handler-context.test.d.ts.map +1 -0
  496. package/dist/router/__tests__/handler-context.test.js +65 -0
  497. package/dist/router/__tests__/handler-context.test.js.map +1 -0
  498. package/dist/router/__tests__/loader-cycle-detection.test.d.ts +2 -0
  499. package/dist/router/__tests__/loader-cycle-detection.test.d.ts.map +1 -0
  500. package/dist/router/__tests__/loader-cycle-detection.test.js +221 -0
  501. package/dist/router/__tests__/loader-cycle-detection.test.js.map +1 -0
  502. package/dist/router/__tests__/match-context.test.d.ts +2 -0
  503. package/dist/router/__tests__/match-context.test.d.ts.map +1 -0
  504. package/dist/router/__tests__/match-context.test.js +92 -0
  505. package/dist/router/__tests__/match-context.test.js.map +1 -0
  506. package/dist/router/__tests__/match-pipelines.test.d.ts +2 -0
  507. package/dist/router/__tests__/match-pipelines.test.d.ts.map +1 -0
  508. package/dist/router/__tests__/match-pipelines.test.js +417 -0
  509. package/dist/router/__tests__/match-pipelines.test.js.map +1 -0
  510. package/dist/router/__tests__/match-result.test.d.ts +2 -0
  511. package/dist/router/__tests__/match-result.test.d.ts.map +1 -0
  512. package/dist/router/__tests__/match-result.test.js +457 -0
  513. package/dist/router/__tests__/match-result.test.js.map +1 -0
  514. package/dist/router/__tests__/on-error.test.d.ts +2 -0
  515. package/dist/router/__tests__/on-error.test.d.ts.map +1 -0
  516. package/dist/router/__tests__/on-error.test.js +678 -0
  517. package/dist/router/__tests__/on-error.test.js.map +1 -0
  518. package/dist/router/__tests__/pattern-matching.test.d.ts +2 -0
  519. package/dist/router/__tests__/pattern-matching.test.d.ts.map +1 -0
  520. package/dist/router/__tests__/pattern-matching.test.js +629 -0
  521. package/dist/router/__tests__/pattern-matching.test.js.map +1 -0
  522. package/dist/router/__tests__/segment-resolution-parallel-loading.test.d.ts +2 -0
  523. package/dist/router/__tests__/segment-resolution-parallel-loading.test.d.ts.map +1 -0
  524. package/dist/router/__tests__/segment-resolution-parallel-loading.test.js +155 -0
  525. package/dist/router/__tests__/segment-resolution-parallel-loading.test.js.map +1 -0
  526. package/dist/router/error-handling.d.ts +77 -0
  527. package/dist/router/error-handling.d.ts.map +1 -0
  528. package/dist/router/error-handling.js +202 -0
  529. package/dist/router/error-handling.js.map +1 -0
  530. package/dist/router/handler-context.d.ts +20 -0
  531. package/dist/router/handler-context.d.ts.map +1 -0
  532. package/dist/router/handler-context.js +198 -0
  533. package/dist/router/handler-context.js.map +1 -0
  534. package/dist/router/intercept-resolution.d.ts +66 -0
  535. package/dist/router/intercept-resolution.d.ts.map +1 -0
  536. package/dist/router/intercept-resolution.js +246 -0
  537. package/dist/router/intercept-resolution.js.map +1 -0
  538. package/dist/router/loader-resolution.d.ts +64 -0
  539. package/dist/router/loader-resolution.d.ts.map +1 -0
  540. package/dist/router/loader-resolution.js +284 -0
  541. package/dist/router/loader-resolution.js.map +1 -0
  542. package/dist/router/logging.d.ts +15 -0
  543. package/dist/router/logging.d.ts.map +1 -0
  544. package/dist/router/logging.js +99 -0
  545. package/dist/router/logging.js.map +1 -0
  546. package/dist/router/manifest.d.ts +22 -0
  547. package/dist/router/manifest.d.ts.map +1 -0
  548. package/dist/router/manifest.js +181 -0
  549. package/dist/router/manifest.js.map +1 -0
  550. package/dist/router/match-api.d.ts +35 -0
  551. package/dist/router/match-api.d.ts.map +1 -0
  552. package/dist/router/match-api.js +406 -0
  553. package/dist/router/match-api.js.map +1 -0
  554. package/dist/router/match-context.d.ts +206 -0
  555. package/dist/router/match-context.d.ts.map +1 -0
  556. package/dist/router/match-context.js +17 -0
  557. package/dist/router/match-context.js.map +1 -0
  558. package/dist/router/match-middleware/background-revalidation.d.ts +127 -0
  559. package/dist/router/match-middleware/background-revalidation.d.ts.map +1 -0
  560. package/dist/router/match-middleware/background-revalidation.js +75 -0
  561. package/dist/router/match-middleware/background-revalidation.js.map +1 -0
  562. package/dist/router/match-middleware/cache-lookup.d.ts +112 -0
  563. package/dist/router/match-middleware/cache-lookup.d.ts.map +1 -0
  564. package/dist/router/match-middleware/cache-lookup.js +257 -0
  565. package/dist/router/match-middleware/cache-lookup.js.map +1 -0
  566. package/dist/router/match-middleware/cache-store.d.ts +113 -0
  567. package/dist/router/match-middleware/cache-store.d.ts.map +1 -0
  568. package/dist/router/match-middleware/cache-store.js +108 -0
  569. package/dist/router/match-middleware/cache-store.js.map +1 -0
  570. package/dist/router/match-middleware/index.d.ts +81 -0
  571. package/dist/router/match-middleware/index.d.ts.map +1 -0
  572. package/dist/router/match-middleware/index.js +80 -0
  573. package/dist/router/match-middleware/index.js.map +1 -0
  574. package/dist/router/match-middleware/intercept-resolution.d.ts +117 -0
  575. package/dist/router/match-middleware/intercept-resolution.d.ts.map +1 -0
  576. package/dist/router/match-middleware/intercept-resolution.js +134 -0
  577. package/dist/router/match-middleware/intercept-resolution.js.map +1 -0
  578. package/dist/router/match-middleware/segment-resolution.d.ts +99 -0
  579. package/dist/router/match-middleware/segment-resolution.d.ts.map +1 -0
  580. package/dist/router/match-middleware/segment-resolution.js +53 -0
  581. package/dist/router/match-middleware/segment-resolution.js.map +1 -0
  582. package/dist/router/match-pipelines.d.ts +147 -0
  583. package/dist/router/match-pipelines.d.ts.map +1 -0
  584. package/dist/router/match-pipelines.js +82 -0
  585. package/dist/router/match-pipelines.js.map +1 -0
  586. package/dist/router/match-result.d.ts +126 -0
  587. package/dist/router/match-result.d.ts.map +1 -0
  588. package/dist/router/match-result.js +93 -0
  589. package/dist/router/match-result.js.map +1 -0
  590. package/dist/router/metrics.d.ts +20 -0
  591. package/dist/router/metrics.d.ts.map +1 -0
  592. package/dist/router/metrics.js +47 -0
  593. package/dist/router/metrics.js.map +1 -0
  594. package/dist/router/middleware.d.ts +249 -0
  595. package/dist/router/middleware.d.ts.map +1 -0
  596. package/dist/router/middleware.js +434 -0
  597. package/dist/router/middleware.js.map +1 -0
  598. package/dist/router/middleware.test.d.ts +2 -0
  599. package/dist/router/middleware.test.d.ts.map +1 -0
  600. package/dist/router/middleware.test.js +816 -0
  601. package/dist/router/middleware.test.js.map +1 -0
  602. package/dist/router/pattern-matching.d.ts +149 -0
  603. package/dist/router/pattern-matching.d.ts.map +1 -0
  604. package/dist/router/pattern-matching.js +349 -0
  605. package/dist/router/pattern-matching.js.map +1 -0
  606. package/dist/router/revalidation.d.ts +44 -0
  607. package/dist/router/revalidation.d.ts.map +1 -0
  608. package/dist/router/revalidation.js +147 -0
  609. package/dist/router/revalidation.js.map +1 -0
  610. package/dist/router/router-context.d.ts +135 -0
  611. package/dist/router/router-context.d.ts.map +1 -0
  612. package/dist/router/router-context.js +36 -0
  613. package/dist/router/router-context.js.map +1 -0
  614. package/dist/router/segment-resolution.d.ts +127 -0
  615. package/dist/router/segment-resolution.d.ts.map +1 -0
  616. package/dist/router/segment-resolution.js +919 -0
  617. package/dist/router/segment-resolution.js.map +1 -0
  618. package/dist/router/trie-matching.d.ts +40 -0
  619. package/dist/router/trie-matching.d.ts.map +1 -0
  620. package/dist/router/trie-matching.js +127 -0
  621. package/dist/router/trie-matching.js.map +1 -0
  622. package/dist/router/types.d.ts +136 -0
  623. package/dist/router/types.d.ts.map +1 -0
  624. package/dist/router/types.js +7 -0
  625. package/dist/router/types.js.map +1 -0
  626. package/dist/router.d.ts +753 -0
  627. package/dist/router.d.ts.map +1 -0
  628. package/dist/router.gen.d.ts +6 -0
  629. package/dist/router.gen.d.ts.map +1 -0
  630. package/dist/router.gen.js +6 -0
  631. package/dist/router.gen.js.map +1 -0
  632. package/dist/router.js +1304 -0
  633. package/dist/router.js.map +1 -0
  634. package/dist/rsc/__tests__/helpers.test.d.ts +2 -0
  635. package/dist/rsc/__tests__/helpers.test.d.ts.map +1 -0
  636. package/dist/rsc/__tests__/helpers.test.js +140 -0
  637. package/dist/rsc/__tests__/helpers.test.js.map +1 -0
  638. package/dist/rsc/handler.d.ts +45 -0
  639. package/dist/rsc/handler.d.ts.map +1 -0
  640. package/dist/rsc/handler.js +1172 -0
  641. package/dist/rsc/handler.js.map +1 -0
  642. package/dist/rsc/helpers.d.ts +16 -0
  643. package/dist/rsc/helpers.d.ts.map +1 -0
  644. package/dist/rsc/helpers.js +55 -0
  645. package/dist/rsc/helpers.js.map +1 -0
  646. package/dist/rsc/index.d.ts +22 -0
  647. package/dist/rsc/index.d.ts.map +1 -0
  648. package/dist/rsc/index.js +23 -0
  649. package/dist/rsc/index.js.map +1 -0
  650. package/dist/rsc/nonce.d.ts +9 -0
  651. package/dist/rsc/nonce.d.ts.map +1 -0
  652. package/dist/rsc/nonce.js +18 -0
  653. package/dist/rsc/nonce.js.map +1 -0
  654. package/dist/rsc/types.d.ts +206 -0
  655. package/dist/rsc/types.d.ts.map +1 -0
  656. package/dist/rsc/types.js +8 -0
  657. package/dist/rsc/types.js.map +1 -0
  658. package/dist/search-params.d.ts +103 -0
  659. package/dist/search-params.d.ts.map +1 -0
  660. package/dist/search-params.js +74 -0
  661. package/dist/search-params.js.map +1 -0
  662. package/dist/segment-system.d.ts +75 -0
  663. package/dist/segment-system.d.ts.map +1 -0
  664. package/dist/segment-system.js +336 -0
  665. package/dist/segment-system.js.map +1 -0
  666. package/dist/server/context.d.ts +245 -0
  667. package/dist/server/context.d.ts.map +1 -0
  668. package/dist/server/context.js +197 -0
  669. package/dist/server/context.js.map +1 -0
  670. package/dist/server/fetchable-loader-store.d.ts +18 -0
  671. package/dist/server/fetchable-loader-store.d.ts.map +1 -0
  672. package/dist/server/fetchable-loader-store.js +18 -0
  673. package/dist/server/fetchable-loader-store.js.map +1 -0
  674. package/dist/server/handle-store.d.ts +85 -0
  675. package/dist/server/handle-store.d.ts.map +1 -0
  676. package/dist/server/handle-store.js +142 -0
  677. package/dist/server/handle-store.js.map +1 -0
  678. package/dist/server/loader-registry.d.ts +55 -0
  679. package/dist/server/loader-registry.d.ts.map +1 -0
  680. package/dist/server/loader-registry.js +132 -0
  681. package/dist/server/loader-registry.js.map +1 -0
  682. package/dist/server/request-context.d.ts +226 -0
  683. package/dist/server/request-context.d.ts.map +1 -0
  684. package/dist/server/request-context.js +290 -0
  685. package/dist/server/request-context.js.map +1 -0
  686. package/dist/server/root-layout.d.ts +4 -0
  687. package/dist/server/root-layout.d.ts.map +1 -0
  688. package/dist/server/root-layout.js +5 -0
  689. package/dist/server/root-layout.js.map +1 -0
  690. package/dist/server.d.ts +15 -0
  691. package/dist/server.d.ts.map +1 -0
  692. package/dist/server.js +20 -0
  693. package/dist/server.js.map +1 -0
  694. package/dist/ssr/__tests__/ssr-handler.test.d.ts +2 -0
  695. package/dist/ssr/__tests__/ssr-handler.test.d.ts.map +1 -0
  696. package/dist/ssr/__tests__/ssr-handler.test.js +132 -0
  697. package/dist/ssr/__tests__/ssr-handler.test.js.map +1 -0
  698. package/dist/ssr/index.d.ts +98 -0
  699. package/dist/ssr/index.d.ts.map +1 -0
  700. package/dist/ssr/index.js +158 -0
  701. package/dist/ssr/index.js.map +1 -0
  702. package/dist/static-handler.d.ts +50 -0
  703. package/dist/static-handler.d.ts.map +1 -0
  704. package/dist/static-handler.gen.d.ts +5 -0
  705. package/dist/static-handler.gen.d.ts.map +1 -0
  706. package/dist/static-handler.gen.js +5 -0
  707. package/dist/static-handler.gen.js.map +1 -0
  708. package/dist/static-handler.js +29 -0
  709. package/dist/static-handler.js.map +1 -0
  710. package/dist/testing/vitest.js +48 -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 +2659 -883
  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/dist/vite/package-resolution.js +112 -0
  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/dist/vite/virtual-entries.js +110 -0
  809. package/dist/vite/virtual-entries.js.map +1 -0
  810. package/package.json +57 -11
  811. package/skills/breadcrumbs/SKILL.md +3 -1
  812. package/skills/bundle-analysis/SKILL.md +159 -0
  813. package/skills/cache-guide/SKILL.md +243 -21
  814. package/skills/caching/SKILL.md +118 -2
  815. package/skills/composability/SKILL.md +27 -2
  816. package/skills/document-cache/SKILL.md +78 -55
  817. package/skills/handler-use/SKILL.md +364 -0
  818. package/skills/hooks/SKILL.md +229 -20
  819. package/skills/host-router/SKILL.md +45 -20
  820. package/skills/i18n/SKILL.md +276 -0
  821. package/skills/intercept/SKILL.md +46 -4
  822. package/skills/layout/SKILL.md +28 -7
  823. package/skills/links/SKILL.md +249 -17
  824. package/skills/loader/SKILL.md +273 -53
  825. package/skills/middleware/SKILL.md +49 -12
  826. package/skills/migrate-nextjs/SKILL.md +562 -0
  827. package/skills/migrate-react-router/SKILL.md +769 -0
  828. package/skills/mime-routes/SKILL.md +27 -0
  829. package/skills/observability/SKILL.md +137 -0
  830. package/skills/parallel/SKILL.md +71 -6
  831. package/skills/prerender/SKILL.md +123 -100
  832. package/skills/rango/SKILL.md +242 -22
  833. package/skills/react-compiler/SKILL.md +168 -0
  834. package/skills/response-routes/SKILL.md +66 -9
  835. package/skills/route/SKILL.md +88 -4
  836. package/skills/router-setup/SKILL.md +90 -5
  837. package/skills/server-actions/SKILL.md +751 -0
  838. package/skills/streams-and-websockets/SKILL.md +283 -0
  839. package/skills/testing/SKILL.md +776 -0
  840. package/skills/typesafety/SKILL.md +329 -27
  841. package/skills/use-cache/SKILL.md +34 -5
  842. package/skills/view-transitions/SKILL.md +294 -0
  843. package/src/__augment-tests__/augment.ts +81 -0
  844. package/src/__augment-tests__/augmented.check.ts +117 -0
  845. package/src/__internal.ts +1 -1
  846. package/src/browser/action-coordinator.ts +53 -36
  847. package/src/browser/app-shell.ts +52 -0
  848. package/src/browser/app-version.ts +14 -0
  849. package/src/browser/event-controller.ts +86 -70
  850. package/src/browser/history-state.ts +21 -0
  851. package/src/browser/index.ts +3 -3
  852. package/src/browser/navigation-bridge.ts +101 -13
  853. package/src/browser/navigation-client.ts +125 -53
  854. package/src/browser/navigation-store.ts +75 -17
  855. package/src/browser/navigation-transaction.ts +10 -28
  856. package/src/browser/partial-update.ts +90 -30
  857. package/src/browser/prefetch/cache.ts +129 -21
  858. package/src/browser/prefetch/fetch.ts +156 -18
  859. package/src/browser/prefetch/queue.ts +92 -29
  860. package/src/browser/prefetch/resource-ready.ts +77 -0
  861. package/src/browser/rango-state.ts +53 -13
  862. package/src/browser/react/Link.tsx +72 -8
  863. package/src/browser/react/NavigationProvider.tsx +83 -33
  864. package/src/browser/react/context.ts +7 -2
  865. package/src/browser/react/filter-segment-order.ts +51 -7
  866. package/src/browser/react/index.ts +3 -0
  867. package/src/browser/react/location-state-shared.ts +175 -4
  868. package/src/browser/react/location-state.ts +39 -13
  869. package/src/browser/react/use-handle.ts +23 -64
  870. package/src/browser/react/use-navigation.ts +22 -2
  871. package/src/browser/react/use-params.ts +20 -8
  872. package/src/browser/react/use-reverse.ts +106 -0
  873. package/src/browser/react/use-router.ts +43 -10
  874. package/src/browser/react/use-segments.ts +11 -8
  875. package/src/browser/response-adapter.ts +25 -0
  876. package/src/browser/rsc-router.tsx +87 -22
  877. package/src/browser/scroll-restoration.ts +29 -19
  878. package/src/browser/segment-reconciler.ts +36 -14
  879. package/src/browser/segment-structure-assert.ts +2 -2
  880. package/src/browser/server-action-bridge.ts +31 -36
  881. package/src/browser/types.ts +48 -5
  882. package/src/build/collect-fallback-refs.ts +107 -0
  883. package/src/build/generate-manifest.ts +65 -40
  884. package/src/build/generate-route-types.ts +5 -0
  885. package/src/build/index.ts +2 -0
  886. package/src/build/route-trie.ts +52 -25
  887. package/src/build/route-types/codegen.ts +4 -4
  888. package/src/build/route-types/include-resolution.ts +9 -2
  889. package/src/build/route-types/per-module-writer.ts +7 -4
  890. package/src/build/route-types/router-processing.ts +266 -86
  891. package/src/build/route-types/scan-filter.ts +9 -2
  892. package/src/build/route-types/source-scan.ts +118 -0
  893. package/src/build/runtime-discovery.ts +9 -20
  894. package/src/cache/cache-scope.ts +40 -56
  895. package/src/cache/cf/cf-cache-store.ts +54 -13
  896. package/src/cache/taint.ts +55 -0
  897. package/src/client.rsc.tsx +3 -0
  898. package/src/client.tsx +94 -238
  899. package/src/context-var.ts +72 -2
  900. package/src/decode-loader-results.ts +36 -0
  901. package/src/errors.ts +30 -1
  902. package/src/handle.ts +65 -12
  903. package/src/host/index.ts +2 -2
  904. package/src/host/router.ts +129 -57
  905. package/src/host/types.ts +31 -2
  906. package/src/host/utils.ts +1 -1
  907. package/src/href-client.ts +140 -20
  908. package/src/index.rsc.ts +12 -5
  909. package/src/index.ts +61 -11
  910. package/src/loader-store.ts +500 -0
  911. package/src/loader.rsc.ts +21 -6
  912. package/src/loader.ts +3 -10
  913. package/src/missing-id-error.ts +68 -0
  914. package/src/outlet-context.ts +1 -1
  915. package/src/prerender/store.ts +5 -4
  916. package/src/prerender.ts +141 -80
  917. package/src/response-utils.ts +37 -0
  918. package/src/reverse.ts +65 -15
  919. package/src/route-content-wrapper.tsx +6 -28
  920. package/src/route-definition/dsl-helpers.ts +411 -261
  921. package/src/route-definition/helper-factories.ts +29 -139
  922. package/src/route-definition/helpers-types.ts +110 -34
  923. package/src/route-definition/index.ts +3 -0
  924. package/src/route-definition/redirect.ts +9 -1
  925. package/src/route-definition/resolve-handler-use.ts +155 -0
  926. package/src/route-definition/use-item-types.ts +32 -0
  927. package/src/route-types.ts +37 -41
  928. package/src/router/basename.ts +14 -0
  929. package/src/router/content-negotiation.ts +113 -1
  930. package/src/router/error-handling.ts +1 -1
  931. package/src/router/handler-context.ts +77 -38
  932. package/src/router/intercept-resolution.ts +13 -22
  933. package/src/router/lazy-includes.ts +8 -8
  934. package/src/router/loader-resolution.ts +174 -22
  935. package/src/router/manifest.ts +22 -13
  936. package/src/router/match-api.ts +128 -192
  937. package/src/router/match-handlers.ts +63 -20
  938. package/src/router/match-middleware/cache-lookup.ts +70 -97
  939. package/src/router/match-middleware/cache-store.ts +3 -2
  940. package/src/router/match-middleware/segment-resolution.ts +53 -0
  941. package/src/router/match-result.ts +103 -4
  942. package/src/router/metrics.ts +1 -1
  943. package/src/router/middleware-types.ts +21 -34
  944. package/src/router/middleware.ts +101 -89
  945. package/src/router/navigation-snapshot.ts +182 -0
  946. package/src/router/pattern-matching.ts +101 -17
  947. package/src/router/prerender-match.ts +110 -10
  948. package/src/router/preview-match.ts +32 -102
  949. package/src/router/request-classification.ts +286 -0
  950. package/src/router/revalidation.ts +58 -2
  951. package/src/router/route-snapshot.ts +245 -0
  952. package/src/router/router-interfaces.ts +77 -28
  953. package/src/router/router-options.ts +76 -11
  954. package/src/router/router-registry.ts +2 -5
  955. package/src/router/segment-resolution/fresh.ts +105 -13
  956. package/src/router/segment-resolution/helpers.ts +29 -24
  957. package/src/router/segment-resolution/revalidation.ts +236 -112
  958. package/src/router/segment-resolution/view-transition-default.ts +36 -0
  959. package/src/router/substitute-pattern-params.ts +56 -0
  960. package/src/router/telemetry.ts +99 -0
  961. package/src/router/trie-matching.ts +18 -13
  962. package/src/router/types.ts +9 -0
  963. package/src/router/url-params.ts +49 -0
  964. package/src/router.ts +86 -22
  965. package/src/rsc/handler-context.ts +2 -2
  966. package/src/rsc/handler.ts +440 -381
  967. package/src/rsc/helpers.ts +91 -43
  968. package/src/rsc/index.ts +1 -1
  969. package/src/rsc/loader-fetch.ts +23 -3
  970. package/src/rsc/manifest-init.ts +5 -1
  971. package/src/rsc/origin-guard.ts +28 -10
  972. package/src/rsc/progressive-enhancement.ts +18 -2
  973. package/src/rsc/response-route-handler.ts +46 -53
  974. package/src/rsc/rsc-rendering.ts +41 -48
  975. package/src/rsc/runtime-warnings.ts +9 -10
  976. package/src/rsc/server-action.ts +25 -37
  977. package/src/rsc/ssr-setup.ts +18 -2
  978. package/src/rsc/types.ts +17 -3
  979. package/src/search-params.ts +4 -4
  980. package/src/segment-content-promise.ts +67 -0
  981. package/src/segment-loader-promise.ts +122 -0
  982. package/src/segment-system.tsx +132 -116
  983. package/src/serialize.ts +243 -0
  984. package/src/server/context.ts +190 -51
  985. package/src/server/cookie-store.ts +28 -4
  986. package/src/server/handle-store.ts +19 -0
  987. package/src/server/loader-registry.ts +9 -8
  988. package/src/server/request-context.ts +195 -57
  989. package/src/ssr/index.tsx +8 -1
  990. package/src/static-handler.ts +19 -7
  991. package/src/testing/cache-status.ts +166 -0
  992. package/src/testing/collect-handle.ts +63 -0
  993. package/src/testing/dispatch.ts +440 -0
  994. package/src/testing/dom.entry.ts +22 -0
  995. package/src/testing/e2e/fixture.ts +154 -0
  996. package/src/testing/e2e/index.ts +149 -0
  997. package/src/testing/e2e/matchers.ts +51 -0
  998. package/src/testing/e2e/page-helpers.ts +272 -0
  999. package/src/testing/e2e/parity.ts +306 -0
  1000. package/src/testing/e2e/server.ts +183 -0
  1001. package/src/testing/flight-matchers.ts +104 -0
  1002. package/src/testing/flight-runtime.d.ts +57 -0
  1003. package/src/testing/flight-tree.ts +309 -0
  1004. package/src/testing/flight.entry.ts +39 -0
  1005. package/src/testing/flight.ts +197 -0
  1006. package/src/testing/generated-routes.ts +223 -0
  1007. package/src/testing/index.ts +106 -0
  1008. package/src/testing/internal/context.ts +304 -0
  1009. package/src/testing/internal/flight-client-globals.ts +30 -0
  1010. package/src/testing/render-route.tsx +565 -0
  1011. package/src/testing/run-loader.ts +341 -0
  1012. package/src/testing/run-middleware.ts +179 -0
  1013. package/src/testing/vitest-stubs/cloudflare-email.ts +9 -0
  1014. package/src/testing/vitest-stubs/cloudflare-workers.ts +21 -0
  1015. package/src/testing/vitest-stubs/plugin-rsc.ts +16 -0
  1016. package/src/testing/vitest-stubs/version.ts +5 -0
  1017. package/src/testing/vitest.ts +185 -0
  1018. package/src/types/cache-types.ts +4 -4
  1019. package/src/types/global-namespace.ts +39 -26
  1020. package/src/types/handler-context.ts +103 -67
  1021. package/src/types/index.ts +1 -0
  1022. package/src/types/loader-types.ts +41 -15
  1023. package/src/types/request-scope.ts +126 -0
  1024. package/src/types/route-entry.ts +12 -1
  1025. package/src/types/segments.ts +36 -2
  1026. package/src/urls/include-helper.ts +34 -67
  1027. package/src/urls/index.ts +0 -3
  1028. package/src/urls/path-helper-types.ts +50 -9
  1029. package/src/urls/path-helper.ts +63 -63
  1030. package/src/urls/pattern-types.ts +48 -19
  1031. package/src/urls/response-types.ts +25 -22
  1032. package/src/urls/type-extraction.ts +26 -116
  1033. package/src/urls/urls-function.ts +1 -5
  1034. package/src/use-loader.tsx +487 -44
  1035. package/src/vite/debug.ts +185 -0
  1036. package/src/vite/discovery/bundle-postprocess.ts +34 -37
  1037. package/src/vite/discovery/discover-routers.ts +105 -51
  1038. package/src/vite/discovery/discovery-errors.ts +194 -0
  1039. package/src/vite/discovery/gate-state.ts +171 -0
  1040. package/src/vite/discovery/prerender-collection.ts +188 -93
  1041. package/src/vite/discovery/route-types-writer.ts +40 -84
  1042. package/src/vite/discovery/self-gen-tracking.ts +27 -1
  1043. package/src/vite/discovery/state.ts +46 -4
  1044. package/src/vite/discovery/virtual-module-codegen.ts +13 -23
  1045. package/src/vite/index.ts +6 -0
  1046. package/src/vite/plugin-types.ts +126 -4
  1047. package/src/vite/plugins/cjs-to-esm.ts +8 -7
  1048. package/src/vite/plugins/client-ref-dedup.ts +16 -0
  1049. package/src/vite/plugins/client-ref-hashing.ts +28 -5
  1050. package/src/vite/plugins/cloudflare-protocol-loader-hook.d.mts +23 -0
  1051. package/src/vite/plugins/cloudflare-protocol-loader-hook.mjs +76 -0
  1052. package/src/vite/plugins/cloudflare-protocol-stub.ts +214 -0
  1053. package/src/vite/plugins/expose-action-id.ts +54 -30
  1054. package/src/vite/plugins/expose-id-utils.ts +24 -8
  1055. package/src/vite/plugins/expose-ids/export-analysis.ts +100 -20
  1056. package/src/vite/plugins/expose-ids/handler-transform.ts +12 -35
  1057. package/src/vite/plugins/expose-ids/loader-transform.ts +3 -5
  1058. package/src/vite/plugins/expose-ids/router-transform.ts +20 -3
  1059. package/src/vite/plugins/expose-internal-ids.ts +544 -317
  1060. package/src/vite/plugins/performance-tracks.ts +92 -0
  1061. package/src/vite/plugins/refresh-cmd.ts +88 -26
  1062. package/src/vite/plugins/use-cache-transform.ts +65 -50
  1063. package/src/vite/plugins/version-injector.ts +39 -23
  1064. package/src/vite/plugins/version-plugin.ts +59 -2
  1065. package/src/vite/plugins/virtual-entries.ts +2 -2
  1066. package/src/vite/rango.ts +130 -26
  1067. package/src/vite/router-discovery.ts +920 -129
  1068. package/src/vite/utils/ast-handler-extract.ts +15 -15
  1069. package/src/vite/utils/banner.ts +1 -1
  1070. package/src/vite/utils/bundle-analysis.ts +4 -2
  1071. package/src/vite/utils/client-chunks.ts +190 -0
  1072. package/src/vite/utils/forward-user-plugins.ts +193 -0
  1073. package/src/vite/utils/manifest-utils.ts +21 -5
  1074. package/src/vite/utils/package-resolution.ts +41 -1
  1075. package/src/vite/utils/prerender-utils.ts +38 -5
  1076. package/src/vite/utils/shared-utils.ts +109 -27
  1077. package/src/browser/action-response-classifier.ts +0 -99
@@ -0,0 +1,776 @@
1
+ ---
2
+ name: testing
3
+ description: Test @rangojs/router apps — unit (loaders/middleware/reverse/components), integration (dispatch/Flight), and e2e (dev+prod parity, progressive enhancement)
4
+ argument-hint: [layer]
5
+ ---
6
+
7
+ # Testing @rangojs/router apps
8
+
9
+ Rango ships six consumer-facing testing entries, one per test runtime/dependency:
10
+ `@rangojs/router/testing` (unit + integration, under a Vite-driven Vitest
11
+ project), `@rangojs/router/testing/vitest` (the `rangoTestConfig`/`rangoTestAliases` setup preset),
12
+ `@rangojs/router/testing/dom` (`renderRoute`, needs RTL + a DOM env),
13
+ `@rangojs/router/testing/e2e` (the Playwright harness),
14
+ `@rangojs/router/testing/flight` (real Flight, react-server condition only), and
15
+ `@rangojs/router/testing/flight-matchers` (the Flight matchers).
16
+ The hard problem in an RSC app is that the layer you reach for is dictated by
17
+ **what the behavior touches** — a pure predicate is a one-line vitest test; a
18
+ real async Server Component cannot be a plain node test at all. Pick the layer
19
+ **first**, then the primitive. Reaching one layer too high (e2e for a reverse
20
+ function) is slow; one too low (a node test for Flight) fails to compile or
21
+ silently asserts nothing.
22
+
23
+ Compatibility (the setup that bit the first installed consumer — read before
24
+ writing `vitest.config.ts`):
25
+
26
+ - **Node >= 23:** use **`rangoTestConfig()`**, not the bare `rangoTestAliases()`.
27
+ `@rangojs/router` is consumed as SOURCE (its exports resolve to `./src/*.ts`),
28
+ and Node >= 23 refuses to type-strip `.ts` under `node_modules`
29
+ (`ERR_UNSUPPORTED_NODE_MODULES_TYPE_STRIPPING`). `rangoTestConfig` ships as
30
+ compiled JS (so the config itself loads under Node) AND adds the required
31
+ `server.deps.inline: [/@rangojs[/\\]router/]` so Vite — not Node — transpiles
32
+ rango's source under test. With bare `rangoTestAliases` you must wire
33
+ `deps.inline` yourself.
34
+ - **Vitest:** the rango fragment goes under `test` (`test.alias` +
35
+ `test.server.deps.inline`, both returned by `rangoTestConfig`). The node/DOM
36
+ project keeps React as its CLIENT build; the Flight project uses the
37
+ `react-server` condition in a separate `vitest.rsc.config.ts`.
38
+
39
+ For the prose guide with full setup and migration, see
40
+ [`docs/testing.md`](https://github.com/ivogt/vite-rsc/blob/main/packages/rangojs-router/docs/testing.md)
41
+ (the `docs/` directory is not shipped in the published package, so this is an
42
+ absolute link).
43
+
44
+ ## When to use
45
+
46
+ Use this skill when adding or changing tests for a Rango app: a loader,
47
+ middleware, a route map, a client component, a response route, cache/SWR
48
+ behavior, prerender, or a navigation/PE flow.
49
+
50
+ Two non-negotiable mandates (from the repo's `CLAUDE.md`, and they apply to
51
+ consumer apps too):
52
+
53
+ - **Every e2e covers BOTH dev and production.** A dev-only e2e is not
54
+ acceptable. Use `parityDescribe` — it generates the dev and production
55
+ describes from one body, so you cannot forget the prod half.
56
+ - **Progressive-enhancement parity** is a first-class assertion. A form-driven
57
+ flow must produce the same observable result with JS on and JS off. Use
58
+ `expectParity`.
59
+
60
+ ## The read-first shape
61
+
62
+ Four import roots, each matched to the dependency/runtime that can load it —
63
+ this split is forced by hard walls, not preference:
64
+
65
+ - `@rangojs/router/testing` — unit + integration primitives. Run these under a
66
+ **Vite-driven Vitest** project with the rango Vite plugin active (the router
67
+ internals import the `@rangojs/router:version` virtual module; without the
68
+ plugin, alias `@rangojs/router:version`). It references neither React,
69
+ `@testing-library/react`, Playwright, nor the RSC runtime — a unit suite
70
+ testing only loaders/middleware/`dispatch` pulls in none of them.
71
+ - `@rangojs/router/testing/dom` — `renderRoute` (the RTL component stub). Kept
72
+ separate so the unit barrel above stays free of React/RTL; it lazy-loads
73
+ `@testing-library/react` at call time and needs a DOM env (happy-dom/jsdom).
74
+ - `@rangojs/router/testing/e2e` — the Playwright harness. Kept separate so it
75
+ loads in a plain (non-Vite) Playwright runner; the unit barrel pulls in
76
+ router-manifest code that a Playwright loader cannot resolve. The helpers take
77
+ your `test`/`expect` as parameters, so this entry never imports
78
+ `@playwright/test` at runtime.
79
+ - `@rangojs/router/testing/flight` — real Flight rendering. Its serializer loads
80
+ only under the `react-server` node condition; pulling it elsewhere throws.
81
+
82
+ The single rule that drives everything:
83
+
84
+ > **If the behavior needs a real Flight render, it cannot be a plain vitest node
85
+ > test.** It is either `renderToFlightString` (under the react-server vitest
86
+ > project) or an e2e test. There is no middle ground in node.
87
+
88
+ ## Decision tree: behavior -> layer -> primitive
89
+
90
+ | The behavior is… | Layer | Primitive | Import root |
91
+ | --------------------------------------------------------------------------------------------------------- | ------------ | ---------------------------------------------------------------- | -------------------------------- |
92
+ | a pure function / `reverse` / a predicate (`revalidate`, `isAction`) | unit (node) | call it directly; `runMiddleware`/`runLoader` for ctx | `@rangojs/router/testing` |
93
+ | one loader's data logic | unit (node) | `runLoader` (a registered `createLoader` handle, or the raw fn) | `@rangojs/router/testing` |
94
+ | one middleware's ordering / short-circuit / cookie+header merge | unit (node) | `runMiddleware` | `@rangojs/router/testing` |
95
+ | a CLIENT component reading router context (`useParams`/`useReverse`/`Outlet`/`useNavigation`/`useLoader`) | unit (DOM) | `renderRoute` (needs happy-dom/jsdom + `@testing-library/react`) | `@rangojs/router/testing/dom` |
96
+ | a redirect / status / headers / cookies / **response route** (json/text/html/xml/md), no Flight | integration | `dispatch` (router -> Response) | `@rangojs/router/testing` |
97
+ | a real async **Server Component** / Flight serialization shape | RSC unit | `renderToFlightString` + `toMatchFlight` | `@rangojs/router/testing/flight` |
98
+ | a client island's **typed props** across the boundary / inlined-vs-island | RSC unit | `renderServerTree` + `findClientBoundaries` | `@rangojs/router/testing/flight` |
99
+ | navigation, hydration, PE parity, view transitions, real SSR | e2e | `createRangoE2E` -> `parityDescribe`/`expectParity` | `@rangojs/router/testing/e2e` |
100
+ | cache hit/miss/stale, prerender (= a cache hit by design) | e2e + signal | `assertCacheStatus` / telemetry sink (gate on) | `@rangojs/router/testing` |
101
+ | generated route map drift vs runtime | unit (node) | `assertGeneratedRoutesMatch` | `@rangojs/router/testing` |
102
+
103
+ Cross-references: `/loader`, `/middleware`, `/server-actions`, `/caching`,
104
+ `/prerender`, `/typesafety`.
105
+
106
+ ## Unit recipes (vitest, node)
107
+
108
+ ### runMiddleware — ordering, short-circuit, cookie/header merge
109
+
110
+ Runs the chain through the router's **real** `executeMiddleware`, so
111
+ `next()`, return-Response short-circuit, throw-Response short-circuit,
112
+ double-next guards, and header/cookie merging behave exactly as in production.
113
+ `nextCalled` is `0` on short-circuit, `1` on pass-through. The result also
114
+ carries `cookies` (the effective `{ name: value }` view — assert a cookie the
115
+ chain set without casting through the `@internal` `ctx.cookies()`). The returned
116
+ `ctx` is the underlying `RequestContext` for anything else (`ctx.get(...)`,
117
+ `ctx.res.headers`).
118
+
119
+ ```ts
120
+ import { describe, it, expect } from "vitest";
121
+ import { runMiddleware } from "@rangojs/router/testing";
122
+ import type { Middleware } from "@rangojs/router";
123
+
124
+ const requireUser: Middleware = async (ctx, next) => {
125
+ if (!ctx.get("user")) return new Response(null, { status: 401 });
126
+ return next();
127
+ };
128
+
129
+ it("passes through when the user is present", async () => {
130
+ const { response, nextCalled } = await runMiddleware(
131
+ requireUser,
132
+ "/dashboard",
133
+ {
134
+ vars: { user: { id: 1 } }, // object form; or [[key, value]] tuples (key may be a createVar())
135
+ },
136
+ );
137
+ expect(nextCalled).toBe(1);
138
+ expect(response.status).toBe(200);
139
+ });
140
+
141
+ it("short-circuits (return OR throw Response) when unauthenticated", async () => {
142
+ const { response, nextCalled } = await runMiddleware(
143
+ requireUser,
144
+ "/dashboard",
145
+ );
146
+ expect(nextCalled).toBe(0);
147
+ expect(response.status).toBe(401);
148
+ });
149
+ ```
150
+
151
+ Seed prior-middleware state with `vars` (string key or `createVar()` handle).
152
+ Model the downstream route with `next`. Enable `ctx.reverse(...)` by passing
153
+ `routeMap` (and `routeName` for scoped `.name` resolution). Pass an array to run
154
+ several in order. Cookies set via `cookies().set(...)` surface on the result's
155
+ `cookies` and on the merged response `Set-Cookie`.
156
+
157
+ There is no `handles`/`rendered` option (only `runLoader` has them): middleware
158
+ runs BEFORE the render barrier, so it has no post-barrier handle access in
159
+ production — `ctx.use(Handle)` after `ctx.rendered()` is a loader/handler
160
+ capability, not a middleware one. Read handle data in a loader and test it with
161
+ `runLoader`'s `handles`/`rendered`.
162
+
163
+ ### runLoader — one loader's data logic
164
+
165
+ Pass a registered `createLoader()` handle **or** the raw loader body `(ctx) => ...`.
166
+ A handle's fn is recovered from the registry: `createLoader` assigns a
167
+ runtime-fallback `$$id` and registers the fn even without the Vite plugin, when
168
+ imported through the server build (`@rangojs/router` under the `rangoTestConfig`
169
+ preset). The raw body needs no build at all. Either way `runLoader` invokes the
170
+ function against a real `RequestContext`, so cookies, headers, `ctx.get`, and
171
+ `ctx.reverse` resolve. (A handle imported through the CLIENT build has its body
172
+ dropped — `runLoader` then throws a clear error pointing you to the preset or the
173
+ raw body.)
174
+
175
+ ```ts
176
+ import { runLoader } from "@rangojs/router/testing";
177
+ import { createLoader, createVar } from "@rangojs/router";
178
+
179
+ const User = createVar<{ name: string }>();
180
+ // The registered loader — no separate body export needed for testability:
181
+ const ProductLoader = createLoader(async (ctx) => ({
182
+ id: ctx.params.id,
183
+ region: ctx.env.REGION,
184
+ user: ctx.get(User),
185
+ }));
186
+
187
+ it("reads params, env, and seeded vars", async () => {
188
+ const data = await runLoader(ProductLoader, {
189
+ params: { id: "42" },
190
+ env: { REGION: "eu" },
191
+ vars: [[User, { name: "Ada" }]],
192
+ });
193
+ expect(data).toEqual({ id: "42", region: "eu", user: { name: "Ada" } });
194
+ });
195
+ // runLoader(async (ctx) => ({ ... }), opts) — the bare body — works identically.
196
+ ```
197
+
198
+ Options: `params` (also surfaced as `routeParams`), `search`, `env`, `vars`,
199
+ `method`/`body`/`formData`, `routeMap`/`routeName` (for `ctx.reverse`), and
200
+ `use` (a resolver for `ctx.use(OtherLoader)` composition — without it, `ctx.use`
201
+ runs the dependency's own `fn` if it carries one).
202
+
203
+ Two unit-only limitations to document in your test, not work around:
204
+
205
+ - `ctx.reverse(...)` **throws** unless you pass `routeMap`.
206
+ - `ctx.rendered()` **throws** (the DSL render barrier only exists in a full
207
+ match) and `ctx.isAction(...)` (the action-render context) is not available —
208
+ test those with `renderToFlightString` or e2e.
209
+
210
+ No body extraction needed: `export const L = createLoader(async (ctx) => {...})`
211
+ can be imported and passed straight to `runLoader(L, ...)`. Exporting the inner
212
+ body separately is optional now (only if you want to test it without going
213
+ through `createLoader` at all).
214
+
215
+ COOKIE SEEDING: there is no `cookies`/`headers` option — seed a request cookie by
216
+ passing a full `Request` with the header, `runLoader(body, { request: new
217
+ Request("https://app.test/", { headers: { Cookie: "sid=abc" } }) })`. A loader
218
+ that reads `cookies()` then sees `abc`. (`search`/`method` are baked onto this
219
+ request for you, so pass a `Request` only when you need headers/cookies.)
220
+
221
+ ### runInRequestContext — an action (or any fn) that reads request context
222
+
223
+ For a server ACTION (or any function) that authenticates off the request cookie
224
+ and calls `getRequestContext()` / `cookies()` but has no loader-context shape,
225
+ `runInRequestContext(fn, opts)` builds a real `RequestContext` (same `opts` as the
226
+ other primitives — `env`, `request`, `vars`, ...) AND enters it, so the function
227
+ runs exactly as in production. `fn` may be async; the context stays active across
228
+ its awaits. It captures the action's OUTPUT whether `fn` RETURNS or THROWS, so it
229
+ is assertable WITHOUT casting through the `@internal` `ctx.res` / `ctx.cookies()`:
230
+
231
+ - `result` — fn's return value (awaited), or `undefined` if it threw
232
+ - `thrown` — what `fn` threw (a redirect/notFound `Response` on the SUCCESS path), or `undefined`. Captured, NOT re-thrown — assert on it for a throwing action
233
+ - `response` — Set-Cookie / headers / status the run set; on a thrown redirect, that redirect's `Location` merged with the cookies
234
+ - `cookies` — the effective `{ name: value }` cookie view after the run
235
+ - `locationState` — the flash the action set via `ctx.setLocationState()` / `redirect({ state })`, resolved to the `{ key: value }` the client reads
236
+
237
+ The THROW path matters: the dominant cookie+flash case is an auth action that sets
238
+ a cookie + flash then `throw redirect("/app")` on success. Because the snapshot
239
+ fires on the throw too, you do NOT have to wrap the action in your own try/catch:
240
+
241
+ ```ts
242
+ import { runInRequestContext } from "@rangojs/router/testing";
243
+ import { loginAction } from "../src/actions/login"; // sets a session cookie + flash, then throw redirect("/app")
244
+
245
+ it("sets the session cookie + flash and redirects", async () => {
246
+ const { thrown, cookies, locationState } = await runInRequestContext(
247
+ () => loginAction(input),
248
+ {
249
+ env,
250
+ request: new Request("https://app.test/admin", {
251
+ headers: { Cookie: "sid=abc" },
252
+ }),
253
+ },
254
+ );
255
+ expect((thrown as Response).headers.get("Location")).toBe("/app"); // redirected
256
+ expect(cookies.session).toBeDefined(); // cookie set before the throw, no @internal cast
257
+ expect(locationState).toEqual({ flash: { text: "Welcome back" } });
258
+ });
259
+ ```
260
+
261
+ For the low-level case where you already hold a context from
262
+ `createTestRequestContext(...)`, `runWithRequestContext(ctx, fn)` is re-exported
263
+ from `@rangojs/router/testing` to enter it directly; `runInRequestContext` is the
264
+ one-call convenience over the two.
265
+
266
+ ### Your bindings are your seam (env.DB / Durable Objects / R2)
267
+
268
+ The node primitives test the router's seams; the moment your loader/middleware/
269
+ action calls a **platform binding** (`env.DB`, a Durable Object stub, `env.R2`),
270
+ you have crossed out of rango and into your app's I/O. rango deliberately ships
271
+ **no doubles** for these — they are app- and schema-specific — so the double is
272
+ yours to build and inject through the `env` option every primitive already takes:
273
+
274
+ ```ts
275
+ await runLoader(bundleLoaderBody, { env: { DB: fakeD1 } });
276
+ await runMiddleware(requireMembership, "/t/acme/edit", { env: { DB: fakeD1 } });
277
+ await runInRequestContext(() => authorizeAction(input), {
278
+ env: { DB: fakeD1 },
279
+ request,
280
+ });
281
+ ```
282
+
283
+ Plan for this seam — it is usually the single biggest effort in a consumer unit
284
+ suite, and the work is in matching the **driver contract**, not the binding's
285
+ public API. The sharp edge: a `D1Database` double for **`drizzle-orm/d1`** must
286
+ serve **positional row arrays in schema-column order** for drizzle's `.raw()`
287
+ path (with the driver-level encodings so the decoder round-trips `Date`/JSON) —
288
+ NOT `{ column: value }` objects. A naive object-shaped double returns
289
+ silently-wrong or empty rows. That contract is per-method: drizzle-d1 serves
290
+ SELECTs through `.raw()` (the positional rows above), but writes
291
+ (INSERT/UPDATE/DELETE) go through `.run()`, which returns `{ success, meta }` (no
292
+ rows) and bypasses the row responder entirely — model BOTH paths, a read-only
293
+ `.raw()` double silently no-ops every write. Keep the double at the binding
294
+ boundary; never mock a rango primitive to dodge building it.
295
+
296
+ ### renderRoute — a client component reading router context
297
+
298
+ RTL-style stub. Peer of React Router's `createRoutesStub` / Expo's
299
+ `renderRouter`. It mounts the router's real `NavigationProvider` plus a
300
+ synthetic segment tree so `useParams`, `useReverse`, `useNavigation`, `Outlet`,
301
+ `usePathname`, `useSearchParams`, and `useLoader`/`useFetchLoader` (reading
302
+ **seeded** data) resolve — no server, no Vite, no Flight round-trip. It is
303
+ `async` (lazy-loads `@testing-library/react`).
304
+
305
+ ```tsx
306
+ // @vitest-environment happy-dom
307
+ import { describe, it, expect, afterEach } from "vitest";
308
+ import { cleanup } from "@testing-library/react";
309
+ import { renderRoute } from "@rangojs/router/testing/dom";
310
+ import { Outlet, useParams, useReverse } from "@rangojs/router/client";
311
+
312
+ afterEach(cleanup);
313
+
314
+ function Layout() {
315
+ return (
316
+ <div>
317
+ <span data-testid="shell">shell</span>
318
+ <Outlet />
319
+ </div>
320
+ );
321
+ }
322
+ function Product() {
323
+ const { productId } = useParams<{ productId: string }>();
324
+ const reverse = useReverse({ product: "/products/:productId" });
325
+ return (
326
+ <a data-testid="link" href={reverse("product", { productId: "2" })}>
327
+ {productId}
328
+ </a>
329
+ );
330
+ }
331
+
332
+ it("resolves params + reverse + Outlet through the layout chain", async () => {
333
+ const { getByTestId, router } = await renderRoute(
334
+ [
335
+ { path: "/products", Component: Layout }, // layout (root)
336
+ { path: "/products/:productId", Component: Product }, // leaf (last)
337
+ ],
338
+ { initialUrl: "/products/1" },
339
+ );
340
+ expect(getByTestId("shell").textContent).toBe("shell");
341
+ expect(getByTestId("link").getAttribute("href")).toBe("/products/2");
342
+
343
+ await router.navigate("/products/2"); // client-only nav, re-resolves the same routes
344
+ expect(router.pathname()).toBe("/products/2");
345
+ });
346
+ ```
347
+
348
+ `RenderRouteSpec = { path, Component, layout?, loaderIds?, name? }`. The array
349
+ is the layout chain root-to-leaf; the **last** entry is the leaf route. Seed
350
+ loader reads with `options.loaderData` keyed by the loader's `$$id`; attach a
351
+ loader to a specific layout via that spec's `loaderIds`:
352
+
353
+ ```tsx
354
+ const CartLoader = {
355
+ __brand: "loader",
356
+ $$id: "loaders/cart#CartLoader",
357
+ } as any;
358
+ await renderRoute(
359
+ [
360
+ { path: "/shop", Component: CartLayout, loaderIds: [CartLoader.$$id] },
361
+ { path: "/shop/item", Component: Page },
362
+ ],
363
+ { initialUrl: "/shop/item", loaderData: { [CartLoader.$$id]: { count: 3 } } },
364
+ );
365
+ ```
366
+
367
+ Seed `useHandle` reads with `handles: [[handle, pushedValues[]]]` and
368
+ `useLocationState` with `locationState: [[def, value]]` (both by reference).
369
+ Handle data is accumulated GLOBALLY (not segment-scoped like loaders), so a
370
+ LAYOUT component reading a handle (a `DetailLayout`/`ActionToolbar` reading
371
+ `EditTarget`/`PageEyebrow`) sees the seeded values, not just the leaf route.
372
+
373
+ Model an `include('/shop', …)` mount with the `mount` option: it wraps the
374
+ segment chain in a MountContext exactly as production, so `useMount()` returns
375
+ the prefix and `useHref`/`useReverse` resolve mount-prefixed URLs — a
376
+ mount-relative subtree (`/c/:slug` mounted under `/shop`) becomes reproducible at
377
+ the unit layer instead of e2e-only:
378
+
379
+ ```tsx
380
+ await renderRoute([{ path: "/c/wine", Component: PDP }], { mount: "/shop" });
381
+ // useMount() -> "/shop"; useReverse({ product: "/c/:slug" })("product", { slug: "wine" }) -> "/shop/c/wine"
382
+ ```
383
+
384
+ Don't confuse this with an OPTIONAL param in the matched pattern: `/:locale?/c/:group`
385
+ at `/en/c/wine` auto-fills `locale` from the match, so `reverse("group", { group })`
386
+ returns `/en/c/group` with NO `mount` needed (production parity — `useReverse`
387
+ merges `useParams()`). Use `mount` only for an `include()` prefix; a param-bearing
388
+ mount like `include("/:locale?", …)` resolves to a concrete prefix you pass as
389
+ `mount: "/en"`. A locale "dropping" from a reversed URL in a test is usually a
390
+ missing `mount` seed, not an auto-fill gap.
391
+
392
+ FIDELITY CAVEAT — this is the **client tree only**. It does NOT catch
393
+ server/client boundary reference-identity remount bugs, real Flight
394
+ serialization errors, loader execution, middleware, or handler ordering. Those
395
+ are `renderToFlightString` / e2e territory. Loader data is seeded, never run.
396
+ Needs a DOM env (`// @vitest-environment happy-dom`, or jsdom) and the consumer
397
+ must install `@testing-library/react` (optional peer).
398
+
399
+ CATCH — streaming `use(promise)` Suspense content (e.g. an async breadcrumb
400
+ `content: Promise<ReactNode>`): a plain `Promise.resolve(node)` does NOT flush
401
+ its Suspense retry in RTL/happy-dom (renderRoute renders internally, not inside
402
+ an awaited `act`), so the DOM stays on the fallback. Assert the **pending**
403
+ fallback with a never-resolving `new Promise(() => {})`; for the **arrived**
404
+ state pass an already-settled promise so `use()` reads it synchronously:
405
+ `const p = Promise.resolve(node) as any; p.status = "fulfilled"; p.value = node;`.
406
+ The real pending→resolved transition is an e2e concern.
407
+
408
+ ARIA GOTCHA — query a `<Link>` by `getByRole("link")` only when it renders a bare
409
+ anchor. An explicit `role` on the link (e.g. `<Link role="tab">` in a tablist)
410
+ OVERRIDES the anchor's implicit `link` role, so `getByRole("link")` finds
411
+ nothing — query the explicit role (`getByRole("tab")`) or fall back to
412
+ `getByText`/`getByTestId` and assert `getAttribute("href")`.
413
+
414
+ ### Type-level tests — make misuse fail to compile
415
+
416
+ The reverse/href/params/env types are a real contract; a wrong route name,
417
+ missing param, or unknown binding should be a COMPILE error, not a runtime
418
+ surprise. This is the highest signal-per-cost test in the suite, but it runs at
419
+ typecheck time, not in the vitest runner — so it is its own layer, wired into CI
420
+ as a real step (`pnpm run typecheck` / `tsc --noEmit`). Three recipes, smallest
421
+ first:
422
+
423
+ 1. Negative assertions with `@ts-expect-error` (a runtime test cannot do this) —
424
+ the directive ERRORS if the line below ever starts compiling, so a regressed
425
+ guard fails the typecheck:
426
+
427
+ ```ts
428
+ import { useReverse } from "@rangojs/router/client";
429
+ const reverse = useReverse({ product: "/products/:productId" });
430
+ reverse("product", { productId: "2" }); // ok
431
+ // @ts-expect-error missing required param
432
+ reverse("product", {});
433
+ // @ts-expect-error unknown route name
434
+ reverse("nope", {});
435
+ ```
436
+
437
+ 2. Positive assertions with vitest's `expectTypeOf` — for pinning an INFERRED
438
+ type (a loader's return, a parsed search schema, a handle's accumulated
439
+ shape), in a normal `*.test.ts`:
440
+
441
+ ```ts
442
+ import { expectTypeOf } from "vitest";
443
+ expectTypeOf(await runLoader(cartLoaderBody)).toEqualTypeOf<{
444
+ count: number;
445
+ }>();
446
+ ```
447
+
448
+ 3. A dedicated `*.test-d.ts` + `tsconfig.types.json` (extends base, includes only
449
+ those files; run `tsc -p tsconfig.types.json --noEmit`) for a large type
450
+ suite — the pattern rango itself uses for its augmentation contracts. Recipe 1
451
+ is enough for most apps; reach for 3 only when inline assertions clutter
452
+ runtime tests.
453
+
454
+ ## Integration recipes
455
+
456
+ ### dispatch — request -> Response, without Flight
457
+
458
+ In-process matching + middleware, no RSC render. Covers `308` redirects
459
+ (trailing slash etc.) with `Location`, `404`, response routes
460
+ (json/text/html/xml/md with content negotiation), and **global + route-level
461
+ middleware** short-circuits with full `next()`/throw/header+cookie fidelity. It
462
+ reuses the router's own `previewMatch`, so middleware collection is the router's,
463
+ not a re-implementation. Hitting an RSC (component) route throws a clear
464
+ directive error.
465
+
466
+ So `dispatch` IS the way to exercise a RESPONSE route's real route-level
467
+ middleware chain (the guard stack) against the actual registered tree. The gap:
468
+ a COMPONENT route's guard stack cannot run here (dispatch refuses it, and
469
+ `renderToFlightString`/`renderRoute` don't run route middleware) — assert that at
470
+ e2e, or extract the middleware fn and unit-test it with `runMiddleware`.
471
+
472
+ SETUP CAVEAT (use the preset): `@rangojs/router` resolves to server-only STUBS
473
+ outside the `react-server` condition (urls/createRouter/cookies/getRequestContext
474
+ throw), and importing your router also pulls `@vitejs/plugin-rsc/rsc` (whose body
475
+ imports Vite virtuals). Vitest does not apply the `react-server` condition to
476
+ bare-package resolution. The preset `@rangojs/router/testing/vitest` handles all
477
+ of it — alias `@rangojs/router` to real impls + stub the virtuals — so no
478
+ per-file `vi.mock` is needed. Spread `rangoTestConfig(...)` into your `test`
479
+ block:
480
+
481
+ ```ts
482
+ // vitest.config.ts
483
+ import { defineConfig } from "vitest/config";
484
+ import { rangoTestConfig } from "@rangojs/router/testing/vitest";
485
+ export default defineConfig({
486
+ test: {
487
+ globals: true,
488
+ include: ["test/**/*.test.{ts,tsx}"],
489
+ environment: "node",
490
+ ...rangoTestConfig({ preset: "cloudflare" }),
491
+ },
492
+ });
493
+ ```
494
+
495
+ `rangoTestConfig` returns BOTH the resolve `alias` entries AND
496
+ `server.deps.inline: [/@rangojs[/\\]router/]`. The `deps.inline` half is
497
+ mandatory for an installed (node_modules) consumer: `@rangojs/router` ships as
498
+ TypeScript source, Vitest externalizes node_modules by default, and Node >= 23
499
+ refuses to type-strip `.ts` under `node_modules`
500
+ (`ERR_UNSUPPORTED_NODE_MODULES_TYPE_STRIPPING`) — `deps.inline` forces Vite (not
501
+ Node) to transpile rango's source. The preset entry itself ships as compiled JS,
502
+ so the `import { rangoTestConfig }` line loads under plain Node config loading.
503
+ (If you need only the aliases, `rangoTestAliases(...)` is still exported, but then
504
+ you must wire `server.deps.inline` yourself.)
505
+
506
+ LIMITATION: the FULL router usually can't be imported in a bare test —
507
+ `Prerender()`/`createLoader()` need the plugin-injected `$$id` (real `Prerender()`
508
+ throws "missing $$id"). Build a router from a `Prerender`-free include (your API
509
+ routes); `dispatch` accepts the public router type with no cast:
510
+
511
+ ```ts
512
+ import { describe, it, expect } from "vitest";
513
+ import { dispatch } from "@rangojs/router/testing";
514
+ import { createRouter } from "@rangojs/router";
515
+ import { apiPatterns } from "../src/api/urls"; // path.json(...) routes only
516
+
517
+ const router = createRouter().routes(apiPatterns);
518
+
519
+ it("serializes a JSON response route (auto-wrapped under data)", async () => {
520
+ const res = await dispatch(router, "/health");
521
+ expect(res.status).toBe(200);
522
+ expect(await res.json()).toEqual({ data: { status: "ok" } });
523
+ });
524
+
525
+ it("maps a thrown RouterError to its status + typed JSON envelope", async () => {
526
+ const res = await dispatch(router, "/products/999");
527
+ expect(res.status).toBe(404);
528
+ expect((await res.json()).error.code).toBe("NOT_FOUND");
529
+ });
530
+ ```
531
+
532
+ ### renderToFlightString — real async Server Component
533
+
534
+ A REAL Flight render of an async Server Component, in plain node — but ONLY
535
+ under the `react-server` condition (see the next section for the vitest
536
+ project). The render runs inside a request context, so async components can call
537
+ `getRequestContext()`, read params, cookies, etc.
538
+
539
+ ```tsx
540
+ // flight.rsc-test.tsx (note the *.rsc-test suffix)
541
+ import { describe, it, expect } from "vitest";
542
+ import { renderToFlightString } from "@rangojs/router/testing/flight";
543
+ // Matchers are a SEPARATE subpath (they import vitest); renderToFlightString does not.
544
+ import { flightMatchers } from "@rangojs/router/testing/flight-matchers";
545
+
546
+ expect.extend(flightMatchers);
547
+
548
+ // Keep components PURE leaves: take data as props. Do NOT import a server API
549
+ // (getRequestContext, cookies) from the `@rangojs/router` barrel — under the
550
+ // react-server condition the bare specifier resolves to the throwing stub, so
551
+ // it cannot be flight-tested in a bare consumer project.
552
+ async function Greeting({ name }: { name: string }) {
553
+ await Promise.resolve();
554
+ return <div>Hello {name}!</div>;
555
+ }
556
+ async function ItemView({ id }: { id: string }) {
557
+ return <span>id={id}</span>;
558
+ }
559
+
560
+ it("renders text and props", async () => {
561
+ expect(await renderToFlightString(<Greeting name="Ada" />)).toMatchFlight(
562
+ "Ada",
563
+ );
564
+ expect(await renderToFlightString(<ItemView id="42" />)).toMatchFlight("42");
565
+ });
566
+
567
+ it("matches a normalized snapshot", async () => {
568
+ expect(
569
+ await renderToFlightString(<Greeting name="World" />),
570
+ ).toMatchFlightSnapshot();
571
+ });
572
+ ```
573
+
574
+ `toMatchFlight(substring)` asserts the normalized Flight string CONTAINS the
575
+ substring (containment, not equality — the row framing is an internal serializer
576
+ detail). `toMatchFlightSnapshot()` snapshots the normalized payload. SCOPE:
577
+ `renderToFlightString` returns the wire STRING; for typed assertions on a client
578
+ boundary's props, use `renderServerTree` (next).
579
+
580
+ ### renderServerTree — serialize then deserialize to an inspectable tree
581
+
582
+ Same react-server project. Serializes the real Flight, then deserializes it to a
583
+ React element tree you can traverse. The win over the wire string: a client
584
+ boundary's props come back as REAL JS values (a `Date` is a `Date`), and you can
585
+ confirm a `"use client"` component crossed the boundary (an `I` row) vs being
586
+ inlined. No hydration / no interaction (that is the e2e tier).
587
+
588
+ ```tsx
589
+ import { it, expect } from "vitest";
590
+ import {
591
+ renderServerTree,
592
+ findClientBoundaries,
593
+ } from "@rangojs/router/testing/flight";
594
+ import { PriceTag } from "./PriceTag.client.js"; // "use client"
595
+
596
+ // One line registers every island so it serializes as a real boundary (the rsc
597
+ // project does not apply the "use client" transform).
598
+ const clientModules = import.meta.glob("./*.client.tsx", { eager: true });
599
+
600
+ async function Panel({ amount, asOf }: { amount: number; asOf: Date }) {
601
+ await Promise.resolve();
602
+ return <PriceTag amount={amount} currency="USD" asOf={asOf} />;
603
+ }
604
+
605
+ it("client props survive the round trip", async () => {
606
+ const { flight, tree } = await renderServerTree(
607
+ <Panel amount={19.5} asOf={new Date("2026-01-02T00:00:00Z")} />,
608
+ { clientModules },
609
+ );
610
+ expect(flight).toMatchFlight("PriceTag"); // wire assertions still work
611
+ const [tag] = findClientBoundaries(tree, "PriceTag");
612
+ expect(tag.props.amount).toBe(19.5); // a real number
613
+ expect(tag.props.asOf).toBeInstanceOf(Date); // a real Date, not "$D..."
614
+ });
615
+ ```
616
+
617
+ `findClientBoundaries(tree, name?)` always returns an array (`{ id, name, props,
618
+ element }[]`) in document order, optionally filtered by export name; destructure
619
+ `const [tag] = …` for one island, assert `.length` when count matters (missing
620
+ name -> `[]`). A true interactive, clickable DOM `renderServer` is intentionally
621
+ NOT shipped — in-process happy-dom hydration re-tests React and misses
622
+ server/client divergence (which needs a real browser). Use e2e for interaction.
623
+
624
+ ## E2E recipes (Playwright)
625
+
626
+ Wire the harness once, passing your own Playwright `test`/`expect` (so
627
+ `@rangojs/router/testing/e2e` never imports `@playwright/test` at runtime — it is
628
+ an optional peer you install). Import the harness from the **`/e2e` entry** — the
629
+ unit barrel is not loadable in a plain Playwright runner:
630
+
631
+ ```ts
632
+ // e2e/helper.ts
633
+ import { test, expect } from "@playwright/test";
634
+ import { createRangoE2E } from "@rangojs/router/testing/e2e";
635
+
636
+ export const e2e = createRangoE2E({
637
+ test,
638
+ expect,
639
+ defaultRoot: new URL("..", import.meta.url).pathname, // your app root
640
+ });
641
+ export const { useFixture, parityDescribe, expectParity, rangoMatchers } = e2e;
642
+ ```
643
+
644
+ ### parityDescribe REPLACES hand-titling `(production)`
645
+
646
+ This is THE mechanism that satisfies the dev+prod mandate structurally. One
647
+ declaration registers a dev describe (`name`) AND a production describe
648
+ (`` `${name} (production)` ``) from one body — the `(production)` suffix is
649
+ generated, so the prod suite can never drift into the dev bucket. Use `f.url(...)`
650
+ for navigation.
651
+
652
+ ```ts
653
+ import { test, expect } from "@playwright/test";
654
+ import { parityDescribe, rangoMatchers } from "./helper";
655
+ // rangoMatchers ships the type augmentation, so `expect(page).toHaveRangoPathname`
656
+ // is typed after extend.
657
+ expect.extend(rangoMatchers);
658
+
659
+ parityDescribe("product navigation", (f) => {
660
+ test("navigates to a product and updates the pathname", async ({ page }) => {
661
+ await page.goto(f.url("/"));
662
+ await page.getByTestId("product-link").click();
663
+ await expect(page).toHaveRangoPathname("/products/1");
664
+ });
665
+ });
666
+ ```
667
+
668
+ The body runs verbatim against a dev server (`pnpm dev`) and a built+previewed
669
+ server (`pnpm build` + `pnpm preview`). `useFixture` handles spawn, dep-optimizer
670
+ warmup, cross-platform process-group kill, and teardown.
671
+
672
+ ### expectParity — JS path vs no-JS progressive enhancement
673
+
674
+ Runs one intent over the JS path and a fresh no-JS context, asserting the
675
+ observed testids, pathname, and cookies match. CONTRACT: PE parity only holds if
676
+ the submit target is a real `<form>` (no-JS does a native POST). Cookie
677
+ observation is `document.cookie` (non-HttpOnly only) in v1.
678
+
679
+ ```ts
680
+ parityDescribe("add to cart parity", (f) => {
681
+ test("JS and no-JS produce the same result", async ({ page }) => {
682
+ await page.goto(f.url("/products/1"));
683
+ await expectParity(
684
+ page,
685
+ { submit: { testId: "add-to-cart-form", data: { qty: "2" } } },
686
+ { observe: ["cart-count", "flash"] },
687
+ );
688
+ });
689
+ });
690
+ ```
691
+
692
+ `intent` is `{ navigate: string }` or `{ submit: { testId, data? } }`. Other
693
+ helpers from `createRangoE2E`: `waitForHydration`, `expectNoReload`,
694
+ `expectNoPageError`, `testId`, `waitForNavigation`, `goBack`/`goForward`,
695
+ `testNoJs` (a `test` with JS disabled). `rangoMatchers` ships
696
+ `toHaveRangoPathname` only — `toHaveSegments`/`toHaveParams` are a documented
697
+ future addition (they need a client-emitted signal that does not exist yet; do
698
+ not assume them).
699
+
700
+ ## Cache / SWR / prerender recipes
701
+
702
+ The `X-Rango-Cache` header is emitted **only** when the gate is on:
703
+ `createRouter({ debugCacheSignal: true })` or `process.env.RANGO_TEST_SIGNALS === "1"`.
704
+ Off by default — zero production surface. v1 status is COARSE (route-level, keyed
705
+ by the route key — the route NAME, e.g. `product.detail`, NOT the URL pattern),
706
+ not per-individual-segment. `assertCacheStatus` reads that header.
707
+
708
+ ```ts
709
+ // In a Playwright e2e, import cache-status helpers from the e2e entry (the
710
+ // `@rangojs/router/testing` barrel is Vitest-only — it pulls a build virtual).
711
+ import { assertCacheStatus } from "@rangojs/router/testing/e2e";
712
+
713
+ // e2e (the gate must be enabled on the app under test). The segment key is the
714
+ // route NAME the header carries, not the URL pattern ("/products/:id").
715
+ const res = await page.request.get(f.url("/products/1"));
716
+ assertCacheStatus(res, "product.detail", "miss");
717
+ const res2 = await page.request.get(f.url("/products/1"));
718
+ assertCacheStatus(res2, "product.detail", "hit");
719
+ ```
720
+
721
+ Statuses: `"hit" | "miss" | "stale" | "prerendered" | "passthrough"`.
722
+
723
+ Zero-prod-surface alternative — the telemetry sink (no header at all):
724
+
725
+ ```ts
726
+ import { createCacheSink, filterCacheDecisions } from "@rangojs/router/testing";
727
+ const { sink, events } = createCacheSink();
728
+ const router = createRouter({ telemetry: sink /* ... */ }).routes(urlpatterns);
729
+ // ...drive a request...
730
+ const decisions = filterCacheDecisions(events);
731
+ expect(decisions[0].segments?.[0].cacheStatus).toBe("hit");
732
+ ```
733
+
734
+ PRERENDER: a pre-rendered route is **indistinguishable from a cache hit by
735
+ design** — the worker handles every request and looks up a stored Flight payload
736
+ (see `/prerender`). The browser cannot tell. So you cannot assert "prerendered"
737
+ from the rendered DOM; assert it via the signal (`assertCacheStatus(res, seg,
738
+ "prerendered")`), and run prerender assertions in **production** mode (build-time
739
+ artifacts only exist after `pnpm build`).
740
+
741
+ ## Anti-patterns and gotchas
742
+
743
+ - **No dev-only e2e.** A `useFixture({ mode: "build" })` describe whose title
744
+ omits `(production)` silently lands in the dev bucket — prod coverage lost,
745
+ no error. Always use `parityDescribe`; never hand-title. `(prod)`,
746
+ `-build`, `-prod` do NOT count — the bucketing matches the literal
747
+ `(production)`.
748
+ - **Don't hand-mock the router provider** to test a client component — use
749
+ `renderRoute`, which mounts the real `NavigationProvider`.
750
+ - **Don't call `createLoader(...)` in a unit test** and try to invoke it.
751
+ Extract the body and pass it to `runLoader`.
752
+ - **`dispatch` needs the plugin-rsc mock** (or a Vite-RSC env). A bare import of
753
+ your router throws on Vite virtual modules otherwise.
754
+ - **`renderToFlightString` is not a node test.** It only runs under the
755
+ react-server vitest project; name files `*.rsc-test.{ts,tsx}` and run
756
+ `pnpm test:unit:rsc`. The main vitest project must NOT set the react-server
757
+ condition (it would flip React to the no-hooks server build and break every
758
+ `renderRoute`/client test).
759
+ - **Running an e2e subset:** add `--no-deps` — `--grep` does NOT filter
760
+ dependency projects, so grepping one production test otherwise pulls in the
761
+ whole dev suite. And `--grep` is a regex: a pasted title containing
762
+ `(production)` / `:locale?` / `[...]` mis-matches; grep a metacharacter-free
763
+ fragment.
764
+
765
+ ## Pre-push checklist (mirror CLAUDE.md)
766
+
767
+ Before pushing, run all of these and fix any failure:
768
+
769
+ 1. `pnpm run typecheck` (or `pnpm exec tsc --noEmit`)
770
+ 2. `pnpm run test:unit` (node + DOM vitest)
771
+ 3. `pnpm run test:unit:rsc` (the react-server Flight project)
772
+ 4. `pnpm run lint`
773
+ 5. `pnpm run format`
774
+
775
+ And: **every e2e has a production counterpart.** `parityDescribe` makes this
776
+ automatic — if you wrote a plain `test.describe` for a behavior, convert it.