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

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 (299) hide show
  1. package/AGENTS.md +5 -0
  2. package/README.md +884 -4
  3. package/dist/bin/rango.js +1531 -155
  4. package/dist/vite/index.js +4440 -2170
  5. package/package.json +60 -54
  6. package/skills/breadcrumbs/SKILL.md +250 -0
  7. package/skills/cache-guide/SKILL.md +262 -0
  8. package/skills/caching/SKILL.md +50 -21
  9. package/skills/composability/SKILL.md +172 -0
  10. package/skills/debug-manifest/SKILL.md +12 -8
  11. package/skills/document-cache/SKILL.md +18 -16
  12. package/skills/fonts/SKILL.md +6 -4
  13. package/skills/hooks/SKILL.md +333 -71
  14. package/skills/host-router/SKILL.md +218 -0
  15. package/skills/intercept/SKILL.md +131 -8
  16. package/skills/layout/SKILL.md +100 -3
  17. package/skills/links/SKILL.md +74 -15
  18. package/skills/loader/SKILL.md +388 -38
  19. package/skills/middleware/SKILL.md +171 -34
  20. package/skills/mime-routes/SKILL.md +15 -11
  21. package/skills/parallel/SKILL.md +78 -1
  22. package/skills/prerender/SKILL.md +405 -45
  23. package/skills/rango/SKILL.md +85 -21
  24. package/skills/response-routes/SKILL.md +144 -91
  25. package/skills/route/SKILL.md +226 -14
  26. package/skills/router-setup/SKILL.md +123 -30
  27. package/skills/theme/SKILL.md +9 -8
  28. package/skills/typesafety/SKILL.md +316 -87
  29. package/skills/use-cache/SKILL.md +324 -0
  30. package/src/__internal.ts +102 -4
  31. package/src/bin/rango.ts +312 -15
  32. package/src/browser/action-coordinator.ts +97 -0
  33. package/src/browser/action-response-classifier.ts +99 -0
  34. package/src/browser/event-controller.ts +87 -64
  35. package/src/browser/history-state.ts +80 -0
  36. package/src/browser/intercept-utils.ts +52 -0
  37. package/src/browser/link-interceptor.ts +24 -4
  38. package/src/browser/logging.ts +55 -0
  39. package/src/browser/merge-segment-loaders.ts +20 -12
  40. package/src/browser/navigation-bridge.ts +285 -553
  41. package/src/browser/navigation-client.ts +123 -73
  42. package/src/browser/navigation-store.ts +33 -50
  43. package/src/browser/navigation-transaction.ts +295 -0
  44. package/src/browser/network-error-handler.ts +61 -0
  45. package/src/browser/partial-update.ts +261 -309
  46. package/src/browser/prefetch/cache.ts +154 -0
  47. package/src/browser/prefetch/fetch.ts +135 -0
  48. package/src/browser/prefetch/observer.ts +65 -0
  49. package/src/browser/prefetch/policy.ts +48 -0
  50. package/src/browser/prefetch/queue.ts +88 -0
  51. package/src/browser/rango-state.ts +112 -0
  52. package/src/browser/react/Link.tsx +182 -70
  53. package/src/browser/react/NavigationProvider.tsx +51 -11
  54. package/src/browser/react/context.ts +6 -0
  55. package/src/browser/react/filter-segment-order.ts +11 -0
  56. package/src/browser/react/index.ts +12 -12
  57. package/src/browser/react/location-state-shared.ts +95 -53
  58. package/src/browser/react/location-state.ts +60 -15
  59. package/src/browser/react/mount-context.ts +6 -1
  60. package/src/browser/react/nonce-context.ts +23 -0
  61. package/src/browser/react/shallow-equal.ts +27 -0
  62. package/src/browser/react/use-action.ts +29 -51
  63. package/src/browser/react/use-client-cache.ts +5 -3
  64. package/src/browser/react/use-handle.ts +29 -70
  65. package/src/browser/react/use-link-status.ts +6 -5
  66. package/src/browser/react/use-navigation.ts +22 -63
  67. package/src/browser/react/use-params.ts +65 -0
  68. package/src/browser/react/use-pathname.ts +47 -0
  69. package/src/browser/react/use-router.ts +63 -0
  70. package/src/browser/react/use-search-params.ts +56 -0
  71. package/src/browser/react/use-segments.ts +80 -97
  72. package/src/browser/response-adapter.ts +73 -0
  73. package/src/browser/rsc-router.tsx +106 -27
  74. package/src/browser/scroll-restoration.ts +92 -16
  75. package/src/browser/segment-reconciler.ts +216 -0
  76. package/src/browser/segment-structure-assert.ts +16 -0
  77. package/src/browser/server-action-bridge.ts +504 -599
  78. package/src/browser/shallow.ts +6 -1
  79. package/src/browser/types.ts +107 -47
  80. package/src/browser/validate-redirect-origin.ts +29 -0
  81. package/src/build/generate-manifest.ts +82 -21
  82. package/src/build/generate-route-types.ts +36 -752
  83. package/src/build/index.ts +6 -5
  84. package/src/build/route-trie.ts +39 -13
  85. package/src/build/route-types/ast-helpers.ts +25 -0
  86. package/src/build/route-types/ast-route-extraction.ts +98 -0
  87. package/src/build/route-types/codegen.ts +102 -0
  88. package/src/build/route-types/include-resolution.ts +411 -0
  89. package/src/build/route-types/param-extraction.ts +48 -0
  90. package/src/build/route-types/per-module-writer.ts +128 -0
  91. package/src/build/route-types/router-processing.ts +469 -0
  92. package/src/build/route-types/scan-filter.ts +78 -0
  93. package/src/build/runtime-discovery.ts +231 -0
  94. package/src/cache/background-task.ts +34 -0
  95. package/src/cache/cache-key-utils.ts +44 -0
  96. package/src/cache/cache-policy.ts +125 -0
  97. package/src/cache/cache-runtime.ts +338 -0
  98. package/src/cache/cache-scope.ts +120 -301
  99. package/src/cache/cf/cf-cache-store.ts +119 -7
  100. package/src/cache/cf/index.ts +8 -2
  101. package/src/cache/document-cache.ts +101 -72
  102. package/src/cache/handle-capture.ts +81 -0
  103. package/src/cache/handle-snapshot.ts +41 -0
  104. package/src/cache/index.ts +0 -15
  105. package/src/cache/memory-segment-store.ts +191 -13
  106. package/src/cache/profile-registry.ts +73 -0
  107. package/src/cache/read-through-swr.ts +134 -0
  108. package/src/cache/segment-codec.ts +256 -0
  109. package/src/cache/taint.ts +98 -0
  110. package/src/cache/types.ts +72 -122
  111. package/src/client.rsc.tsx +3 -1
  112. package/src/client.tsx +84 -126
  113. package/src/component-utils.ts +4 -4
  114. package/src/components/DefaultDocument.tsx +5 -1
  115. package/src/context-var.ts +86 -0
  116. package/src/debug.ts +17 -7
  117. package/src/errors.ts +77 -7
  118. package/src/handle.ts +15 -10
  119. package/src/handles/MetaTags.tsx +73 -20
  120. package/src/handles/breadcrumbs.ts +66 -0
  121. package/src/handles/index.ts +1 -0
  122. package/src/handles/meta.ts +30 -13
  123. package/src/host/cookie-handler.ts +21 -15
  124. package/src/host/errors.ts +8 -8
  125. package/src/host/index.ts +4 -7
  126. package/src/host/pattern-matcher.ts +27 -27
  127. package/src/host/router.ts +61 -39
  128. package/src/host/testing.ts +8 -8
  129. package/src/host/types.ts +15 -7
  130. package/src/host/utils.ts +1 -1
  131. package/src/href-client.ts +65 -45
  132. package/src/index.rsc.ts +133 -21
  133. package/src/index.ts +164 -52
  134. package/src/internal-debug.ts +11 -0
  135. package/src/loader.rsc.ts +25 -143
  136. package/src/loader.ts +27 -10
  137. package/src/network-error-thrower.tsx +3 -1
  138. package/src/outlet-provider.tsx +45 -0
  139. package/src/prerender/param-hash.ts +4 -2
  140. package/src/prerender/store.ts +158 -13
  141. package/src/prerender.ts +333 -26
  142. package/src/reverse.ts +184 -121
  143. package/src/root-error-boundary.tsx +41 -29
  144. package/src/route-content-wrapper.tsx +7 -4
  145. package/src/route-definition/dsl-helpers.ts +934 -0
  146. package/src/route-definition/helper-factories.ts +200 -0
  147. package/src/route-definition/helpers-types.ts +430 -0
  148. package/src/route-definition/index.ts +52 -0
  149. package/src/route-definition/redirect.ts +93 -0
  150. package/src/route-definition.ts +1 -1431
  151. package/src/route-map-builder.ts +156 -123
  152. package/src/route-name.ts +53 -0
  153. package/src/route-types.ts +48 -9
  154. package/src/router/content-negotiation.ts +116 -0
  155. package/src/router/debug-manifest.ts +72 -0
  156. package/src/router/error-handling.ts +9 -9
  157. package/src/router/find-match.ts +158 -0
  158. package/src/router/handler-context.ts +374 -81
  159. package/src/router/intercept-resolution.ts +24 -16
  160. package/src/router/lazy-includes.ts +234 -0
  161. package/src/router/loader-resolution.ts +215 -122
  162. package/src/router/logging.ts +248 -0
  163. package/src/router/manifest.ts +83 -32
  164. package/src/router/match-api.ts +118 -119
  165. package/src/router/match-context.ts +4 -2
  166. package/src/router/match-handlers.ts +440 -0
  167. package/src/router/match-middleware/background-revalidation.ts +80 -93
  168. package/src/router/match-middleware/cache-lookup.ts +336 -84
  169. package/src/router/match-middleware/cache-store.ts +43 -24
  170. package/src/router/match-middleware/intercept-resolution.ts +45 -20
  171. package/src/router/match-middleware/segment-resolution.ts +16 -8
  172. package/src/router/match-pipelines.ts +10 -45
  173. package/src/router/match-result.ts +34 -28
  174. package/src/router/metrics.ts +235 -15
  175. package/src/router/middleware-cookies.ts +55 -0
  176. package/src/router/middleware-types.ts +222 -0
  177. package/src/router/middleware.ts +324 -367
  178. package/src/router/pattern-matching.ts +197 -41
  179. package/src/router/prerender-match.ts +402 -0
  180. package/src/router/preview-match.ts +170 -0
  181. package/src/router/revalidation.ts +137 -38
  182. package/src/router/router-context.ts +36 -21
  183. package/src/router/router-interfaces.ts +452 -0
  184. package/src/router/router-options.ts +592 -0
  185. package/src/router/router-registry.ts +24 -0
  186. package/src/router/segment-resolution/fresh.ts +570 -0
  187. package/src/router/segment-resolution/helpers.ts +263 -0
  188. package/src/router/segment-resolution/loader-cache.ts +198 -0
  189. package/src/router/segment-resolution/revalidation.ts +1239 -0
  190. package/src/router/segment-resolution/static-store.ts +67 -0
  191. package/src/router/segment-resolution.ts +21 -1315
  192. package/src/router/segment-wrappers.ts +289 -0
  193. package/src/router/telemetry-otel.ts +299 -0
  194. package/src/router/telemetry.ts +300 -0
  195. package/src/router/timeout.ts +148 -0
  196. package/src/router/trie-matching.ts +96 -29
  197. package/src/router/types.ts +16 -9
  198. package/src/router.ts +590 -1983
  199. package/src/rsc/handler-context.ts +45 -0
  200. package/src/rsc/handler.ts +661 -1015
  201. package/src/rsc/helpers.ts +140 -6
  202. package/src/rsc/index.ts +0 -20
  203. package/src/rsc/loader-fetch.ts +209 -0
  204. package/src/rsc/manifest-init.ts +86 -0
  205. package/src/rsc/nonce.ts +14 -0
  206. package/src/rsc/origin-guard.ts +141 -0
  207. package/src/rsc/progressive-enhancement.ts +379 -0
  208. package/src/rsc/response-error.ts +37 -0
  209. package/src/rsc/response-route-handler.ts +347 -0
  210. package/src/rsc/rsc-rendering.ts +237 -0
  211. package/src/rsc/runtime-warnings.ts +42 -0
  212. package/src/rsc/server-action.ts +348 -0
  213. package/src/rsc/ssr-setup.ts +128 -0
  214. package/src/rsc/types.ts +38 -11
  215. package/src/search-params.ts +230 -0
  216. package/src/segment-system.tsx +25 -13
  217. package/src/server/context.ts +173 -48
  218. package/src/server/cookie-store.ts +190 -0
  219. package/src/server/fetchable-loader-store.ts +37 -0
  220. package/src/server/handle-store.ts +94 -15
  221. package/src/server/loader-registry.ts +15 -56
  222. package/src/server/request-context.ts +430 -70
  223. package/src/server.ts +35 -155
  224. package/src/ssr/index.tsx +100 -31
  225. package/src/static-handler.ts +114 -0
  226. package/src/theme/ThemeProvider.tsx +21 -15
  227. package/src/theme/ThemeScript.tsx +5 -5
  228. package/src/theme/constants.ts +5 -2
  229. package/src/theme/index.ts +4 -14
  230. package/src/theme/theme-context.ts +4 -30
  231. package/src/theme/theme-script.ts +21 -18
  232. package/src/types/boundaries.ts +158 -0
  233. package/src/types/cache-types.ts +198 -0
  234. package/src/types/error-types.ts +192 -0
  235. package/src/types/global-namespace.ts +100 -0
  236. package/src/types/handler-context.ts +687 -0
  237. package/src/types/index.ts +88 -0
  238. package/src/types/loader-types.ts +183 -0
  239. package/src/types/route-config.ts +170 -0
  240. package/src/types/route-entry.ts +102 -0
  241. package/src/types/segments.ts +148 -0
  242. package/src/types.ts +1 -1757
  243. package/src/urls/include-helper.ts +197 -0
  244. package/src/urls/index.ts +53 -0
  245. package/src/urls/path-helper-types.ts +339 -0
  246. package/src/urls/path-helper.ts +329 -0
  247. package/src/urls/pattern-types.ts +95 -0
  248. package/src/urls/response-types.ts +106 -0
  249. package/src/urls/type-extraction.ts +372 -0
  250. package/src/urls/urls-function.ts +98 -0
  251. package/src/urls.ts +1 -1282
  252. package/src/use-loader.tsx +85 -77
  253. package/src/vite/discovery/bundle-postprocess.ts +184 -0
  254. package/src/vite/discovery/discover-routers.ts +344 -0
  255. package/src/vite/discovery/prerender-collection.ts +385 -0
  256. package/src/vite/discovery/route-types-writer.ts +258 -0
  257. package/src/vite/discovery/self-gen-tracking.ts +47 -0
  258. package/src/vite/discovery/state.ts +110 -0
  259. package/src/vite/discovery/virtual-module-codegen.ts +203 -0
  260. package/src/vite/index.ts +11 -1963
  261. package/src/vite/plugin-types.ts +131 -0
  262. package/src/vite/plugins/cjs-to-esm.ts +93 -0
  263. package/src/vite/plugins/client-ref-dedup.ts +115 -0
  264. package/src/vite/plugins/client-ref-hashing.ts +105 -0
  265. package/src/vite/{expose-action-id.ts → plugins/expose-action-id.ts} +72 -51
  266. package/src/vite/plugins/expose-id-utils.ts +287 -0
  267. package/src/vite/plugins/expose-ids/export-analysis.ts +296 -0
  268. package/src/vite/plugins/expose-ids/handler-transform.ts +179 -0
  269. package/src/vite/plugins/expose-ids/loader-transform.ts +74 -0
  270. package/src/vite/plugins/expose-ids/router-transform.ts +110 -0
  271. package/src/vite/plugins/expose-ids/types.ts +45 -0
  272. package/src/vite/plugins/expose-internal-ids.ts +569 -0
  273. package/src/vite/plugins/refresh-cmd.ts +65 -0
  274. package/src/vite/plugins/use-cache-transform.ts +323 -0
  275. package/src/vite/plugins/version-injector.ts +83 -0
  276. package/src/vite/plugins/version-plugin.ts +254 -0
  277. package/src/vite/{virtual-entries.ts → plugins/virtual-entries.ts} +23 -14
  278. package/src/vite/plugins/virtual-stub-plugin.ts +29 -0
  279. package/src/vite/rango.ts +510 -0
  280. package/src/vite/router-discovery.ts +785 -0
  281. package/src/vite/utils/ast-handler-extract.ts +517 -0
  282. package/src/vite/utils/banner.ts +36 -0
  283. package/src/vite/utils/bundle-analysis.ts +137 -0
  284. package/src/vite/utils/manifest-utils.ts +70 -0
  285. package/src/vite/{package-resolution.ts → utils/package-resolution.ts} +25 -29
  286. package/src/vite/utils/prerender-utils.ts +189 -0
  287. package/src/vite/utils/shared-utils.ts +169 -0
  288. package/CLAUDE.md +0 -43
  289. package/src/browser/lru-cache.ts +0 -69
  290. package/src/browser/request-controller.ts +0 -164
  291. package/src/cache/memory-store.ts +0 -253
  292. package/src/href-context.ts +0 -33
  293. package/src/router.gen.ts +0 -6
  294. package/src/urls.gen.ts +0 -8
  295. package/src/vite/expose-handle-id.ts +0 -209
  296. package/src/vite/expose-loader-id.ts +0 -426
  297. package/src/vite/expose-location-state-id.ts +0 -177
  298. package/src/vite/expose-prerender-handler-id.ts +0 -429
  299. /package/src/vite/{version.d.ts → plugins/version.d.ts} +0 -0
@@ -6,15 +6,16 @@
6
6
  */
7
7
 
8
8
  import { CacheScope, createCacheScope } from "../cache/cache-scope.js";
9
- import {
10
- RouteNotFoundError,
11
- } from "../errors";
9
+ import { RouteNotFoundError } from "../errors";
12
10
  import {
13
11
  createErrorInfo,
14
12
  createErrorSegment,
15
13
  findNearestErrorBoundary as findErrorBoundary,
16
14
  } from "./error-handling.js";
17
- import { createHandlerContext } from "./handler-context.js";
15
+ import {
16
+ createHandlerContext,
17
+ stripInternalParams,
18
+ } from "./handler-context.js";
18
19
  import { setupLoaderAccess } from "./loader-resolution.js";
19
20
  import { loadManifest, clearManifestCache } from "./manifest.js";
20
21
  import { collectRouteMiddleware } from "./middleware.js";
@@ -25,24 +26,17 @@ import {
25
26
  LoaderEntry,
26
27
  getContext,
27
28
  InterceptSelectorContext,
28
- type MetricsStore,
29
29
  } from "../server/context";
30
- import {
31
- getGlobalRouteMap,
32
- } from "../route-map-builder.js";
33
- import type {
34
- ErrorBoundaryHandler,
35
- ErrorInfo,
36
- HandlerContext,
37
- MatchResult,
38
- ResolvedSegment,
39
- } from "../types";
30
+ import type { ErrorBoundaryHandler, ErrorInfo, MatchResult } from "../types";
40
31
  import type { ReactNode } from "react";
41
- import type { MatchContext, ActionContext as MatchActionContext } from "./match-context.js";
32
+ import type { MatchContext } from "./match-context.js";
42
33
  import type { MatchApiDeps, ActionContext } from "./types.js";
43
- import type { InterceptEntry } from "../server/context";
44
- import type { RouteMatchResult } from "./pattern-matching.js";
45
- import { getRequestContext } from "../server/request-context.js";
34
+ import {
35
+ getRequestContext,
36
+ setRequestContextPrevRouteKey,
37
+ } from "../server/request-context.js";
38
+ import { isAutoGeneratedRouteName } from "../route-name.js";
39
+ import { debugLog, debugWarn } from "./logging.js";
46
40
 
47
41
  /**
48
42
  * Create match context for full requests (document/SSR).
@@ -97,22 +91,32 @@ export async function createMatchContextForFull<TEnv>(
97
91
  });
98
92
  }
99
93
 
94
+ if (
95
+ manifestEntry.type === "route" &&
96
+ manifestEntry.prerenderDef?.options?.passthrough === true
97
+ ) {
98
+ matched.pt = true;
99
+ }
100
+
100
101
  const routeMiddleware = collectRouteMiddleware(
101
102
  traverseBack(manifestEntry),
102
103
  matched.params,
103
104
  );
104
105
 
105
- const bindings = (env as any)?.Bindings ?? env;
106
+ // Clean URL without internal _rsc* params for userland access
107
+ const cleanUrl = stripInternalParams(url);
106
108
 
107
109
  const handlerContext = createHandlerContext(
108
110
  matched.params,
109
111
  request,
110
- url.searchParams,
112
+ cleanUrl.searchParams,
111
113
  pathname,
112
- url,
113
- bindings,
114
- getGlobalRouteMap(),
114
+ cleanUrl,
115
+ env,
116
+ deps.getRouteMap(),
115
117
  matched.routeKey,
118
+ matched.responseType,
119
+ matched.pt === true,
116
120
  );
117
121
 
118
122
  const loaderPromises = new Map<string, Promise<any>>();
@@ -140,14 +144,13 @@ export async function createMatchContextForFull<TEnv>(
140
144
 
141
145
  return {
142
146
  request,
143
- url,
147
+ url: cleanUrl,
144
148
  pathname,
145
149
  env,
146
- bindings,
147
150
  clientSegmentIds: [],
148
151
  clientSegmentSet: new Set(),
149
152
  stale: false,
150
- prevUrl: url,
153
+ prevUrl: cleanUrl,
151
154
  prevParams: {},
152
155
  prevMatch: null,
153
156
  matched,
@@ -159,17 +162,21 @@ export async function createMatchContextForFull<TEnv>(
159
162
  : matched.routeKey,
160
163
  handlerContext,
161
164
  loaderPromises,
162
- routeMap: getGlobalRouteMap(),
165
+ routeMap: deps.getRouteMap(),
163
166
  metricsStore,
164
167
  Store,
165
168
  interceptContextMatch: null,
166
169
  interceptSelectorContext: {
167
- from: url,
168
- to: url,
170
+ from: cleanUrl,
171
+ to: cleanUrl,
169
172
  params: matched.params,
170
173
  request,
171
174
  env,
172
175
  segments: { path: [], ids: [] },
176
+ toRouteName:
177
+ matched.routeKey && !isAutoGeneratedRouteName(matched.routeKey)
178
+ ? matched.routeKey
179
+ : undefined,
173
180
  },
174
181
  isSameRouteNavigation: false,
175
182
  interceptResult: null,
@@ -195,7 +202,6 @@ export async function createMatchContextForPartial<TEnv>(
195
202
  const url = new URL(request.url);
196
203
  const pathname = url.pathname;
197
204
 
198
- const requestStartTime = performance.now();
199
205
  const metricsStore = deps.getMetricsStore();
200
206
 
201
207
  const clientSegmentIds =
@@ -217,10 +223,21 @@ export async function createMatchContextForPartial<TEnv>(
217
223
  return null;
218
224
  }
219
225
 
220
- const prevUrl = new URL(previousUrl, url.origin);
221
- const interceptContextUrl = interceptSourceUrl
222
- ? new URL(interceptSourceUrl, url.origin)
223
- : prevUrl;
226
+ let prevUrl: URL;
227
+ try {
228
+ prevUrl = new URL(previousUrl, url.origin);
229
+ } catch {
230
+ return null;
231
+ }
232
+
233
+ let interceptContextUrl: URL;
234
+ try {
235
+ interceptContextUrl = interceptSourceUrl
236
+ ? new URL(interceptSourceUrl, url.origin)
237
+ : prevUrl;
238
+ } catch {
239
+ interceptContextUrl = prevUrl;
240
+ }
224
241
 
225
242
  const routeMatchStart = metricsStore ? performance.now() : 0;
226
243
  const prevMatch = deps.findMatch(prevUrl.pathname);
@@ -250,9 +267,10 @@ export async function createMatchContextForPartial<TEnv>(
250
267
  }
251
268
 
252
269
  if (prevMatch && prevMatch.entry !== matched.entry && !matched.pr) {
253
- console.log(
254
- `[Router.matchPartial] Route group changed: ${prevMatch.routeKey} → ${matched.routeKey}`,
255
- );
270
+ debugLog("matchPartial", "route group changed", {
271
+ from: prevMatch.routeKey,
272
+ to: matched.routeKey,
273
+ });
256
274
  }
257
275
 
258
276
  const manifestStart = metricsStore ? performance.now() : 0;
@@ -271,28 +289,38 @@ export async function createMatchContextForPartial<TEnv>(
271
289
  });
272
290
  }
273
291
 
292
+ if (
293
+ manifestEntry.type === "route" &&
294
+ manifestEntry.prerenderDef?.options?.passthrough === true
295
+ ) {
296
+ matched.pt = true;
297
+ }
298
+
274
299
  const routeMiddleware = collectRouteMiddleware(
275
300
  traverseBack(manifestEntry),
276
301
  matched.params,
277
302
  );
278
303
 
279
- const bindings = (env as any)?.Bindings ?? env;
304
+ // Clean URL without internal _rsc* params for userland access
305
+ const cleanUrl = stripInternalParams(url);
306
+
280
307
  const handlerContext = createHandlerContext(
281
308
  matched.params,
282
309
  request,
283
- url.searchParams,
310
+ cleanUrl.searchParams,
284
311
  pathname,
285
- url,
286
- bindings,
287
- getGlobalRouteMap(),
312
+ cleanUrl,
313
+ env,
314
+ deps.getRouteMap(),
288
315
  matched.routeKey,
316
+ matched.responseType,
317
+ matched.pt === true,
289
318
  );
290
319
 
291
320
  const clientSegmentSet = new Set(clientSegmentIds);
292
- console.log(
293
- `[Router.matchPartial] Client segments:`,
294
- Array.from(clientSegmentSet),
295
- );
321
+ debugLog("matchPartial", "client segments", {
322
+ segments: Array.from(clientSegmentSet),
323
+ });
296
324
 
297
325
  const loaderPromises = new Map<string, Promise<any>>();
298
326
  setupLoaderAccess(handlerContext, loaderPromises);
@@ -310,17 +338,17 @@ export async function createMatchContextForPartial<TEnv>(
310
338
  }
311
339
 
312
340
  const isSameRouteNavigation = !!(
313
- interceptContextMatch &&
314
- interceptContextMatch.routeKey === matched.routeKey
341
+ interceptContextMatch && interceptContextMatch.routeKey === matched.routeKey
315
342
  );
316
343
 
317
344
  if (interceptSourceUrl) {
318
- console.log(`[Router.matchPartial] Intercept context detected:`);
319
- console.log(` - Current URL: ${pathname}`);
320
- console.log(` - Intercept source: ${interceptSourceUrl}`);
321
- console.log(` - Context match: ${interceptContextMatch?.routeKey}`);
322
- console.log(` - Current route: ${matched.routeKey}`);
323
- console.log(` - Same route navigation: ${isSameRouteNavigation}`);
345
+ debugLog("matchPartial.intercept", "intercept context detected", {
346
+ currentUrl: pathname,
347
+ interceptSource: interceptSourceUrl,
348
+ contextRoute: interceptContextMatch?.routeKey,
349
+ currentRoute: matched.routeKey,
350
+ sameRouteNavigation: isSameRouteNavigation,
351
+ });
324
352
  }
325
353
 
326
354
  const localRouteName = matched.routeKey.includes(".")
@@ -332,16 +360,35 @@ export async function createMatchContextForPartial<TEnv>(
332
360
  if (/D\d+\./.test(id)) return false;
333
361
  return true;
334
362
  });
363
+ const effectiveFromUrl = interceptSourceUrl ? interceptContextUrl : prevUrl;
364
+ const effectiveFromMatch = interceptSourceUrl
365
+ ? interceptContextMatch
366
+ : prevMatch;
367
+
368
+ // Store previous route key on the request context for revalidation
369
+ // fromRouteName. Uses effectiveFromMatch so intercept-source navigations
370
+ // see the intercept origin route, not the plain previous URL route.
371
+ setRequestContextPrevRouteKey(effectiveFromMatch?.routeKey);
372
+
335
373
  const interceptSelectorContext: InterceptSelectorContext = {
336
- from: prevUrl,
337
- to: url,
374
+ from: effectiveFromUrl,
375
+ to: cleanUrl,
338
376
  params: matched.params,
339
377
  request,
340
378
  env,
341
379
  segments: {
342
- path: prevUrl.pathname.split("/").filter(Boolean),
380
+ path: effectiveFromUrl.pathname.split("/").filter(Boolean),
343
381
  ids: filteredSegmentIds,
344
382
  },
383
+ fromRouteName:
384
+ effectiveFromMatch?.routeKey &&
385
+ !isAutoGeneratedRouteName(effectiveFromMatch.routeKey)
386
+ ? effectiveFromMatch.routeKey
387
+ : undefined,
388
+ toRouteName:
389
+ matched.routeKey && !isAutoGeneratedRouteName(matched.routeKey)
390
+ ? matched.routeKey
391
+ : undefined,
345
392
  };
346
393
  const isAction = !!actionContext;
347
394
 
@@ -372,9 +419,9 @@ export async function createMatchContextForPartial<TEnv>(
372
419
  manifestEntry.type === "route" &&
373
420
  interceptSourceUrl
374
421
  ) {
375
- console.log(
376
- `[Router.matchPartial] Leaving intercept - forcing route segment render: ${manifestEntry.shortCode}`,
377
- );
422
+ debugLog("matchPartial.intercept", "forcing route segment render", {
423
+ segmentId: manifestEntry.shortCode,
424
+ });
378
425
  clientSegmentSet.delete(manifestEntry.shortCode);
379
426
  }
380
427
 
@@ -390,10 +437,9 @@ export async function createMatchContextForPartial<TEnv>(
390
437
 
391
438
  return {
392
439
  request,
393
- url,
440
+ url: cleanUrl,
394
441
  pathname,
395
442
  env,
396
- bindings,
397
443
  clientSegmentIds,
398
444
  clientSegmentSet,
399
445
  stale,
@@ -407,7 +453,7 @@ export async function createMatchContextForPartial<TEnv>(
407
453
  localRouteName,
408
454
  handlerContext,
409
455
  loaderPromises,
410
- routeMap: getGlobalRouteMap(),
456
+ routeMap: deps.getRouteMap(),
411
457
  metricsStore,
412
458
  Store,
413
459
  interceptContextMatch,
@@ -437,11 +483,11 @@ export async function matchError<TEnv>(
437
483
  const url = new URL(request.url);
438
484
  const pathname = url.pathname;
439
485
 
440
- console.log(`[Router.matchError] Matching error for ${pathname}`);
486
+ debugLog("matchError", "matching error", { pathname });
441
487
 
442
488
  const matched = deps.findMatch(pathname);
443
489
  if (!matched) {
444
- console.warn(`[Router.matchError] No route matched for ${pathname}`);
490
+ debugWarn("matchError", "no route matched", { pathname });
445
491
  return null;
446
492
  }
447
493
 
@@ -545,10 +591,7 @@ export async function matchError<TEnv>(
545
591
 
546
592
  const reqCtx = getRequestContext();
547
593
  if (reqCtx) {
548
- reqCtx.res = new Response(null, {
549
- status: 500,
550
- headers: reqCtx.res.headers,
551
- });
594
+ reqCtx._setStatus(500);
552
595
  }
553
596
 
554
597
  const effectiveFallback = fallback || DefaultErrorFallback;
@@ -560,14 +603,13 @@ export async function matchError<TEnv>(
560
603
  );
561
604
 
562
605
  if (useDefaultFallback) {
563
- console.log(
564
- `[Router.matchError] Using default error boundary (no user-defined boundary found)`,
565
- );
606
+ debugLog("matchError", "using default error boundary");
566
607
  }
567
608
 
568
- console.log(
569
- `[Router.matchError] Boundary: ${boundaryEntry.shortCode}, outlet replaced: ${outletEntry.shortCode}`,
570
- );
609
+ debugLog("matchError", "resolved boundary", {
610
+ boundarySegmentId: boundaryEntry.shortCode,
611
+ outletSegmentId: outletEntry.shortCode,
612
+ });
571
613
 
572
614
  return {
573
615
  segments: [errorSegment],
@@ -576,46 +618,3 @@ export async function matchError<TEnv>(
576
618
  params: matched.params,
577
619
  };
578
620
  }
579
-
580
- /**
581
- * Preview match - returns route middleware without segment resolution.
582
- */
583
- export async function previewMatch<TEnv>(
584
- request: Request,
585
- context: TEnv,
586
- deps: MatchApiDeps<TEnv>,
587
- ): Promise<{
588
- routeMiddleware?: Array<{
589
- handler: import("./middleware.js").MiddlewareFn;
590
- params: Record<string, string>;
591
- }>;
592
- } | null> {
593
- const url = new URL(request.url);
594
- const pathname = url.pathname;
595
-
596
- const matched = deps.findMatch(pathname);
597
- if (!matched) {
598
- return null;
599
- }
600
-
601
- if (matched.redirectTo) {
602
- return { routeMiddleware: undefined };
603
- }
604
-
605
- const manifestEntry = await loadManifest(
606
- matched.entry,
607
- matched.routeKey,
608
- pathname,
609
- undefined,
610
- false,
611
- );
612
-
613
- const routeMiddleware = collectRouteMiddleware(
614
- traverseBack(manifestEntry),
615
- matched.params,
616
- );
617
-
618
- return {
619
- routeMiddleware: routeMiddleware.length > 0 ? routeMiddleware : undefined,
620
- };
621
- }
@@ -45,7 +45,7 @@
45
45
  * - request, url, pathname: The incoming HTTP request
46
46
  *
47
47
  * Environment:
48
- * - env, bindings: Server environment (Cloudflare bindings, etc.)
48
+ * - env: Server environment (Cloudflare bindings, etc.)
49
49
  *
50
50
  * Client State (from RSC request headers):
51
51
  * - clientSegmentIds: Segments the client currently has
@@ -140,7 +140,6 @@ export interface MatchContext<TEnv = any> {
140
140
 
141
141
  // Environment
142
142
  env: TEnv;
143
- bindings: TEnv;
144
143
 
145
144
  // Client state
146
145
  clientSegmentIds: string[];
@@ -211,6 +210,9 @@ export interface MatchPipelineState {
211
210
  // Whether cache should be revalidated (SWR)
212
211
  shouldRevalidate?: boolean;
213
212
 
213
+ // Source of cache hit ("runtime" or "prerender")
214
+ cacheSource?: "runtime" | "prerender";
215
+
214
216
  // Resolved segments from pipeline
215
217
  segments: ResolvedSegment[];
216
218
  matchedIds: string[];