@rangojs/router 0.17.0 → 0.19.0

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 (293) hide show
  1. package/README.md +3 -2
  2. package/dist/types/browser/cookie-name.d.ts +6 -0
  3. package/dist/types/browser/event-controller.d.ts +3 -3
  4. package/dist/types/browser/history-state.d.ts +18 -0
  5. package/dist/types/browser/navigation-transaction.d.ts +20 -2
  6. package/dist/types/browser/partial-update.d.ts +16 -1
  7. package/dist/types/browser/prefetch/cache.d.ts +6 -6
  8. package/dist/types/browser/react/Link.d.ts +19 -9
  9. package/dist/types/browser/react/context.d.ts +2 -2
  10. package/dist/types/browser/react/location-state-shared.d.ts +95 -56
  11. package/dist/types/browser/react/location-state.d.ts +1 -1
  12. package/dist/types/browser/transition-when.d.ts +80 -0
  13. package/dist/types/browser/types.d.ts +104 -9
  14. package/dist/types/build/generate-manifest.d.ts +8 -0
  15. package/dist/types/cache/background-task.d.ts +24 -2
  16. package/dist/types/cache/cache-exec-scope.d.ts +31 -0
  17. package/dist/types/cache/cache-key-utils.d.ts +48 -2
  18. package/dist/types/cache/cache-policy.d.ts +18 -1
  19. package/dist/types/cache/cache-runtime.d.ts +7 -0
  20. package/dist/types/cache/cache-scope.d.ts +192 -26
  21. package/dist/types/cache/cache-tag.d.ts +116 -11
  22. package/dist/types/cache/cf/cf-base64.d.ts +6 -0
  23. package/dist/types/cache/cf/cf-cache-constants.d.ts +11 -0
  24. package/dist/types/cache/cf/cf-cache-store.d.ts +224 -72
  25. package/dist/types/cache/cf/cf-cache-types.d.ts +31 -4
  26. package/dist/types/cache/cf/cf-shell-frame.d.ts +95 -0
  27. package/dist/types/cache/cf/cf-tag-marker-memo.d.ts +19 -0
  28. package/dist/types/cache/document-cache.d.ts +10 -0
  29. package/dist/types/cache/handle-snapshot.d.ts +41 -8
  30. package/dist/types/cache/index.d.ts +1 -0
  31. package/dist/types/cache/invalidation-order.d.ts +23 -0
  32. package/dist/types/cache/isolate-tag-memo.d.ts +149 -0
  33. package/dist/types/cache/request-tag-mask.d.ts +54 -0
  34. package/dist/types/cache/shell-memo.d.ts +178 -0
  35. package/dist/types/cache/shell-snapshot.d.ts +141 -105
  36. package/dist/types/cache/tag-invalidation.d.ts +54 -3
  37. package/dist/types/cache/types.d.ts +267 -96
  38. package/dist/types/cache/vercel/vercel-cache-store.d.ts +123 -18
  39. package/dist/types/client-urls/navigation.d.ts +28 -2
  40. package/dist/types/client-urls/server-projection.d.ts +5 -2
  41. package/dist/types/client-urls/types.d.ts +5 -5
  42. package/dist/types/client.d.ts +1 -1
  43. package/dist/types/index.d.ts +1 -1
  44. package/dist/types/index.rsc.d.ts +1 -1
  45. package/dist/types/prerender/build-shell-capture.d.ts +11 -4
  46. package/dist/types/route-definition/helpers-types.d.ts +11 -11
  47. package/dist/types/route-name.d.ts +7 -0
  48. package/dist/types/router/error-handling.d.ts +1 -1
  49. package/dist/types/router/instrument.d.ts +8 -0
  50. package/dist/types/router/intercept-resolution.d.ts +2 -0
  51. package/dist/types/router/match-context.d.ts +5 -0
  52. package/dist/types/router/match-middleware/background-revalidation.d.ts +0 -4
  53. package/dist/types/router/middleware-types.d.ts +6 -1
  54. package/dist/types/router/router-options.d.ts +4 -1
  55. package/dist/types/router/segment-resolution/loader-cache.d.ts +58 -12
  56. package/dist/types/router/segment-resolution/loader-mask.d.ts +3 -4
  57. package/dist/types/router/segment-resolution/loader-snapshot.d.ts +33 -48
  58. package/dist/types/router/segment-resolution/mask-nested.d.ts +73 -24
  59. package/dist/types/router/segment-resolution/view-transition-default.d.ts +7 -5
  60. package/dist/types/router/transition-when.d.ts +24 -10
  61. package/dist/types/rsc/attach-transition-when.d.ts +18 -0
  62. package/dist/types/rsc/full-payload.d.ts +21 -0
  63. package/dist/types/rsc/handler.d.ts +1 -1
  64. package/dist/types/rsc/response-cache-serve.d.ts +15 -12
  65. package/dist/types/rsc/shell-build-manifest.d.ts +12 -3
  66. package/dist/types/rsc/shell-capture-constants.d.ts +116 -12
  67. package/dist/types/rsc/shell-capture.d.ts +202 -74
  68. package/dist/types/rsc/shell-serve.d.ts +144 -50
  69. package/dist/types/rsc/types.d.ts +9 -0
  70. package/dist/types/segment-system.d.ts +7 -0
  71. package/dist/types/server/context.d.ts +155 -33
  72. package/dist/types/server/cookie-store.d.ts +33 -0
  73. package/dist/types/server/handle-store.d.ts +52 -1
  74. package/dist/types/server/request-context.d.ts +210 -63
  75. package/dist/types/server/request-headers.d.ts +44 -0
  76. package/dist/types/server.d.ts +1 -0
  77. package/dist/types/ssr/index.d.ts +9 -0
  78. package/dist/types/ssr/ssr-root.d.ts +9 -8
  79. package/dist/types/testing/e2e/index.d.ts +1 -1
  80. package/dist/types/testing/flight.entry.d.ts +7 -0
  81. package/dist/types/testing/index.d.ts +3 -2
  82. package/dist/types/testing/internal/action-id.d.ts +7 -0
  83. package/dist/types/testing/location-state-key.d.ts +24 -0
  84. package/dist/types/testing/render-route.d.ts +17 -1
  85. package/dist/types/testing/run-loader.d.ts +18 -3
  86. package/dist/types/testing/run-transition-when.d.ts +44 -69
  87. package/dist/types/testing/serve-shell-request.d.ts +133 -0
  88. package/dist/types/testing/shell-status.d.ts +44 -19
  89. package/dist/types/transition-when-ref.d.ts +79 -0
  90. package/dist/types/types/cache-types.d.ts +15 -3
  91. package/dist/types/types/handler-context.d.ts +14 -1
  92. package/dist/types/types/index.d.ts +1 -1
  93. package/dist/types/types/segments.d.ts +86 -71
  94. package/dist/types/urls/path-helper-types.d.ts +3 -4
  95. package/dist/types/urls/pattern-types.d.ts +21 -18
  96. package/dist/types/vite/plugins/transition-when-hoist.d.ts +45 -0
  97. package/dist/types/vite/router-discovery.d.ts +29 -2
  98. package/dist/vite/index.js +1005 -105
  99. package/package.json +1 -1
  100. package/skills/breadcrumbs/SKILL.md +17 -7
  101. package/skills/cache-guide/SKILL.md +175 -76
  102. package/skills/caching/SKILL.md +361 -33
  103. package/skills/catalog.json +1 -1
  104. package/skills/client-urls/SKILL.md +12 -7
  105. package/skills/cloudflare/SKILL.md +15 -0
  106. package/skills/comparison/references/framework-comparison.md +52 -37
  107. package/skills/defer-hydration/SKILL.md +50 -30
  108. package/skills/deployment-caching/SKILL.md +5 -2
  109. package/skills/document-cache/SKILL.md +32 -2
  110. package/skills/handler-use/SKILL.md +2 -0
  111. package/skills/hooks/SKILL.md +3 -1
  112. package/skills/hooks/handle-and-actions.md +3 -1
  113. package/skills/hooks/navigation.md +23 -2
  114. package/skills/hooks/state.md +101 -7
  115. package/skills/intercept/SKILL.md +29 -12
  116. package/skills/loader/SKILL.md +197 -44
  117. package/skills/middleware/SKILL.md +34 -9
  118. package/skills/migrate-nextjs/SKILL.md +68 -37
  119. package/skills/migrate-react-router/SKILL.md +2 -1
  120. package/skills/migrate-react-router/component-migration.md +3 -1
  121. package/skills/migrate-react-router/data-and-actions.md +3 -1
  122. package/skills/migrate-react-router/route-mapping.md +7 -4
  123. package/skills/observability/SKILL.md +65 -0
  124. package/skills/parallel/SKILL.md +13 -8
  125. package/skills/ppr/SKILL.md +715 -371
  126. package/skills/prerender/SKILL.md +30 -17
  127. package/skills/rango/SKILL.md +72 -34
  128. package/skills/route/SKILL.md +14 -7
  129. package/skills/router-setup/SKILL.md +4 -2
  130. package/skills/scripts/SKILL.md +8 -1
  131. package/skills/server-actions/SKILL.md +11 -0
  132. package/skills/shell-manifest/SKILL.md +21 -12
  133. package/skills/testing/SKILL.md +49 -43
  134. package/skills/testing/cache-prerender.md +15 -14
  135. package/skills/testing/client-components.md +45 -3
  136. package/skills/testing/loader.md +19 -1
  137. package/skills/testing/middleware.md +1 -0
  138. package/skills/testing/predicates.md +49 -49
  139. package/skills/testing/render-handler.md +1 -0
  140. package/skills/testing/serve-shell-request.md +202 -0
  141. package/skills/testing/server-actions.md +9 -3
  142. package/skills/theme/SKILL.md +56 -4
  143. package/skills/typesafety/env-and-bindings.md +18 -2
  144. package/skills/use-cache/SKILL.md +91 -23
  145. package/skills/vercel/SKILL.md +14 -2
  146. package/skills/view-transitions/SKILL.md +150 -29
  147. package/src/__augment-tests__/augmented.check.ts +23 -0
  148. package/src/browser/cookie-name.ts +23 -0
  149. package/src/browser/event-controller.ts +4 -4
  150. package/src/browser/history-state.ts +75 -1
  151. package/src/browser/link-interceptor.ts +4 -0
  152. package/src/browser/navigation-bridge.ts +77 -18
  153. package/src/browser/navigation-client.ts +4 -3
  154. package/src/browser/navigation-store.ts +43 -1
  155. package/src/browser/navigation-transaction.ts +31 -11
  156. package/src/browser/partial-update.ts +146 -35
  157. package/src/browser/prefetch/cache.ts +6 -6
  158. package/src/browser/prefetch/fetch.ts +2 -2
  159. package/src/browser/react/Link.tsx +38 -33
  160. package/src/browser/react/NavigationProvider.tsx +2 -2
  161. package/src/browser/react/context.ts +2 -2
  162. package/src/browser/react/location-state-shared.ts +241 -49
  163. package/src/browser/react/location-state.ts +5 -2
  164. package/src/browser/rsc-router.tsx +9 -0
  165. package/src/browser/server-action-bridge.ts +84 -15
  166. package/src/browser/transition-when.ts +205 -0
  167. package/src/browser/types.ts +124 -10
  168. package/src/build/generate-manifest.ts +77 -1
  169. package/src/cache/background-task.ts +55 -2
  170. package/src/cache/cache-exec-scope.ts +48 -1
  171. package/src/cache/cache-key-utils.ts +62 -2
  172. package/src/cache/cache-policy.ts +31 -4
  173. package/src/cache/cache-runtime.ts +209 -129
  174. package/src/cache/cache-scope.ts +573 -69
  175. package/src/cache/cache-tag.ts +475 -19
  176. package/src/cache/cf/cf-base64.ts +36 -4
  177. package/src/cache/cf/cf-cache-constants.ts +12 -0
  178. package/src/cache/cf/cf-cache-store.ts +1094 -376
  179. package/src/cache/cf/cf-cache-types.ts +32 -4
  180. package/src/cache/cf/cf-shell-frame.ts +258 -0
  181. package/src/cache/cf/cf-tag-marker-memo.ts +55 -40
  182. package/src/cache/document-cache.ts +53 -7
  183. package/src/cache/handle-snapshot.ts +53 -9
  184. package/src/cache/index.ts +2 -0
  185. package/src/cache/invalidation-order.ts +84 -0
  186. package/src/cache/isolate-tag-memo.ts +308 -0
  187. package/src/cache/request-tag-mask.ts +147 -0
  188. package/src/cache/shell-memo.ts +341 -0
  189. package/src/cache/shell-snapshot.ts +249 -277
  190. package/src/cache/tag-invalidation.ts +109 -18
  191. package/src/cache/types.ts +274 -102
  192. package/src/cache/vercel/vercel-cache-store.ts +561 -74
  193. package/src/client-urls/client-root.tsx +8 -4
  194. package/src/client-urls/client-urls.ts +8 -6
  195. package/src/client-urls/navigation.ts +55 -4
  196. package/src/client-urls/server-projection.ts +31 -10
  197. package/src/client-urls/types.ts +12 -5
  198. package/src/client.tsx +2 -0
  199. package/src/host/cookie-handler.ts +2 -1
  200. package/src/index.rsc.ts +3 -0
  201. package/src/index.ts +3 -0
  202. package/src/loader-redirect.tsx +7 -3
  203. package/src/prerender/build-shell-capture.ts +173 -110
  204. package/src/route-definition/dsl-helpers.ts +6 -3
  205. package/src/route-definition/helpers-types.ts +11 -11
  206. package/src/route-name.ts +12 -0
  207. package/src/router/content-negotiation.ts +4 -1
  208. package/src/router/error-handling.ts +5 -2
  209. package/src/router/handler-context.ts +42 -5
  210. package/src/router/instrument.ts +54 -2
  211. package/src/router/intercept-resolution.ts +30 -8
  212. package/src/router/loader-resolution.ts +89 -33
  213. package/src/router/logging.ts +5 -3
  214. package/src/router/match-api.ts +89 -42
  215. package/src/router/match-context.ts +5 -0
  216. package/src/router/match-handlers.ts +14 -29
  217. package/src/router/match-middleware/background-revalidation.ts +3 -5
  218. package/src/router/match-middleware/cache-lookup.ts +52 -19
  219. package/src/router/match-middleware/cache-store.ts +36 -10
  220. package/src/router/match-result.ts +1 -0
  221. package/src/router/middleware-types.ts +6 -1
  222. package/src/router/middleware.ts +20 -4
  223. package/src/router/navigation-snapshot.ts +6 -5
  224. package/src/router/prerender-match.ts +10 -0
  225. package/src/router/request-classification.ts +7 -4
  226. package/src/router/router-options.ts +4 -1
  227. package/src/router/segment-resolution/fresh.ts +18 -13
  228. package/src/router/segment-resolution/helpers.ts +4 -2
  229. package/src/router/segment-resolution/loader-cache.ts +366 -70
  230. package/src/router/segment-resolution/loader-mask.ts +3 -4
  231. package/src/router/segment-resolution/loader-snapshot.ts +215 -126
  232. package/src/router/segment-resolution/mask-nested.ts +161 -42
  233. package/src/router/segment-resolution/revalidation.ts +27 -13
  234. package/src/router/segment-resolution/view-transition-default.ts +6 -21
  235. package/src/router/telemetry.ts +6 -3
  236. package/src/router/transition-when.ts +34 -52
  237. package/src/router.ts +2 -1
  238. package/src/rsc/attach-transition-when.ts +47 -0
  239. package/src/rsc/full-payload.ts +47 -3
  240. package/src/rsc/handler.ts +24 -10
  241. package/src/rsc/loader-fetch.ts +2 -1
  242. package/src/rsc/manifest-init.ts +4 -0
  243. package/src/rsc/origin-guard.ts +8 -5
  244. package/src/rsc/progressive-enhancement.ts +10 -32
  245. package/src/rsc/response-cache-serve.ts +69 -78
  246. package/src/rsc/response-route-handler.ts +2 -2
  247. package/src/rsc/rsc-rendering.ts +712 -338
  248. package/src/rsc/server-action.ts +8 -20
  249. package/src/rsc/shell-build-manifest.ts +49 -29
  250. package/src/rsc/shell-capture-constants.ts +182 -12
  251. package/src/rsc/shell-capture.ts +1126 -612
  252. package/src/rsc/shell-serve.ts +331 -85
  253. package/src/rsc/ssr-setup.ts +3 -2
  254. package/src/rsc/types.ts +9 -0
  255. package/src/segment-system.tsx +40 -7
  256. package/src/server/context.ts +328 -72
  257. package/src/server/cookie-store.ts +184 -133
  258. package/src/server/handle-store.ts +245 -27
  259. package/src/server/request-context.ts +364 -100
  260. package/src/server/request-headers.ts +134 -0
  261. package/src/server.ts +4 -0
  262. package/src/ssr/index.tsx +96 -37
  263. package/src/ssr/ssr-root.tsx +9 -8
  264. package/src/testing/dispatch.ts +4 -7
  265. package/src/testing/e2e/index.ts +1 -0
  266. package/src/testing/flight.entry.ts +14 -0
  267. package/src/testing/index.ts +5 -0
  268. package/src/testing/internal/action-id.ts +25 -0
  269. package/src/testing/internal/context.ts +1 -1
  270. package/src/testing/location-state-key.ts +45 -0
  271. package/src/testing/render-handler.ts +1 -1
  272. package/src/testing/render-route.tsx +109 -16
  273. package/src/testing/run-client-revalidate.ts +3 -19
  274. package/src/testing/run-loader.ts +67 -5
  275. package/src/testing/run-transition-when.ts +109 -172
  276. package/src/testing/serve-shell-request.ts +381 -0
  277. package/src/testing/shell-status.ts +73 -47
  278. package/src/theme/ThemeProvider.tsx +7 -6
  279. package/src/transition-when-ref.ts +220 -0
  280. package/src/types/cache-types.ts +15 -3
  281. package/src/types/handler-context.ts +14 -1
  282. package/src/types/index.ts +3 -0
  283. package/src/types/segments.ts +94 -91
  284. package/src/urls/path-helper-types.ts +3 -4
  285. package/src/urls/pattern-types.ts +21 -18
  286. package/src/vite/discovery/discover-routers.ts +3 -0
  287. package/src/vite/discovery/shell-prerender-phase.ts +9 -2
  288. package/src/vite/discovery/virtual-module-codegen.ts +16 -6
  289. package/src/vite/plugins/transition-when-hoist.ts +1064 -0
  290. package/src/vite/rango.ts +2 -0
  291. package/src/vite/router-discovery.ts +89 -9
  292. package/dist/types/rsc/transition-gate.d.ts +0 -23
  293. package/src/rsc/transition-gate.ts +0 -86
@@ -1,195 +1,132 @@
1
1
  /**
2
- * runTransitionWhen — unit-test a transition({ when }) predicate in isolation.
2
+ * runTransitionWhen — unit-test a transition({ when }) browser predicate.
3
3
  *
4
- * Runs the SAME server functions the router uses — the PPR pre-handler evaluator
5
- * when `ppr: true`, applyViewTransitionDefault (which strips the server-only
6
- * function), and gateTransitions. So the
7
- * predicate sees exactly the navigation/action metadata it would at runtime
8
- * (currentUrl/currentParams/fromRouteName, nextUrl/nextParams/toRouteName,
9
- * actionId/actionUrl/actionResult/formData/method, get/env), and `kept` reflects
10
- * whether the transition would apply this request. The result also exposes the
11
- * assembled `whenContext` so tests can assert the exact fields without reaching
12
- * into private request-context state.
4
+ * Builds the context and evaluates the predicate through the SAME browser
5
+ * functions the router uses at navigation time (browser/transition-when.ts):
6
+ * a throw counts as false and is logged. `from`/`to` take a URL string or a
7
+ * partial RouteLocation; a `state` given as location-state entries
8
+ * (`[Def(value)]`, what Link/push take) is stored the way a push stores it,
9
+ * so `Def.read(ctx.to)` reads it back. Accepts the predicate or a whole
10
+ * TransitionConfig.
13
11
  *
14
- * This is the public way to exercise a transition gate: the full
15
- * match -> render pipeline that wires these together only runs under real RSC
16
- * rendering (which the Flight primitives do not drive), so without this primitive
17
- * a consumer could not test their predicate through @rangojs/router/testing.
18
- *
19
- * Synchronous: a transition predicate returns a boolean and the gate has no I/O.
12
+ * Synchronous: a transition predicate returns a boolean and has no I/O.
20
13
  */
21
14
 
22
15
  import {
23
- runWithRequestContext,
24
- type RequestContext,
25
- } from "../server/request-context.js";
26
- import { applyViewTransitionDefault } from "../router/segment-resolution/view-transition-default.js";
27
- import { gateTransitions } from "../rsc/transition-gate.js";
28
- import { createTestRequestContext, type VarsInit } from "./internal/context.js";
16
+ createTransitionWhenContext,
17
+ evaluateTransitionWhen,
18
+ type RouteLocationInput,
19
+ } from "../browser/transition-when.js";
20
+ import {
21
+ buildHistoryState,
22
+ resolveNavigationState,
23
+ } from "../browser/history-state.js";
24
+ import { isLocationStateEntry } from "../browser/react/location-state-shared.js";
25
+ import { resolveTestActionId } from "./internal/action-id.js";
29
26
  import type {
30
- ResolvedSegment,
27
+ RouteLocation,
31
28
  TransitionConfig,
32
29
  TransitionWhenContext,
30
+ TransitionWhenFn,
31
+ TransitionWhenKind,
33
32
  } from "../types/segments.js";
34
- import type { OnErrorCallback } from "../types/error-types.js";
35
- import type { EntryData } from "../server/context.js";
36
- import { evaluatePprTransitionWhen } from "../router/transition-when.js";
37
- import { invokeOnError } from "../router/error-handling.js";
38
- import { toURL } from "./to-url.js";
39
33
 
40
- /**
41
- * Options for runTransitionWhen. All navigation/action fields are optional and
42
- * default to "absent", matching what the gate sees for an initial full load with
43
- * no action: omit `currentUrl`/`currentParams`/`fromRouteName` to model the
44
- * navigation source being unavailable, and omit the `action*` fields to model a
45
- * plain (non-action) navigation.
46
- */
47
- export interface RunTransitionWhenOptions<TEnv = any> {
48
- /** The navigation TARGET request (drives `nextUrl`): a Request or URL/path string. Defaults to `http://localhost/`. */
49
- request?: Request | string;
50
- /** Route params for the target (`nextParams`). */
51
- params?: Record<string, string>;
52
- /** Target route name (`toRouteName`). */
53
- toRouteName?: string;
54
- /** Environment bindings surfaced as `env` (and `ctx.env`). */
55
- env?: TEnv;
56
- /** Variables readable via the predicate's `get()`. With `ppr`, these model pre-handler middleware/input state. */
57
- vars?: VarsInit;
58
- /** Navigation SOURCE url (`currentUrl`): a URL or path string. */
59
- currentUrl?: string | URL;
60
- /** Source route params (`currentParams`). */
61
- currentParams?: Record<string, string>;
62
- /** Source route name (`fromRouteName`). */
63
- fromRouteName?: string;
64
- /** Id of the action that triggered a revalidation (`actionId`). */
65
- actionId?: string;
66
- /** Url the action was submitted from (`actionUrl`). */
67
- actionUrl?: string | URL;
68
- /** The action's return value (`actionResult`). */
69
- actionResult?: unknown;
70
- /** FormData from a form action (`formData`). */
34
+ type ImportedAction = (...args: never[]) => unknown;
35
+
36
+ /** A navigation side: a URL, or a partial RouteLocation. */
37
+ export type RunTransitionWhenLocation =
38
+ | string
39
+ | URL
40
+ | (Partial<Omit<RouteLocation, "url">> & { url?: string | URL });
41
+
42
+ /** The action fields of a `kind: "action"` context. */
43
+ export interface RunTransitionWhenAction {
44
+ /** The triggering action: an imported server action or its actionId. */
45
+ ref?: ImportedAction | string;
71
46
  formData?: FormData;
72
- /** Receives an error thrown by the predicate (the gate reports to `router.onError`, phase `"rendering"`). */
73
- onError?: OnErrorCallback;
74
- /** Model a route with `ppr`, where the predicate runs before route handlers and cache lookup. */
75
- ppr?: boolean;
47
+ /** The action's return value on success. */
48
+ result?: unknown;
49
+ /** What a failed action threw (the error lane). */
50
+ error?: unknown;
76
51
  }
77
52
 
78
- /**
79
- * Result of runTransitionWhen.
80
- */
81
- export interface RunTransitionWhenResult<TEnv = any> {
82
- /** True if the transition would apply this request (predicate returned non-false, or there is no `when`). */
83
- kept: boolean;
84
- /** Convenience inverse of `kept`. */
85
- dropped: boolean;
53
+ export interface RunTransitionWhenOptions {
54
+ /** Defaults to `"action"` when `action` is given, `"push"` otherwise. */
55
+ kind?: TransitionWhenKind;
56
+ /** The committed location being left. Defaults to `http://localhost/`. */
57
+ from?: RunTransitionWhenLocation;
58
+ /** The destination. Defaults to `from`; always `from` for "action" and "revalidate". */
59
+ to?: RunTransitionWhenLocation;
86
60
  /**
87
- * The production-assembled predicate context. Undefined when the config has
88
- * no `when` predicate.
61
+ * The triggering action (like runClientRevalidate's): an imported server
62
+ * action (id via `$id ?? $$id`), an actionId string, or
63
+ * `{ ref, formData, result, error }`.
89
64
  */
90
- whenContext?: TransitionWhenContext<Record<string, string>, TEnv>;
91
- /** The underlying RequestContext, for additional assertions (`ctx.get(...)`, etc.). */
92
- ctx: RequestContext<TEnv>;
65
+ action?: ImportedAction | string | RunTransitionWhenAction;
93
66
  }
94
67
 
95
- export function runTransitionWhen<TEnv = any>(
96
- config: TransitionConfig,
97
- opts: RunTransitionWhenOptions<TEnv> = {},
98
- ): RunTransitionWhenResult<TEnv> {
99
- const { ctx } = createTestRequestContext<TEnv>({
100
- env: opts.env,
101
- request: opts.request,
102
- vars: opts.vars,
103
- params: opts.params,
104
- });
105
- const reqCtx = ctx as unknown as RequestContext<TEnv>;
68
+ export interface RunTransitionWhenResult {
69
+ /** True when the navigation holds (the predicate did not return false or throw, or there is none). */
70
+ applied: boolean;
71
+ /** Inverse of `applied`. */
72
+ gatedOff: boolean;
73
+ /** The context the predicate received. */
74
+ context: TransitionWhenContext;
75
+ }
106
76
 
107
- // Target route name (the public field the gate reads for `toRouteName`).
108
- if (opts.toRouteName !== undefined)
109
- reqCtx.routeName = opts.toRouteName as RequestContext<TEnv>["routeName"];
110
- // Source (match-time) data the gate reads for currentUrl/currentParams/fromRouteName.
111
- if (opts.currentUrl !== undefined)
112
- reqCtx._gateCurrentUrl = toURL(opts.currentUrl, reqCtx.url);
113
- if (opts.currentParams !== undefined)
114
- reqCtx._gateCurrentParams = opts.currentParams;
115
- if (opts.fromRouteName !== undefined)
116
- reqCtx._prevRouteKey = opts.fromRouteName;
117
- // Action data the gate reads at the action-bearing call sites.
118
- if (opts.actionId !== undefined) reqCtx._gateActionId = opts.actionId;
119
- if (opts.actionUrl !== undefined)
120
- reqCtx._gateActionUrl = toURL(opts.actionUrl, reqCtx.url);
121
- if (opts.actionResult !== undefined)
122
- reqCtx._gateActionResult = opts.actionResult;
123
- if (opts.formData !== undefined) reqCtx._gateFormData = opts.formData;
77
+ const DEFAULT_URL = "http://localhost/";
124
78
 
125
- let whenContext:
126
- | TransitionWhenContext<Record<string, string>, TEnv>
127
- | undefined;
128
- const when = config.when;
129
- const configForGate: TransitionConfig = when
130
- ? {
131
- ...config,
132
- when: (c) => {
133
- whenContext = c as TransitionWhenContext<
134
- Record<string, string>,
135
- TEnv
136
- >;
137
- return when(c);
138
- },
139
- }
140
- : config;
79
+ function toStoredState(state: unknown): unknown {
80
+ if (
81
+ Array.isArray(state) &&
82
+ state.length > 0 &&
83
+ isLocationStateEntry(state[0])
84
+ ) {
85
+ return buildHistoryState(resolveNavigationState(state));
86
+ }
87
+ return state;
88
+ }
89
+
90
+ function toLocation(
91
+ value: RunTransitionWhenLocation | undefined,
92
+ fallback: string | URL,
93
+ ): RouteLocationInput {
94
+ if (value === undefined) return { url: fallback };
95
+ if (typeof value === "string" || value instanceof URL) return { url: value };
96
+ return {
97
+ url: value.url ?? fallback,
98
+ params: value.params,
99
+ routeName: value.routeName,
100
+ state: toStoredState(value.state),
101
+ };
102
+ }
141
103
 
142
- return runWithRequestContext(reqCtx, () => {
143
- if (opts.ppr) {
144
- const entry = {
145
- type: "route",
146
- id: "tx-when-entry",
147
- shortCode: "tx-when-seg",
148
- parent: null,
149
- transition: configForGate,
150
- layout: [],
151
- parallel: {},
152
- } as unknown as EntryData;
153
- evaluatePprTransitionWhen(
154
- [entry],
155
- reqCtx,
156
- { params: reqCtx.params, routeName: opts.toRouteName },
157
- (error, segmentId) =>
158
- invokeOnError(
159
- opts.onError,
160
- error,
161
- "rendering",
162
- {
163
- request: reqCtx.request,
164
- url: reqCtx.url,
165
- params: reqCtx.params,
166
- segmentId,
167
- },
168
- "RSC",
169
- ),
170
- );
171
- }
172
- // Ordinary predicates are collected here and evaluated by the gate. PPR
173
- // predicates keep the decision already evaluated before this step.
174
- const serialized = applyViewTransitionDefault(
175
- configForGate,
176
- undefined,
177
- "tx-when-seg",
178
- );
179
- const segment = {
180
- id: "tx-when-seg",
181
- namespace: "r",
182
- type: "route",
183
- index: 0,
184
- component: null,
185
- transition: serialized,
186
- } as ResolvedSegment;
187
- const [gatedSegment] = gateTransitions(
188
- [segment],
189
- reqCtx as Parameters<typeof gateTransitions>[1],
190
- opts.onError,
191
- );
192
- const kept = gatedSegment.transition !== undefined;
193
- return { kept, dropped: !kept, whenContext, ctx: reqCtx };
104
+ export function runTransitionWhen(
105
+ whenOrConfig: TransitionWhenFn | TransitionConfig,
106
+ opts: RunTransitionWhenOptions = {},
107
+ ): RunTransitionWhenResult {
108
+ const actionOption =
109
+ typeof opts.action === "function" || typeof opts.action === "string"
110
+ ? { ref: opts.action }
111
+ : opts.action;
112
+ const from = toLocation(opts.from, DEFAULT_URL);
113
+ const context = createTransitionWhenContext({
114
+ kind: opts.kind ?? (actionOption ? "action" : "push"),
115
+ from,
116
+ to: opts.to === undefined ? undefined : toLocation(opts.to, from.url),
117
+ ...(actionOption
118
+ ? {
119
+ action: {
120
+ id: resolveTestActionId(actionOption.ref, "runTransitionWhen"),
121
+ formData: actionOption.formData,
122
+ result: actionOption.result,
123
+ error: actionOption.error,
124
+ },
125
+ }
126
+ : {}),
194
127
  });
128
+ const when =
129
+ typeof whenOrConfig === "function" ? whenOrConfig : whenOrConfig.when;
130
+ const applied = when ? evaluateTransitionWhen(when, context) : true;
131
+ return { applied, gatedOff: !applied, context };
195
132
  }