@rangojs/router 0.0.0-experimental.97 → 0.0.0-experimental.98914650

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 (356) hide show
  1. package/README.md +24 -9
  2. package/dist/bin/rango.js +157 -63
  3. package/dist/testing/vitest.js +82 -0
  4. package/dist/vite/index.js +1584 -639
  5. package/package.json +71 -21
  6. package/skills/api-client/SKILL.md +211 -0
  7. package/skills/breadcrumbs/SKILL.md +60 -0
  8. package/skills/bundle-analysis/SKILL.md +159 -0
  9. package/skills/cache-guide/SKILL.md +222 -30
  10. package/skills/caching/SKILL.md +263 -8
  11. package/skills/composability/SKILL.md +27 -2
  12. package/skills/css/SKILL.md +76 -0
  13. package/skills/document-cache/SKILL.md +78 -55
  14. package/skills/handler-use/SKILL.md +3 -1
  15. package/skills/hooks/SKILL.md +235 -28
  16. package/skills/host-router/SKILL.md +122 -22
  17. package/skills/i18n/SKILL.md +276 -0
  18. package/skills/intercept/SKILL.md +29 -5
  19. package/skills/layout/SKILL.md +13 -9
  20. package/skills/links/SKILL.md +173 -17
  21. package/skills/loader/SKILL.md +170 -23
  22. package/skills/middleware/SKILL.md +16 -10
  23. package/skills/migrate-nextjs/SKILL.md +38 -16
  24. package/skills/mime-routes/SKILL.md +27 -0
  25. package/skills/observability/SKILL.md +137 -0
  26. package/skills/parallel/SKILL.md +11 -7
  27. package/skills/prerender/SKILL.md +14 -33
  28. package/skills/rango/SKILL.md +250 -25
  29. package/skills/react-compiler/SKILL.md +168 -0
  30. package/skills/response-routes/SKILL.md +114 -47
  31. package/skills/route/SKILL.md +42 -5
  32. package/skills/router-setup/SKILL.md +3 -3
  33. package/skills/server-actions/SKILL.md +78 -42
  34. package/skills/tailwind/SKILL.md +27 -3
  35. package/skills/testing/SKILL.md +129 -0
  36. package/skills/testing/bindings.md +89 -0
  37. package/skills/testing/cache-prerender.md +124 -0
  38. package/skills/testing/client-components.md +122 -0
  39. package/skills/testing/e2e-parity.md +125 -0
  40. package/skills/testing/flight.md +92 -0
  41. package/skills/testing/handles.md +129 -0
  42. package/skills/testing/loader.md +128 -0
  43. package/skills/testing/middleware.md +99 -0
  44. package/skills/testing/render-handler.md +121 -0
  45. package/skills/testing/response-routes.md +95 -0
  46. package/skills/testing/reverse-and-types.md +84 -0
  47. package/skills/testing/server-actions.md +107 -0
  48. package/skills/testing/server-tree.md +128 -0
  49. package/skills/testing/setup.md +120 -0
  50. package/skills/typesafety/SKILL.md +316 -26
  51. package/skills/use-cache/SKILL.md +36 -5
  52. package/skills/vercel/SKILL.md +107 -0
  53. package/skills/view-transitions/SKILL.md +294 -0
  54. package/src/__augment-tests__/augment.ts +81 -0
  55. package/src/__augment-tests__/augmented.check.ts +116 -0
  56. package/src/__internal.ts +0 -65
  57. package/src/browser/action-coordinator.ts +53 -36
  58. package/src/browser/action-fence.ts +47 -0
  59. package/src/browser/app-shell.ts +14 -27
  60. package/src/browser/cookie-name.ts +140 -0
  61. package/src/browser/event-controller.ts +37 -143
  62. package/src/browser/history-state.ts +21 -0
  63. package/src/browser/index.ts +3 -3
  64. package/src/browser/invalidate-client-cache.ts +52 -0
  65. package/src/browser/navigation-bridge.ts +30 -59
  66. package/src/browser/navigation-client.ts +96 -84
  67. package/src/browser/navigation-store-handle.ts +38 -0
  68. package/src/browser/navigation-store.ts +32 -82
  69. package/src/browser/navigation-transaction.ts +9 -59
  70. package/src/browser/partial-update.ts +60 -127
  71. package/src/browser/prefetch/cache.ts +82 -72
  72. package/src/browser/prefetch/fetch.ts +108 -33
  73. package/src/browser/prefetch/queue.ts +6 -3
  74. package/src/browser/rango-state.ts +157 -115
  75. package/src/browser/react/Link.tsx +0 -2
  76. package/src/browser/react/NavigationProvider.tsx +41 -48
  77. package/src/browser/react/ScrollRestoration.tsx +10 -6
  78. package/src/browser/react/filter-segment-order.ts +0 -2
  79. package/src/browser/react/index.ts +0 -48
  80. package/src/browser/react/location-state-shared.ts +166 -8
  81. package/src/browser/react/location-state.ts +39 -14
  82. package/src/browser/react/use-action.ts +6 -15
  83. package/src/browser/react/use-handle.ts +17 -14
  84. package/src/browser/react/use-link-status.ts +0 -4
  85. package/src/browser/react/use-navigation.ts +0 -3
  86. package/src/browser/react/use-params.ts +11 -11
  87. package/src/browser/react/use-reverse.ts +106 -0
  88. package/src/browser/react/use-router.ts +20 -5
  89. package/src/browser/react/use-search-params.ts +0 -5
  90. package/src/browser/react/use-segments.ts +0 -13
  91. package/src/browser/response-adapter.ts +52 -1
  92. package/src/browser/rsc-router.tsx +70 -34
  93. package/src/browser/scroll-restoration.ts +22 -14
  94. package/src/browser/segment-structure-assert.ts +2 -2
  95. package/src/browser/server-action-bridge.ts +168 -44
  96. package/src/browser/types.ts +36 -21
  97. package/src/browser/validate-redirect-origin.ts +43 -16
  98. package/src/build/collect-fallback-refs.ts +107 -0
  99. package/src/build/generate-manifest.ts +60 -35
  100. package/src/build/generate-route-types.ts +3 -0
  101. package/src/build/index.ts +8 -2
  102. package/src/build/prefix-tree-utils.ts +123 -0
  103. package/src/build/route-trie.ts +89 -10
  104. package/src/build/route-types/codegen.ts +4 -4
  105. package/src/build/route-types/include-resolution.ts +1 -1
  106. package/src/build/route-types/param-extraction.ts +6 -3
  107. package/src/build/route-types/per-module-writer.ts +7 -4
  108. package/src/build/route-types/router-processing.ts +122 -22
  109. package/src/build/route-types/scan-filter.ts +1 -1
  110. package/src/build/route-types/source-scan.ts +118 -0
  111. package/src/build/runtime-discovery.ts +9 -20
  112. package/src/cache/cache-error.ts +104 -0
  113. package/src/cache/cache-policy.ts +68 -28
  114. package/src/cache/cache-runtime.ts +134 -32
  115. package/src/cache/cache-scope.ts +100 -74
  116. package/src/cache/cache-tag.ts +98 -0
  117. package/src/cache/cf/cf-cache-store.ts +2255 -238
  118. package/src/cache/cf/index.ts +6 -16
  119. package/src/cache/document-cache.ts +61 -20
  120. package/src/cache/handle-snapshot.ts +63 -0
  121. package/src/cache/index.ts +22 -20
  122. package/src/cache/memory-segment-store.ts +136 -37
  123. package/src/cache/profile-registry.ts +6 -30
  124. package/src/cache/read-through-swr.ts +41 -11
  125. package/src/cache/segment-codec.ts +0 -16
  126. package/src/cache/tag-invalidation.ts +230 -0
  127. package/src/cache/types.ts +33 -100
  128. package/src/cache/vercel/index.ts +11 -0
  129. package/src/cache/vercel/vercel-cache-store.ts +799 -0
  130. package/src/client.rsc.tsx +6 -21
  131. package/src/client.tsx +25 -61
  132. package/src/component-utils.ts +19 -0
  133. package/src/context-var.ts +17 -5
  134. package/src/decode-loader-results.ts +36 -0
  135. package/src/defer.ts +196 -0
  136. package/src/deps/ssr.ts +0 -1
  137. package/src/errors.ts +30 -4
  138. package/src/handle.ts +31 -23
  139. package/src/handles/MetaTags.tsx +0 -14
  140. package/src/handles/breadcrumbs.ts +16 -5
  141. package/src/handles/meta.ts +0 -39
  142. package/src/host/cookie-handler.ts +0 -36
  143. package/src/host/errors.ts +0 -24
  144. package/src/host/index.ts +8 -2
  145. package/src/host/pattern-matcher.ts +7 -50
  146. package/src/host/router.ts +107 -99
  147. package/src/host/testing.ts +40 -27
  148. package/src/host/types.ts +37 -4
  149. package/src/host/utils.ts +1 -1
  150. package/src/href-client.ts +137 -22
  151. package/src/index.rsc.ts +63 -9
  152. package/src/index.ts +64 -9
  153. package/src/internal-debug.ts +2 -4
  154. package/src/loader-store.ts +500 -0
  155. package/src/loader.rsc.ts +20 -13
  156. package/src/loader.ts +12 -11
  157. package/src/missing-id-error.ts +68 -0
  158. package/src/network-error-thrower.tsx +1 -6
  159. package/src/outlet-provider.tsx +1 -5
  160. package/src/prerender/param-hash.ts +10 -11
  161. package/src/prerender/store.ts +32 -37
  162. package/src/prerender.ts +61 -6
  163. package/src/redirect-origin.ts +100 -0
  164. package/src/response-utils.ts +9 -0
  165. package/src/reverse.ts +65 -40
  166. package/src/root-error-boundary.tsx +1 -19
  167. package/src/route-content-wrapper.tsx +7 -72
  168. package/src/route-definition/dsl-helpers.ts +244 -281
  169. package/src/route-definition/helper-factories.ts +29 -139
  170. package/src/route-definition/helpers-types.ts +40 -17
  171. package/src/route-definition/redirect.ts +43 -9
  172. package/src/route-definition/resolve-handler-use.ts +6 -0
  173. package/src/route-definition/use-item-types.ts +32 -0
  174. package/src/route-map-builder.ts +0 -16
  175. package/src/route-types.ts +19 -41
  176. package/src/router/basename.ts +14 -0
  177. package/src/router/content-negotiation.ts +15 -15
  178. package/src/router/error-handling.ts +13 -17
  179. package/src/router/find-match.ts +44 -23
  180. package/src/router/handler-context.ts +4 -41
  181. package/src/router/intercept-resolution.ts +14 -19
  182. package/src/router/lazy-includes.ts +9 -46
  183. package/src/router/loader-resolution.ts +91 -46
  184. package/src/router/logging.ts +0 -6
  185. package/src/router/manifest.ts +18 -29
  186. package/src/router/match-api.ts +0 -20
  187. package/src/router/match-context.ts +0 -22
  188. package/src/router/match-handlers.ts +57 -58
  189. package/src/router/match-middleware/background-revalidation.ts +0 -7
  190. package/src/router/match-middleware/cache-lookup.ts +150 -271
  191. package/src/router/match-middleware/cache-store.ts +3 -33
  192. package/src/router/match-middleware/intercept-resolution.ts +0 -22
  193. package/src/router/match-middleware/segment-resolution.ts +0 -22
  194. package/src/router/match-pipelines.ts +1 -42
  195. package/src/router/match-result.ts +31 -80
  196. package/src/router/metrics.ts +0 -34
  197. package/src/router/middleware-types.ts +5 -112
  198. package/src/router/middleware.ts +118 -133
  199. package/src/router/navigation-snapshot.ts +0 -51
  200. package/src/router/params-util.ts +23 -0
  201. package/src/router/pattern-matching.ts +62 -67
  202. package/src/router/prerender-match.ts +99 -63
  203. package/src/router/preview-match.ts +3 -1
  204. package/src/router/request-classification.ts +28 -62
  205. package/src/router/revalidation.ts +50 -56
  206. package/src/router/route-snapshot.ts +0 -1
  207. package/src/router/router-context.ts +0 -27
  208. package/src/router/router-interfaces.ts +68 -35
  209. package/src/router/router-options.ts +55 -1
  210. package/src/router/router-registry.ts +2 -5
  211. package/src/router/segment-resolution/fresh.ts +44 -63
  212. package/src/router/segment-resolution/helpers.ts +34 -0
  213. package/src/router/segment-resolution/loader-cache.ts +40 -37
  214. package/src/router/segment-resolution/revalidation.ts +203 -285
  215. package/src/router/segment-resolution/static-store.ts +19 -5
  216. package/src/router/segment-resolution/streamed-handler-telemetry.ts +52 -0
  217. package/src/router/segment-resolution/view-transition-default.ts +36 -0
  218. package/src/router/segment-resolution.ts +4 -1
  219. package/src/router/segment-wrappers.ts +0 -3
  220. package/src/router/state-cookie-name.ts +33 -0
  221. package/src/router/substitute-pattern-params.ts +56 -0
  222. package/src/router/telemetry-otel.ts +0 -20
  223. package/src/router/telemetry.ts +96 -19
  224. package/src/router/timeout.ts +0 -20
  225. package/src/router/trie-matching.ts +87 -48
  226. package/src/router/types.ts +9 -63
  227. package/src/router/url-params.ts +0 -5
  228. package/src/router.ts +80 -41
  229. package/src/rsc/handler-context.ts +3 -2
  230. package/src/rsc/handler.ts +83 -78
  231. package/src/rsc/helpers.ts +93 -5
  232. package/src/rsc/index.ts +1 -1
  233. package/src/rsc/json-route-result.ts +38 -0
  234. package/src/rsc/manifest-init.ts +28 -41
  235. package/src/rsc/origin-guard.ts +39 -25
  236. package/src/rsc/progressive-enhancement.ts +12 -1
  237. package/src/rsc/redirect-guard.ts +99 -0
  238. package/src/rsc/response-error.ts +79 -12
  239. package/src/rsc/response-route-handler.ts +76 -62
  240. package/src/rsc/rsc-rendering.ts +41 -60
  241. package/src/rsc/runtime-warnings.ts +23 -10
  242. package/src/rsc/server-action.ts +62 -67
  243. package/src/rsc/ssr-setup.ts +16 -0
  244. package/src/rsc/types.ts +10 -5
  245. package/src/runtime-env.ts +18 -0
  246. package/src/search-params.ts +4 -20
  247. package/src/segment-loader-promise.ts +14 -2
  248. package/src/segment-system.tsx +199 -142
  249. package/src/serialize.ts +243 -0
  250. package/src/server/context.ts +150 -51
  251. package/src/server/cookie-store.ts +80 -5
  252. package/src/server/handle-store.ts +7 -24
  253. package/src/server/loader-registry.ts +5 -24
  254. package/src/server/request-context.ts +165 -87
  255. package/src/ssr/index.tsx +14 -14
  256. package/src/static-handler.ts +10 -13
  257. package/src/testing/cache-status.ts +162 -0
  258. package/src/testing/collect-handle.ts +40 -0
  259. package/src/testing/dispatch.ts +618 -0
  260. package/src/testing/dom.entry.ts +22 -0
  261. package/src/testing/e2e/fixture.ts +188 -0
  262. package/src/testing/e2e/index.ts +128 -0
  263. package/src/testing/e2e/matchers.ts +35 -0
  264. package/src/testing/e2e/page-helpers.ts +272 -0
  265. package/src/testing/e2e/parity.ts +387 -0
  266. package/src/testing/e2e/server.ts +195 -0
  267. package/src/testing/flight-matchers.ts +97 -0
  268. package/src/testing/flight-normalize.ts +11 -0
  269. package/src/testing/flight-runtime.d.ts +57 -0
  270. package/src/testing/flight-tree.ts +682 -0
  271. package/src/testing/flight.entry.ts +52 -0
  272. package/src/testing/flight.ts +232 -0
  273. package/src/testing/generated-routes.ts +183 -0
  274. package/src/testing/index.ts +99 -0
  275. package/src/testing/internal/context.ts +348 -0
  276. package/src/testing/internal/flight-client-globals.ts +30 -0
  277. package/src/testing/internal/seed-vars.ts +54 -0
  278. package/src/testing/render-handler.ts +330 -0
  279. package/src/testing/render-route.tsx +566 -0
  280. package/src/testing/run-loader.ts +378 -0
  281. package/src/testing/run-middleware.ts +205 -0
  282. package/src/testing/vitest-stubs/cloudflare-email.ts +9 -0
  283. package/src/testing/vitest-stubs/cloudflare-workers.ts +21 -0
  284. package/src/testing/vitest-stubs/plugin-rsc.ts +16 -0
  285. package/src/testing/vitest-stubs/version.ts +5 -0
  286. package/src/testing/vitest.ts +305 -0
  287. package/src/theme/ThemeProvider.tsx +0 -52
  288. package/src/theme/ThemeScript.tsx +0 -6
  289. package/src/theme/constants.ts +0 -12
  290. package/src/theme/index.ts +0 -7
  291. package/src/theme/theme-context.ts +1 -5
  292. package/src/theme/theme-script.ts +0 -14
  293. package/src/theme/use-theme.ts +0 -3
  294. package/src/types/boundaries.ts +0 -35
  295. package/src/types/cache-types.ts +13 -4
  296. package/src/types/error-types.ts +30 -90
  297. package/src/types/global-namespace.ts +54 -41
  298. package/src/types/handler-context.ts +97 -22
  299. package/src/types/index.ts +1 -10
  300. package/src/types/loader-types.ts +6 -3
  301. package/src/types/request-scope.ts +0 -19
  302. package/src/types/route-config.ts +6 -50
  303. package/src/types/route-entry.ts +0 -6
  304. package/src/types/segments.ts +18 -14
  305. package/src/urls/include-helper.ts +9 -56
  306. package/src/urls/index.ts +1 -11
  307. package/src/urls/path-helper-types.ts +19 -5
  308. package/src/urls/path-helper.ts +17 -106
  309. package/src/urls/pattern-types.ts +36 -19
  310. package/src/urls/response-types.ts +20 -19
  311. package/src/urls/type-extraction.ts +58 -139
  312. package/src/urls/urls-function.ts +1 -18
  313. package/src/use-loader.tsx +292 -107
  314. package/src/vite/debug.ts +1 -0
  315. package/src/vite/discovery/bundle-postprocess.ts +8 -7
  316. package/src/vite/discovery/discover-routers.ts +95 -82
  317. package/src/vite/discovery/discovery-errors.ts +194 -0
  318. package/src/vite/discovery/prerender-collection.ts +26 -34
  319. package/src/vite/discovery/route-types-writer.ts +40 -84
  320. package/src/vite/discovery/state.ts +39 -1
  321. package/src/vite/discovery/virtual-module-codegen.ts +14 -34
  322. package/src/vite/index.ts +4 -0
  323. package/src/vite/plugin-types.ts +185 -10
  324. package/src/vite/plugins/cjs-to-esm.ts +3 -18
  325. package/src/vite/plugins/client-ref-dedup.ts +0 -11
  326. package/src/vite/plugins/client-ref-hashing.ts +12 -11
  327. package/src/vite/plugins/cloudflare-protocol-stub.ts +1 -21
  328. package/src/vite/plugins/expose-action-id.ts +4 -75
  329. package/src/vite/plugins/expose-id-utils.ts +3 -54
  330. package/src/vite/plugins/expose-ids/export-analysis.ts +76 -34
  331. package/src/vite/plugins/expose-ids/handler-transform.ts +6 -74
  332. package/src/vite/plugins/expose-ids/loader-transform.ts +3 -20
  333. package/src/vite/plugins/expose-ids/router-transform.ts +0 -13
  334. package/src/vite/plugins/expose-internal-ids.ts +57 -67
  335. package/src/vite/plugins/performance-tracks.ts +9 -16
  336. package/src/vite/plugins/refresh-cmd.ts +1 -1
  337. package/src/vite/plugins/use-cache-transform.ts +26 -49
  338. package/src/vite/plugins/vercel-output.ts +258 -0
  339. package/src/vite/plugins/version-injector.ts +2 -32
  340. package/src/vite/plugins/version-plugin.ts +32 -23
  341. package/src/vite/plugins/virtual-entries.ts +35 -17
  342. package/src/vite/rango.ts +148 -115
  343. package/src/vite/router-discovery.ts +220 -68
  344. package/src/vite/utils/ast-handler-extract.ts +15 -31
  345. package/src/vite/utils/bundle-analysis.ts +10 -15
  346. package/src/vite/utils/client-chunks.ts +184 -0
  347. package/src/vite/utils/forward-user-plugins.ts +171 -0
  348. package/src/vite/utils/manifest-utils.ts +4 -59
  349. package/src/vite/utils/package-resolution.ts +1 -73
  350. package/src/vite/utils/prerender-utils.ts +0 -34
  351. package/src/vite/utils/shared-utils.ts +95 -43
  352. package/src/browser/action-response-classifier.ts +0 -99
  353. package/src/browser/react/use-client-cache.ts +0 -58
  354. package/src/browser/shallow.ts +0 -40
  355. package/src/handles/index.ts +0 -7
  356. package/src/router/middleware-cookies.ts +0 -55
@@ -1,16 +1,11 @@
1
1
  import type { ReactNode } from "react";
2
2
  import type { Handler } from "../types.js";
3
- import type {
4
- AllUseItems,
5
- RouteItem,
6
- RouteUseItem,
7
- UseItems,
8
- } from "../route-types.js";
3
+ import type { RouteItem, RouteUseItem, UseItems } from "../route-types.js";
9
4
  import {
10
- getContext,
11
5
  getUrlPrefix,
12
6
  getNamePrefix,
13
7
  getRootScoped,
8
+ requireDslContext,
14
9
  } from "../server/context";
15
10
  import { invariant, DataNotFoundError } from "../errors";
16
11
  import { validateUserRouteName } from "../route-name.js";
@@ -39,40 +34,11 @@ import {
39
34
  resolveHandlerUse,
40
35
  mergeHandlerUse,
41
36
  } from "../route-definition/resolve-handler-use.js";
37
+ import {
38
+ emptySegmentBase,
39
+ runAndValidateUseItems,
40
+ } from "../route-definition/dsl-helpers.js";
42
41
 
43
- /**
44
- * Check if a value is a valid use item
45
- */
46
- const isValidUseItem = (item: any): item is AllUseItems | undefined | null => {
47
- return (
48
- typeof item === "undefined" ||
49
- item === null ||
50
- (item &&
51
- typeof item === "object" &&
52
- "type" in item &&
53
- [
54
- "layout",
55
- "route",
56
- "middleware",
57
- "revalidate",
58
- "parallel",
59
- "intercept",
60
- "loader",
61
- "loading",
62
- "errorBoundary",
63
- "notFoundBoundary",
64
- "when",
65
- "cache",
66
- "transition",
67
- "include",
68
- ].includes(item.type))
69
- );
70
- };
71
-
72
- /**
73
- * Apply URL prefix to a pattern
74
- * Handles edge cases like "/" patterns and double slashes
75
- */
76
42
  function applyUrlPrefix(prefix: string, pattern: string): string {
77
43
  if (!prefix) return pattern;
78
44
  if (pattern === "/") return prefix;
@@ -82,29 +48,17 @@ function applyUrlPrefix(prefix: string, pattern: string): string {
82
48
  return prefix + pattern;
83
49
  }
84
50
 
85
- /**
86
- * Apply name prefix to a route name
87
- */
88
51
  function applyNamePrefix(prefix: string | undefined, name: string): string {
89
52
  if (!prefix) return name;
90
53
  return `${prefix}.${name}`;
91
54
  }
92
55
 
93
- /**
94
- * Resolve response type from path options (set by path.json(), path.text(), etc.)
95
- */
96
56
  function resolveResponseType(
97
57
  options: PathOptions | undefined,
98
58
  ): string | undefined {
99
59
  return options?.[RESPONSE_TYPE];
100
60
  }
101
61
 
102
- /**
103
- * Create path() helper
104
- *
105
- * The path() function is the key new feature - it combines URL pattern
106
- * with handler at the definition site.
107
- */
108
62
  export function createPathHelper<TEnv>(): PathFn<TEnv> {
109
63
  return ((
110
64
  pattern: string,
@@ -112,17 +66,15 @@ export function createPathHelper<TEnv>(): PathFn<TEnv> {
112
66
  optionsOrUse?: PathOptions | (() => UseItems<RouteUseItem>),
113
67
  maybeUse?: () => UseItems<RouteUseItem>,
114
68
  ): RouteItem => {
115
- const store = getContext();
116
- const ctx = store.getStore();
117
- if (!ctx) throw new Error("path() must be called inside urls()");
69
+ const { store, ctx } = requireDslContext(
70
+ "path() must be called inside urls()",
71
+ );
118
72
 
119
73
  invariant(
120
74
  !ctx.parent || ctx.parent.type !== "parallel",
121
75
  "path() cannot be used inside parallel()",
122
76
  );
123
77
 
124
- // Walk the parent chain to prevent path() nested under another path(),
125
- // even when separated by intermediate layouts (e.g. path(layout(path())))
126
78
  {
127
79
  let ancestor = ctx.parent;
128
80
  while (ancestor) {
@@ -134,7 +86,6 @@ export function createPathHelper<TEnv>(): PathFn<TEnv> {
134
86
  }
135
87
  }
136
88
 
137
- // Determine options and use based on argument types
138
89
  let options: PathOptions | undefined;
139
90
  let use: (() => UseItems<RouteUseItem>) | undefined;
140
91
 
@@ -147,49 +98,29 @@ export function createPathHelper<TEnv>(): PathFn<TEnv> {
147
98
  use = maybeUse;
148
99
  }
149
100
 
150
- // Merge handler.use() defaults with explicit use()
151
- // Response routes (path.json, path.text, etc.) only allow middleware + cache
152
101
  const handlerUseFn = resolveHandlerUse(handler);
153
102
  const mountSite = resolveResponseType(options) ? "response" : "path";
154
103
  const mergedUse = mergeHandlerUse(handlerUseFn, use, mountSite);
155
104
 
156
- // Get prefixes from context (set by include())
157
105
  const urlPrefix = getUrlPrefix();
158
106
  const namePrefix = getNamePrefix();
159
107
 
160
- // Apply URL prefix to pattern
161
108
  const prefixedPattern = applyUrlPrefix(urlPrefix, pattern);
162
109
 
163
- // Generate route name - use provided name or generate from pattern
164
110
  const localName =
165
111
  options?.name || `$path_${pattern.replace(/[/:*?]/g, "_")}`;
166
112
  if (options?.name) {
167
113
  validateUserRouteName(options.name);
168
114
  }
169
- // Apply name prefix if set (from include())
170
115
  const routeName = applyNamePrefix(namePrefix, localName);
171
116
 
172
117
  const namespace = `${ctx.namespace}.${store.getNextIndex("route")}.${routeName}`;
173
118
 
174
- // Per-request pruning: skip registration for routes that won't be rendered.
175
- // forRoute is set by loadManifest() to the matched route name. During
176
- // evaluateLazyEntry() (route matching), forRoute is unset so all routes
177
- // register normally. We still increment counters to keep shortCodes stable
178
- // across different routes (needed for segment reconciliation on navigation).
179
- //
180
- // include() does not need its own forRoute pruning. include() creates lazy
181
- // entries that defer handler execution until route matching. When the lazy
182
- // handler eventually runs inside loadManifest(), this path() check already
183
- // covers all routes defined inside the include.
184
119
  if (ctx.forRoute && routeName !== ctx.forRoute) {
185
120
  store.getShortCode("route");
186
121
  return { type: "route" } as RouteItem;
187
122
  }
188
123
 
189
- // Ensure handler is always a function (wrap ReactNode or extract from prerender/static def)
190
- // For prerender stubs (production builds where handler code is evicted),
191
- // handler.handler is undefined — provide a notFound fallback so requests
192
- // for non-prerendered params get 404 instead of "handler is not a function".
193
124
  const wrappedHandler: Handler<any, any, TEnv> =
194
125
  typeof handler === "function"
195
126
  ? (handler as Handler<any, any, TEnv>)
@@ -214,22 +145,13 @@ export function createPathHelper<TEnv>(): PathFn<TEnv> {
214
145
  : () => handler;
215
146
 
216
147
  const entry = {
148
+ ...emptySegmentBase(),
217
149
  id: namespace,
218
150
  shortCode: store.getShortCode("route"),
219
151
  type: "route" as const,
220
152
  parent: ctx.parent,
221
153
  handler: wrappedHandler,
222
- // Store the PREFIXED pattern for route matching
223
154
  pattern: prefixedPattern,
224
- loading: undefined,
225
- middleware: [],
226
- revalidate: [],
227
- errorBoundary: [],
228
- notFoundBoundary: [],
229
- layout: [],
230
- parallel: {},
231
- intercept: [],
232
- loader: [],
233
155
  ...(urlPrefix ? { mountPath: urlPrefix } : {}),
234
156
  ...(isPassthroughHandler(handler)
235
157
  ? {
@@ -255,29 +177,23 @@ export function createPathHelper<TEnv>(): PathFn<TEnv> {
255
177
  : {}),
256
178
  };
257
179
 
258
- // Capture namespace prefix on static handler for build-time reverse() resolution
259
180
  if (isStaticHandler(handler) && handler.$$id && ctx.namePrefix) {
260
181
  (handler as any).$$routePrefix = ctx.namePrefix;
261
182
  }
262
183
 
263
- // Check for duplicate route names (TypeScript should catch this, but runtime check too)
264
184
  invariant(
265
185
  ctx.manifest.get(routeName) === undefined,
266
186
  `Duplicate route name: ${routeName} at ${namespace}`,
267
187
  );
268
188
 
269
- // Register route entry with prefixed name
270
189
  ctx.manifest.set(routeName, entry);
271
190
 
272
- // Register root-scope flag for dot-local reverse resolution
273
191
  registerRouteRootScope(routeName, getRootScoped());
274
192
 
275
- // Also store pattern in a separate map for URL generation
276
193
  if (ctx.patterns) {
277
194
  ctx.patterns.set(routeName, prefixedPattern);
278
195
  }
279
196
 
280
- // Store pattern grouped by URL prefix for separate entry creation
281
197
  if (ctx.patternsByPrefix) {
282
198
  const urlPrefix = getUrlPrefix() || "";
283
199
  if (!ctx.patternsByPrefix.has(urlPrefix)) {
@@ -286,12 +202,10 @@ export function createPathHelper<TEnv>(): PathFn<TEnv> {
286
202
  ctx.patternsByPrefix.get(urlPrefix)!.set(routeName, prefixedPattern);
287
203
  }
288
204
 
289
- // Store trailing slash config if specified
290
205
  if (options?.trailingSlash && ctx.trailingSlash) {
291
206
  ctx.trailingSlash.set(routeName, options.trailingSlash);
292
207
  }
293
208
 
294
- // Store search schema if specified
295
209
  if (options?.search) {
296
210
  if (ctx.searchSchemas) {
297
211
  ctx.searchSchemas.set(routeName, options.search);
@@ -299,12 +213,14 @@ export function createPathHelper<TEnv>(): PathFn<TEnv> {
299
213
  registerSearchSchema(routeName, options.search);
300
214
  }
301
215
 
302
- // Run merged use callback (handler.use defaults + explicit use) if present
303
216
  if (mergedUse) {
304
- const result = store.run(namespace, entry, mergedUse)?.flat(3);
305
- invariant(
306
- Array.isArray(result) && result.every((item) => isValidUseItem(item)),
307
- `path() use() callback must return an array of use items [${namespace}]`,
217
+ const result = runAndValidateUseItems(
218
+ store,
219
+ namespace,
220
+ entry,
221
+ mergedUse,
222
+ "path",
223
+ "use",
308
224
  );
309
225
  return { name: namespace, type: "route", uses: result } as RouteItem;
310
226
  }
@@ -313,10 +229,6 @@ export function createPathHelper<TEnv>(): PathFn<TEnv> {
313
229
  }) as PathFn<TEnv>;
314
230
  }
315
231
 
316
- /**
317
- * Attach response type tag methods (.json, .text, .html, .xml, .md, .image, .stream, .any) to a path helper.
318
- * Each tag wraps the original path() call with the RESPONSE_TYPE option set.
319
- */
320
232
  export function attachPathResponseTags<TEnv>(
321
233
  pathFn: PathFn<TEnv>,
322
234
  ): PathFn<TEnv> & {
@@ -338,7 +250,6 @@ export function attachPathResponseTags<TEnv>(
338
250
  ) => {
339
251
  let options: PathOptions;
340
252
  let use: (() => any[]) | undefined;
341
-
342
253
  if (typeof optionsOrUse === "function") {
343
254
  options = { [RESPONSE_TYPE]: responseType };
344
255
  use = optionsOrUse;
@@ -1,10 +1,5 @@
1
- import type { ReactNode } from "react";
2
- import type { Handler, TrailingSlashMode } from "../types.js";
3
- import type {
4
- AllUseItems,
5
- RouteUseItem,
6
- UrlPatternsBrand,
7
- } from "../route-types.js";
1
+ import type { TrailingSlashMode } from "../types.js";
2
+ import type { AllUseItems, UrlPatternsBrand } from "../route-types.js";
8
3
  import type { SearchSchema } from "../search-params.js";
9
4
  import { RESPONSE_TYPE } from "./response-types.js";
10
5
  import type { DefaultEnv } from "../types.js";
@@ -54,16 +49,6 @@ export interface PathOptions<
54
49
  [RESPONSE_TYPE]?: string;
55
50
  }
56
51
 
57
- /**
58
- * Internal representation of a URL pattern definition
59
- */
60
- export interface PathDefinition {
61
- pattern: string;
62
- name?: string;
63
- handler: ReactNode | Handler<any, any, any>;
64
- use?: RouteUseItem[];
65
- }
66
-
67
52
  /**
68
53
  * Result of urls() - contains the route definitions
69
54
  */
@@ -72,8 +57,6 @@ export interface UrlPatterns<
72
57
  TRoutes extends Record<string, any> = Record<string, string>,
73
58
  TResponses extends Record<string, unknown> = Record<string, unknown>,
74
59
  > {
75
- /** Internal: route definitions */
76
- readonly definitions: PathDefinition[];
77
60
  /** Internal: compiled handler function */
78
61
  readonly handler: () => AllUseItems[];
79
62
  /** Internal: trailing slash config per route name */
@@ -88,6 +71,40 @@ export interface UrlPatterns<
88
71
  readonly _responses?: TResponses;
89
72
  }
90
73
 
74
+ /**
75
+ * Extract the phantom env type carried by a UrlPatterns value.
76
+ */
77
+ export type UrlPatternsEnv<T> =
78
+ T extends UrlPatterns<infer TEnv, any, any> ? TEnv : never;
79
+
80
+ /**
81
+ * Guards `routes()` env compatibility without over-constraining.
82
+ *
83
+ * - An env-agnostic block (its env is `unknown` — e.g. a shared urls() module,
84
+ * or an app that does not augment `Rango.Env`) attaches to any router.
85
+ * - A block carrying a concrete env is accepted only when the router env
86
+ * (`TRouterEnv`) satisfies it; resolves to `never` otherwise, so a
87
+ * `urls<{ DB: D1Database }>()` cannot be mounted on a `createRouter<{}>()`.
88
+ *
89
+ * Use as `patterns: T & EnvCompatible<T, TEnv>` so `T` still infers from the
90
+ * argument — a bare `EnvCompatible<T, TEnv>` parameter sits in a non-inferrable
91
+ * conditional position and would collapse `T` to its constraint.
92
+ *
93
+ * Known limitation: `TRouterEnv extends ...` distributes over a union router env,
94
+ * so a `urls<A>()` block is accepted on `createRouter<A | B>()` even though the
95
+ * `B` arm cannot supply `A`'s env. Suppressing distribution with
96
+ * `[TRouterEnv] extends [...]` would close that edge but breaks the common
97
+ * generic-`TEnv` call sites (a deferred type parameter can't resolve the tuple
98
+ * conditional, so the intersection stops reducing to `T`). A router has one env,
99
+ * so a union env is not a supported pattern; the distributive form is kept.
100
+ */
101
+ export type EnvCompatible<TPatterns, TRouterEnv> =
102
+ unknown extends UrlPatternsEnv<TPatterns>
103
+ ? TPatterns
104
+ : TRouterEnv extends UrlPatternsEnv<TPatterns>
105
+ ? TPatterns
106
+ : never;
107
+
91
108
  /**
92
109
  * Options for include()
93
110
  */
@@ -32,21 +32,32 @@ type ResponseReverseFunction = [DefaultReverseRouteMap] extends [
32
32
  * Symbol marking a route as a response route (non-RSC).
33
33
  * Stored on PathOptions and UrlPatterns to signal the trie to short-circuit.
34
34
  */
35
- export const RESPONSE_TYPE: unique symbol = Symbol.for(
36
- "rangojs.responseType",
37
- ) as any;
35
+ export const RESPONSE_TYPE: unique symbol = Symbol.for("rangojs.responseType");
38
36
 
39
37
  /**
40
- * Handler that must return Response (not ReactNode).
41
- * Used by path.image(), path.stream(), path.any() (binary/streaming data).
38
+ * Shared shape of a response-route handler: a function returning TReturn (or a
39
+ * promise of it), plus an optional composable `use` thunk merged at mount time.
42
40
  */
43
- export type ResponseHandler<TParams = Record<string, string>, TEnv = any> = ((
41
+ type ResponseHandlerOf<
42
+ TReturn,
43
+ TParams = Record<string, string>,
44
+ TEnv = any,
45
+ > = ((
44
46
  ctx: ResponseHandlerContext<TParams, TEnv>,
45
- ) => Response | Promise<Response>) & {
47
+ ) => TReturn | Promise<TReturn>) & {
46
48
  /** Composable default DSL items merged when the handler is mounted. */
47
49
  use?: () => UseItems<ResponseRouteUseItem>;
48
50
  };
49
51
 
52
+ /**
53
+ * Handler that must return Response (not ReactNode).
54
+ * Used by path.image(), path.stream(), path.any() (binary/streaming data).
55
+ */
56
+ export type ResponseHandler<
57
+ TParams = Record<string, string>,
58
+ TEnv = any,
59
+ > = ResponseHandlerOf<Response, TParams, TEnv>;
60
+
50
61
  /**
51
62
  * JSON-serializable value type for auto-wrap support.
52
63
  */
@@ -65,12 +76,7 @@ export type JsonValue =
65
76
  export type JsonResponseHandler<
66
77
  TParams = Record<string, string>,
67
78
  TEnv = any,
68
- > = ((
69
- ctx: ResponseHandlerContext<TParams, TEnv>,
70
- ) => JsonValue | Response | Promise<JsonValue | Response>) & {
71
- /** Composable default DSL items merged when the handler is mounted. */
72
- use?: () => UseItems<ResponseRouteUseItem>;
73
- };
79
+ > = ResponseHandlerOf<JsonValue | Response, TParams, TEnv>;
74
80
 
75
81
  /**
76
82
  * Handler for text-based response routes (text, html, xml).
@@ -79,12 +85,7 @@ export type JsonResponseHandler<
79
85
  export type TextResponseHandler<
80
86
  TParams = Record<string, string>,
81
87
  TEnv = any,
82
- > = ((
83
- ctx: ResponseHandlerContext<TParams, TEnv>,
84
- ) => string | Response | Promise<string | Response>) & {
85
- /** Composable default DSL items merged when the handler is mounted. */
86
- use?: () => UseItems<ResponseRouteUseItem>;
87
- };
88
+ > = ResponseHandlerOf<string | Response, TParams, TEnv>;
88
89
 
89
90
  /**
90
91
  * Lighter handler context for response routes.