@rangojs/router 0.0.0-experimental.98 → 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.
- package/README.md +24 -9
- package/dist/bin/rango.js +157 -63
- package/dist/testing/vitest.js +82 -0
- package/dist/vite/index.js +1584 -639
- package/package.json +60 -11
- package/skills/api-client/SKILL.md +211 -0
- package/skills/breadcrumbs/SKILL.md +60 -0
- package/skills/bundle-analysis/SKILL.md +159 -0
- package/skills/cache-guide/SKILL.md +222 -30
- package/skills/caching/SKILL.md +263 -8
- package/skills/composability/SKILL.md +27 -2
- package/skills/css/SKILL.md +76 -0
- package/skills/document-cache/SKILL.md +78 -55
- package/skills/handler-use/SKILL.md +3 -1
- package/skills/hooks/SKILL.md +235 -28
- package/skills/host-router/SKILL.md +122 -22
- package/skills/intercept/SKILL.md +29 -5
- package/skills/layout/SKILL.md +13 -9
- package/skills/links/SKILL.md +173 -17
- package/skills/loader/SKILL.md +170 -23
- package/skills/middleware/SKILL.md +16 -10
- package/skills/migrate-nextjs/SKILL.md +38 -16
- package/skills/mime-routes/SKILL.md +27 -0
- package/skills/observability/SKILL.md +137 -0
- package/skills/parallel/SKILL.md +11 -7
- package/skills/prerender/SKILL.md +14 -33
- package/skills/rango/SKILL.md +250 -26
- package/skills/react-compiler/SKILL.md +168 -0
- package/skills/response-routes/SKILL.md +114 -47
- package/skills/route/SKILL.md +22 -5
- package/skills/router-setup/SKILL.md +3 -3
- package/skills/server-actions/SKILL.md +78 -42
- package/skills/tailwind/SKILL.md +27 -3
- package/skills/testing/SKILL.md +129 -0
- package/skills/testing/bindings.md +89 -0
- package/skills/testing/cache-prerender.md +124 -0
- package/skills/testing/client-components.md +122 -0
- package/skills/testing/e2e-parity.md +125 -0
- package/skills/testing/flight.md +92 -0
- package/skills/testing/handles.md +129 -0
- package/skills/testing/loader.md +128 -0
- package/skills/testing/middleware.md +99 -0
- package/skills/testing/render-handler.md +121 -0
- package/skills/testing/response-routes.md +95 -0
- package/skills/testing/reverse-and-types.md +84 -0
- package/skills/testing/server-actions.md +107 -0
- package/skills/testing/server-tree.md +128 -0
- package/skills/testing/setup.md +120 -0
- package/skills/typesafety/SKILL.md +310 -26
- package/skills/use-cache/SKILL.md +36 -5
- package/skills/vercel/SKILL.md +107 -0
- package/skills/view-transitions/SKILL.md +294 -0
- package/src/__augment-tests__/augment.ts +81 -0
- package/src/__augment-tests__/augmented.check.ts +116 -0
- package/src/__internal.ts +0 -65
- package/src/browser/action-coordinator.ts +53 -36
- package/src/browser/action-fence.ts +47 -0
- package/src/browser/app-shell.ts +14 -27
- package/src/browser/cookie-name.ts +140 -0
- package/src/browser/event-controller.ts +37 -143
- package/src/browser/history-state.ts +21 -0
- package/src/browser/index.ts +3 -3
- package/src/browser/invalidate-client-cache.ts +52 -0
- package/src/browser/navigation-bridge.ts +30 -59
- package/src/browser/navigation-client.ts +96 -84
- package/src/browser/navigation-store-handle.ts +38 -0
- package/src/browser/navigation-store.ts +32 -82
- package/src/browser/navigation-transaction.ts +9 -59
- package/src/browser/partial-update.ts +60 -127
- package/src/browser/prefetch/cache.ts +82 -72
- package/src/browser/prefetch/fetch.ts +108 -33
- package/src/browser/prefetch/queue.ts +6 -3
- package/src/browser/rango-state.ts +157 -115
- package/src/browser/react/Link.tsx +0 -2
- package/src/browser/react/NavigationProvider.tsx +41 -48
- package/src/browser/react/ScrollRestoration.tsx +10 -6
- package/src/browser/react/filter-segment-order.ts +0 -2
- package/src/browser/react/index.ts +0 -48
- package/src/browser/react/location-state-shared.ts +166 -8
- package/src/browser/react/location-state.ts +39 -14
- package/src/browser/react/use-action.ts +6 -15
- package/src/browser/react/use-handle.ts +17 -14
- package/src/browser/react/use-link-status.ts +0 -4
- package/src/browser/react/use-navigation.ts +0 -3
- package/src/browser/react/use-params.ts +3 -6
- package/src/browser/react/use-reverse.ts +106 -0
- package/src/browser/react/use-router.ts +20 -5
- package/src/browser/react/use-search-params.ts +0 -5
- package/src/browser/react/use-segments.ts +0 -13
- package/src/browser/response-adapter.ts +52 -1
- package/src/browser/rsc-router.tsx +70 -34
- package/src/browser/scroll-restoration.ts +22 -14
- package/src/browser/segment-structure-assert.ts +2 -2
- package/src/browser/server-action-bridge.ts +168 -44
- package/src/browser/types.ts +36 -21
- package/src/browser/validate-redirect-origin.ts +43 -16
- package/src/build/collect-fallback-refs.ts +107 -0
- package/src/build/generate-manifest.ts +60 -35
- package/src/build/generate-route-types.ts +3 -0
- package/src/build/index.ts +8 -2
- package/src/build/prefix-tree-utils.ts +123 -0
- package/src/build/route-trie.ts +89 -11
- package/src/build/route-types/codegen.ts +4 -4
- package/src/build/route-types/include-resolution.ts +1 -1
- package/src/build/route-types/param-extraction.ts +6 -3
- package/src/build/route-types/per-module-writer.ts +7 -4
- package/src/build/route-types/router-processing.ts +122 -22
- package/src/build/route-types/scan-filter.ts +1 -1
- package/src/build/route-types/source-scan.ts +118 -0
- package/src/build/runtime-discovery.ts +9 -20
- package/src/cache/cache-error.ts +104 -0
- package/src/cache/cache-policy.ts +68 -28
- package/src/cache/cache-runtime.ts +134 -32
- package/src/cache/cache-scope.ts +100 -74
- package/src/cache/cache-tag.ts +98 -0
- package/src/cache/cf/cf-cache-store.ts +2255 -238
- package/src/cache/cf/index.ts +6 -16
- package/src/cache/document-cache.ts +61 -20
- package/src/cache/handle-snapshot.ts +63 -0
- package/src/cache/index.ts +22 -20
- package/src/cache/memory-segment-store.ts +136 -37
- package/src/cache/profile-registry.ts +6 -30
- package/src/cache/read-through-swr.ts +41 -11
- package/src/cache/segment-codec.ts +0 -16
- package/src/cache/tag-invalidation.ts +230 -0
- package/src/cache/types.ts +33 -100
- package/src/cache/vercel/index.ts +11 -0
- package/src/cache/vercel/vercel-cache-store.ts +799 -0
- package/src/client.rsc.tsx +6 -21
- package/src/client.tsx +25 -61
- package/src/component-utils.ts +19 -0
- package/src/context-var.ts +17 -5
- package/src/decode-loader-results.ts +36 -0
- package/src/defer.ts +196 -0
- package/src/deps/ssr.ts +0 -1
- package/src/errors.ts +30 -4
- package/src/handle.ts +31 -23
- package/src/handles/MetaTags.tsx +0 -14
- package/src/handles/breadcrumbs.ts +16 -5
- package/src/handles/meta.ts +0 -39
- package/src/host/cookie-handler.ts +0 -36
- package/src/host/errors.ts +0 -24
- package/src/host/index.ts +8 -2
- package/src/host/pattern-matcher.ts +7 -50
- package/src/host/router.ts +107 -99
- package/src/host/testing.ts +40 -27
- package/src/host/types.ts +37 -4
- package/src/host/utils.ts +1 -1
- package/src/href-client.ts +137 -22
- package/src/index.rsc.ts +63 -9
- package/src/index.ts +64 -9
- package/src/internal-debug.ts +2 -4
- package/src/loader-store.ts +500 -0
- package/src/loader.rsc.ts +20 -13
- package/src/loader.ts +12 -11
- package/src/missing-id-error.ts +68 -0
- package/src/network-error-thrower.tsx +1 -6
- package/src/outlet-provider.tsx +1 -5
- package/src/prerender/param-hash.ts +10 -11
- package/src/prerender/store.ts +32 -37
- package/src/prerender.ts +61 -6
- package/src/redirect-origin.ts +100 -0
- package/src/response-utils.ts +9 -0
- package/src/reverse.ts +65 -41
- package/src/root-error-boundary.tsx +1 -19
- package/src/route-content-wrapper.tsx +7 -72
- package/src/route-definition/dsl-helpers.ts +244 -281
- package/src/route-definition/helper-factories.ts +29 -139
- package/src/route-definition/helpers-types.ts +40 -17
- package/src/route-definition/redirect.ts +43 -9
- package/src/route-definition/resolve-handler-use.ts +6 -0
- package/src/route-definition/use-item-types.ts +32 -0
- package/src/route-map-builder.ts +0 -16
- package/src/route-types.ts +19 -41
- package/src/router/basename.ts +14 -0
- package/src/router/content-negotiation.ts +15 -15
- package/src/router/error-handling.ts +13 -17
- package/src/router/find-match.ts +44 -23
- package/src/router/handler-context.ts +4 -42
- package/src/router/intercept-resolution.ts +14 -19
- package/src/router/lazy-includes.ts +9 -46
- package/src/router/loader-resolution.ts +91 -46
- package/src/router/logging.ts +0 -6
- package/src/router/manifest.ts +18 -29
- package/src/router/match-api.ts +0 -20
- package/src/router/match-context.ts +0 -22
- package/src/router/match-handlers.ts +57 -58
- package/src/router/match-middleware/background-revalidation.ts +0 -7
- package/src/router/match-middleware/cache-lookup.ts +150 -271
- package/src/router/match-middleware/cache-store.ts +3 -33
- package/src/router/match-middleware/intercept-resolution.ts +0 -22
- package/src/router/match-middleware/segment-resolution.ts +0 -22
- package/src/router/match-pipelines.ts +1 -42
- package/src/router/match-result.ts +31 -80
- package/src/router/metrics.ts +0 -34
- package/src/router/middleware-types.ts +0 -116
- package/src/router/middleware.ts +118 -133
- package/src/router/navigation-snapshot.ts +0 -51
- package/src/router/params-util.ts +23 -0
- package/src/router/pattern-matching.ts +20 -58
- package/src/router/prerender-match.ts +99 -63
- package/src/router/preview-match.ts +3 -1
- package/src/router/request-classification.ts +28 -62
- package/src/router/revalidation.ts +50 -56
- package/src/router/route-snapshot.ts +0 -1
- package/src/router/router-context.ts +0 -27
- package/src/router/router-interfaces.ts +68 -35
- package/src/router/router-options.ts +55 -1
- package/src/router/router-registry.ts +2 -5
- package/src/router/segment-resolution/fresh.ts +44 -63
- package/src/router/segment-resolution/helpers.ts +34 -0
- package/src/router/segment-resolution/loader-cache.ts +40 -37
- package/src/router/segment-resolution/revalidation.ts +203 -285
- package/src/router/segment-resolution/static-store.ts +19 -5
- package/src/router/segment-resolution/streamed-handler-telemetry.ts +52 -0
- package/src/router/segment-resolution/view-transition-default.ts +36 -0
- package/src/router/segment-resolution.ts +4 -1
- package/src/router/segment-wrappers.ts +0 -3
- package/src/router/state-cookie-name.ts +33 -0
- package/src/router/substitute-pattern-params.ts +56 -0
- package/src/router/telemetry-otel.ts +0 -20
- package/src/router/telemetry.ts +96 -19
- package/src/router/timeout.ts +0 -20
- package/src/router/trie-matching.ts +87 -47
- package/src/router/types.ts +9 -63
- package/src/router/url-params.ts +0 -5
- package/src/router.ts +80 -41
- package/src/rsc/handler-context.ts +3 -2
- package/src/rsc/handler.ts +83 -78
- package/src/rsc/helpers.ts +93 -5
- package/src/rsc/index.ts +1 -1
- package/src/rsc/json-route-result.ts +38 -0
- package/src/rsc/manifest-init.ts +28 -41
- package/src/rsc/origin-guard.ts +39 -25
- package/src/rsc/progressive-enhancement.ts +12 -1
- package/src/rsc/redirect-guard.ts +99 -0
- package/src/rsc/response-error.ts +79 -12
- package/src/rsc/response-route-handler.ts +76 -62
- package/src/rsc/rsc-rendering.ts +41 -60
- package/src/rsc/runtime-warnings.ts +23 -10
- package/src/rsc/server-action.ts +62 -67
- package/src/rsc/ssr-setup.ts +16 -0
- package/src/rsc/types.ts +10 -5
- package/src/runtime-env.ts +18 -0
- package/src/search-params.ts +4 -20
- package/src/segment-loader-promise.ts +14 -2
- package/src/segment-system.tsx +199 -142
- package/src/serialize.ts +243 -0
- package/src/server/context.ts +150 -51
- package/src/server/cookie-store.ts +80 -5
- package/src/server/handle-store.ts +7 -24
- package/src/server/loader-registry.ts +5 -24
- package/src/server/request-context.ts +165 -87
- package/src/ssr/index.tsx +14 -14
- package/src/static-handler.ts +10 -13
- package/src/testing/cache-status.ts +162 -0
- package/src/testing/collect-handle.ts +40 -0
- package/src/testing/dispatch.ts +618 -0
- package/src/testing/dom.entry.ts +22 -0
- package/src/testing/e2e/fixture.ts +188 -0
- package/src/testing/e2e/index.ts +128 -0
- package/src/testing/e2e/matchers.ts +35 -0
- package/src/testing/e2e/page-helpers.ts +272 -0
- package/src/testing/e2e/parity.ts +387 -0
- package/src/testing/e2e/server.ts +195 -0
- package/src/testing/flight-matchers.ts +97 -0
- package/src/testing/flight-normalize.ts +11 -0
- package/src/testing/flight-runtime.d.ts +57 -0
- package/src/testing/flight-tree.ts +682 -0
- package/src/testing/flight.entry.ts +52 -0
- package/src/testing/flight.ts +232 -0
- package/src/testing/generated-routes.ts +183 -0
- package/src/testing/index.ts +99 -0
- package/src/testing/internal/context.ts +348 -0
- package/src/testing/internal/flight-client-globals.ts +30 -0
- package/src/testing/internal/seed-vars.ts +54 -0
- package/src/testing/render-handler.ts +330 -0
- package/src/testing/render-route.tsx +566 -0
- package/src/testing/run-loader.ts +378 -0
- package/src/testing/run-middleware.ts +205 -0
- package/src/testing/vitest-stubs/cloudflare-email.ts +9 -0
- package/src/testing/vitest-stubs/cloudflare-workers.ts +21 -0
- package/src/testing/vitest-stubs/plugin-rsc.ts +16 -0
- package/src/testing/vitest-stubs/version.ts +5 -0
- package/src/testing/vitest.ts +305 -0
- package/src/theme/ThemeProvider.tsx +0 -52
- package/src/theme/ThemeScript.tsx +0 -6
- package/src/theme/constants.ts +0 -12
- package/src/theme/index.ts +0 -7
- package/src/theme/theme-context.ts +1 -5
- package/src/theme/theme-script.ts +0 -14
- package/src/theme/use-theme.ts +0 -3
- package/src/types/boundaries.ts +0 -35
- package/src/types/cache-types.ts +13 -4
- package/src/types/error-types.ts +30 -90
- package/src/types/global-namespace.ts +54 -41
- package/src/types/handler-context.ts +97 -22
- package/src/types/index.ts +1 -10
- package/src/types/loader-types.ts +6 -3
- package/src/types/request-scope.ts +0 -19
- package/src/types/route-config.ts +6 -50
- package/src/types/route-entry.ts +0 -6
- package/src/types/segments.ts +18 -14
- package/src/urls/include-helper.ts +9 -56
- package/src/urls/index.ts +1 -11
- package/src/urls/path-helper-types.ts +19 -5
- package/src/urls/path-helper.ts +17 -106
- package/src/urls/pattern-types.ts +36 -19
- package/src/urls/response-types.ts +20 -19
- package/src/urls/type-extraction.ts +58 -139
- package/src/urls/urls-function.ts +1 -18
- package/src/use-loader.tsx +292 -107
- package/src/vite/debug.ts +1 -0
- package/src/vite/discovery/bundle-postprocess.ts +8 -7
- package/src/vite/discovery/discover-routers.ts +95 -82
- package/src/vite/discovery/discovery-errors.ts +194 -0
- package/src/vite/discovery/prerender-collection.ts +26 -34
- package/src/vite/discovery/route-types-writer.ts +40 -84
- package/src/vite/discovery/state.ts +39 -1
- package/src/vite/discovery/virtual-module-codegen.ts +14 -34
- package/src/vite/index.ts +4 -0
- package/src/vite/plugin-types.ts +185 -10
- package/src/vite/plugins/cjs-to-esm.ts +3 -18
- package/src/vite/plugins/client-ref-dedup.ts +0 -11
- package/src/vite/plugins/client-ref-hashing.ts +12 -11
- package/src/vite/plugins/cloudflare-protocol-stub.ts +1 -21
- package/src/vite/plugins/expose-action-id.ts +4 -75
- package/src/vite/plugins/expose-id-utils.ts +3 -54
- package/src/vite/plugins/expose-ids/export-analysis.ts +76 -34
- package/src/vite/plugins/expose-ids/handler-transform.ts +6 -74
- package/src/vite/plugins/expose-ids/loader-transform.ts +3 -20
- package/src/vite/plugins/expose-ids/router-transform.ts +0 -13
- package/src/vite/plugins/expose-internal-ids.ts +57 -67
- package/src/vite/plugins/performance-tracks.ts +9 -16
- package/src/vite/plugins/refresh-cmd.ts +1 -1
- package/src/vite/plugins/use-cache-transform.ts +26 -49
- package/src/vite/plugins/vercel-output.ts +258 -0
- package/src/vite/plugins/version-injector.ts +2 -32
- package/src/vite/plugins/version-plugin.ts +32 -23
- package/src/vite/plugins/virtual-entries.ts +35 -17
- package/src/vite/rango.ts +148 -115
- package/src/vite/router-discovery.ts +220 -68
- package/src/vite/utils/ast-handler-extract.ts +15 -31
- package/src/vite/utils/bundle-analysis.ts +10 -15
- package/src/vite/utils/client-chunks.ts +184 -0
- package/src/vite/utils/forward-user-plugins.ts +171 -0
- package/src/vite/utils/manifest-utils.ts +4 -59
- package/src/vite/utils/package-resolution.ts +1 -73
- package/src/vite/utils/prerender-utils.ts +0 -35
- package/src/vite/utils/shared-utils.ts +95 -43
- package/src/browser/action-response-classifier.ts +0 -99
- package/src/browser/react/use-client-cache.ts +0 -58
- package/src/browser/shallow.ts +0 -40
- package/src/handles/index.ts +0 -7
- package/src/router/middleware-cookies.ts +0 -55
|
@@ -23,10 +23,6 @@ import { negotiateRoute } from "./content-negotiation.js";
|
|
|
23
23
|
import { stripInternalParams } from "./handler-context.js";
|
|
24
24
|
import { resolveRoute, type RouteSnapshot } from "./route-snapshot.js";
|
|
25
25
|
|
|
26
|
-
// ---------------------------------------------------------------------------
|
|
27
|
-
// RequestPlan — discriminated union
|
|
28
|
-
// ---------------------------------------------------------------------------
|
|
29
|
-
|
|
30
26
|
interface RedirectPlan<TEnv = any> {
|
|
31
27
|
mode: "redirect";
|
|
32
28
|
route: RouteSnapshot<TEnv>;
|
|
@@ -40,6 +36,12 @@ interface VersionMismatchPlan<TEnv = any> {
|
|
|
40
36
|
reloadUrl: string;
|
|
41
37
|
}
|
|
42
38
|
|
|
39
|
+
interface AppSwitchReloadPlan {
|
|
40
|
+
mode: "app-switch";
|
|
41
|
+
/** Clean target URL (internal _rsc_* params stripped) to navigate to. */
|
|
42
|
+
reloadUrl: string;
|
|
43
|
+
}
|
|
44
|
+
|
|
43
45
|
interface ResponseRoutePlan<TEnv = any> {
|
|
44
46
|
mode: "response";
|
|
45
47
|
route: RouteSnapshot<TEnv>;
|
|
@@ -86,6 +88,7 @@ interface PartialRenderPlan<TEnv = any> {
|
|
|
86
88
|
export type RequestPlan<TEnv = any> =
|
|
87
89
|
| RedirectPlan<TEnv>
|
|
88
90
|
| VersionMismatchPlan<TEnv>
|
|
91
|
+
| AppSwitchReloadPlan
|
|
89
92
|
| ResponseRoutePlan<TEnv>
|
|
90
93
|
| LoaderFetchPlan<TEnv>
|
|
91
94
|
| PeRenderPlan<TEnv>
|
|
@@ -94,12 +97,13 @@ export type RequestPlan<TEnv = any> =
|
|
|
94
97
|
| PartialRenderPlan<TEnv>;
|
|
95
98
|
|
|
96
99
|
/**
|
|
97
|
-
* Plans that have passed the terminal-check gate (version-mismatch
|
|
98
|
-
* and are ready for execution. Always have a
|
|
100
|
+
* Plans that have passed the terminal-check gate (version-mismatch and
|
|
101
|
+
* app-switch reloads handled) and are ready for execution. Always have a
|
|
102
|
+
* `route` field.
|
|
99
103
|
*/
|
|
100
104
|
export type ExecutableRequestPlan<TEnv = any> = Exclude<
|
|
101
105
|
RequestPlan<TEnv>,
|
|
102
|
-
VersionMismatchPlan<TEnv>
|
|
106
|
+
VersionMismatchPlan<TEnv> | AppSwitchReloadPlan
|
|
103
107
|
>;
|
|
104
108
|
|
|
105
109
|
/**
|
|
@@ -116,10 +120,6 @@ export type {
|
|
|
116
120
|
PartialRenderPlan,
|
|
117
121
|
};
|
|
118
122
|
|
|
119
|
-
// ---------------------------------------------------------------------------
|
|
120
|
-
// classifyRequest — the single authoritative classification step
|
|
121
|
-
// ---------------------------------------------------------------------------
|
|
122
|
-
|
|
123
123
|
export interface ClassifyRequestDeps<TEnv = any> {
|
|
124
124
|
findMatch: (pathname: string) => RouteMatchResult<TEnv> | null;
|
|
125
125
|
routerVersion: string;
|
|
@@ -149,15 +149,12 @@ export async function classifyRequest<TEnv = any>(
|
|
|
149
149
|
const isAction =
|
|
150
150
|
request.headers.has("rsc-action") || url.searchParams.has("_rsc_action");
|
|
151
151
|
|
|
152
|
-
// Version mismatch — runs BEFORE route resolution so stale clients
|
|
153
|
-
// requesting removed routes get a reload, not a 404.
|
|
154
152
|
const clientVersion = url.searchParams.get("_rsc_v");
|
|
155
153
|
if (
|
|
156
154
|
deps.routerVersion &&
|
|
157
155
|
clientVersion &&
|
|
158
156
|
clientVersion !== deps.routerVersion
|
|
159
157
|
) {
|
|
160
|
-
// Strip internal _rsc_* params so the browser reloads to a clean URL
|
|
161
158
|
let reloadUrl = stripInternalParams(url).toString();
|
|
162
159
|
if (isAction) {
|
|
163
160
|
const referer = request.headers.get("referer");
|
|
@@ -167,9 +164,7 @@ export async function classifyRequest<TEnv = any>(
|
|
|
167
164
|
if (refererUrl.origin === url.origin) {
|
|
168
165
|
reloadUrl = referer;
|
|
169
166
|
}
|
|
170
|
-
} catch {
|
|
171
|
-
// Malformed referer, fall back to stripped url
|
|
172
|
-
}
|
|
167
|
+
} catch {}
|
|
173
168
|
}
|
|
174
169
|
}
|
|
175
170
|
|
|
@@ -179,9 +174,18 @@ export async function classifyRequest<TEnv = any>(
|
|
|
179
174
|
};
|
|
180
175
|
}
|
|
181
176
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
177
|
+
const clientRouterId = url.searchParams.get("_rsc_rid");
|
|
178
|
+
if (
|
|
179
|
+
clientRouterId &&
|
|
180
|
+
clientRouterId !== deps.routerId &&
|
|
181
|
+
url.searchParams.has("_rsc_partial")
|
|
182
|
+
) {
|
|
183
|
+
return {
|
|
184
|
+
mode: "app-switch",
|
|
185
|
+
reloadUrl: stripInternalParams(url).toString(),
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
|
|
185
189
|
const result = await resolveRoute<TEnv>(pathname, {
|
|
186
190
|
findMatch: deps.findMatch,
|
|
187
191
|
lite: true,
|
|
@@ -193,7 +197,6 @@ export async function classifyRequest<TEnv = any>(
|
|
|
193
197
|
});
|
|
194
198
|
}
|
|
195
199
|
|
|
196
|
-
// Redirect
|
|
197
200
|
if (result.type === "redirect") {
|
|
198
201
|
const snapshot: RouteSnapshot<TEnv> = {
|
|
199
202
|
matched: result as any,
|
|
@@ -215,7 +218,6 @@ export async function classifyRequest<TEnv = any>(
|
|
|
215
218
|
|
|
216
219
|
const snapshot = result.snapshot;
|
|
217
220
|
|
|
218
|
-
// Response route — non-RSC short-circuit (JSON, streaming, etc.)
|
|
219
221
|
const responseResult = await classifyResponseRoute(
|
|
220
222
|
request,
|
|
221
223
|
pathname,
|
|
@@ -225,7 +227,6 @@ export async function classifyRequest<TEnv = any>(
|
|
|
225
227
|
return responseResult;
|
|
226
228
|
}
|
|
227
229
|
|
|
228
|
-
// Mode detection from request signals
|
|
229
230
|
const actionId =
|
|
230
231
|
request.headers.get("rsc-action") || url.searchParams.get("_rsc_action");
|
|
231
232
|
const isLoaderFetch = url.searchParams.has("_rsc_loader");
|
|
@@ -243,7 +244,6 @@ export async function classifyRequest<TEnv = any>(
|
|
|
243
244
|
return { mode: "loader", route: snapshot };
|
|
244
245
|
}
|
|
245
246
|
|
|
246
|
-
// PE detection: POST with form content-type, but not a server action
|
|
247
247
|
const contentType = request.headers.get("content-type") || "";
|
|
248
248
|
const isFormSubmission =
|
|
249
249
|
contentType.includes("multipart/form-data") ||
|
|
@@ -252,22 +252,13 @@ export async function classifyRequest<TEnv = any>(
|
|
|
252
252
|
return { mode: "pe-render", route: snapshot };
|
|
253
253
|
}
|
|
254
254
|
|
|
255
|
-
|
|
256
|
-
const clientRouterId = url.searchParams.get("_rsc_rid");
|
|
257
|
-
const isAppSwitch = !!(clientRouterId && clientRouterId !== deps.routerId);
|
|
258
|
-
const isPartial = url.searchParams.has("_rsc_partial") && !isAppSwitch;
|
|
259
|
-
|
|
260
|
-
if (isPartial) {
|
|
255
|
+
if (url.searchParams.has("_rsc_partial")) {
|
|
261
256
|
return { mode: "partial-render", route: snapshot, negotiated };
|
|
262
257
|
}
|
|
263
258
|
|
|
264
259
|
return { mode: "full-render", route: snapshot, negotiated };
|
|
265
260
|
}
|
|
266
261
|
|
|
267
|
-
// ---------------------------------------------------------------------------
|
|
268
|
-
// Content negotiation for response routes
|
|
269
|
-
// ---------------------------------------------------------------------------
|
|
270
|
-
|
|
271
262
|
/**
|
|
272
263
|
* Check if the route is a response route and perform content negotiation
|
|
273
264
|
* if negotiate variants exist. Returns a ResponseRoutePlan if the route
|
|
@@ -278,33 +269,8 @@ async function classifyResponseRoute<TEnv>(
|
|
|
278
269
|
pathname: string,
|
|
279
270
|
snapshot: RouteSnapshot<TEnv>,
|
|
280
271
|
): Promise<ResponseRoutePlan<TEnv> | null> {
|
|
281
|
-
const { manifestEntry, responseType } = snapshot;
|
|
282
|
-
|
|
283
272
|
const negotiation = await negotiateRoute(request, pathname, snapshot);
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
route: snapshot,
|
|
288
|
-
...negotiation,
|
|
289
|
-
};
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
// Non-negotiated response route (no variants, or RSC won negotiation)
|
|
293
|
-
if (responseType) {
|
|
294
|
-
const handler =
|
|
295
|
-
manifestEntry.type === "route" ? manifestEntry.handler : undefined;
|
|
296
|
-
if (handler) {
|
|
297
|
-
return {
|
|
298
|
-
mode: "response",
|
|
299
|
-
route: snapshot,
|
|
300
|
-
handler,
|
|
301
|
-
responseType,
|
|
302
|
-
negotiated: false,
|
|
303
|
-
manifestEntry,
|
|
304
|
-
routeMiddleware: snapshot.routeMiddleware,
|
|
305
|
-
};
|
|
306
|
-
}
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
return null;
|
|
273
|
+
return negotiation
|
|
274
|
+
? { mode: "response", route: snapshot, ...negotiation }
|
|
275
|
+
: null;
|
|
310
276
|
}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Evaluates whether segments should revalidate based on params, actions, and custom functions.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import type { ResolvedSegment, HandlerContext } from "../types";
|
|
7
|
+
import type { ResolvedSegment, HandlerContext, ActionRef } from "../types";
|
|
8
8
|
import type { ActionContext } from "./types";
|
|
9
9
|
import {
|
|
10
10
|
debugLog,
|
|
@@ -14,21 +14,52 @@ import {
|
|
|
14
14
|
import type { RevalidationTraceEntry } from "./logging.js";
|
|
15
15
|
import { _getRequestContext } from "../server/request-context.js";
|
|
16
16
|
import { isAutoGeneratedRouteName } from "../route-name.js";
|
|
17
|
+
import { paramsEqual } from "./params-util.js";
|
|
17
18
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
):
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
19
|
+
/**
|
|
20
|
+
* Resolve a server-action reference's stable id, mirroring how the action
|
|
21
|
+
* boundary derives `actionContext.actionId` in `rsc/server-action.ts`
|
|
22
|
+
* (`$id ?? $$id`): the file-path `$id` set by the expose-action-id plugin in a
|
|
23
|
+
* production RSC build when present, otherwise React's `$$id`. Resolving both
|
|
24
|
+
* the incoming `actionId` and the reference with the same precedence makes
|
|
25
|
+
* `isAction()` form-agnostic across dev and production.
|
|
26
|
+
*/
|
|
27
|
+
function resolveActionRefId(ref: unknown): string | undefined {
|
|
28
|
+
if (ref == null) return undefined;
|
|
29
|
+
const r = ref as { $id?: unknown; $$id?: unknown };
|
|
30
|
+
if (typeof r.$id === "string") return r.$id;
|
|
31
|
+
if (typeof r.$$id === "string") return r.$$id;
|
|
32
|
+
return undefined;
|
|
33
|
+
}
|
|
30
34
|
|
|
31
|
-
|
|
35
|
+
/**
|
|
36
|
+
* Build the `isAction()` helper bound to the current action's id. Called with no
|
|
37
|
+
* arguments it answers "is this request an action at all?" (any action) — `true`
|
|
38
|
+
* during action handling, `false` on plain navigation. Called with one or more
|
|
39
|
+
* action references it narrows to those: a single imported action, several
|
|
40
|
+
* (variadic), or any export of a namespace import (`import * as Mod`). Returns
|
|
41
|
+
* `false` when there is no action (plain navigation) or nothing matches.
|
|
42
|
+
*/
|
|
43
|
+
function makeIsAction(
|
|
44
|
+
currentActionId: string | undefined,
|
|
45
|
+
): (...actions: ActionRef[]) => boolean {
|
|
46
|
+
return (...actions: ActionRef[]): boolean => {
|
|
47
|
+
if (!currentActionId) return false;
|
|
48
|
+
// Bare isAction(): an action is in flight (currentActionId is set) and the
|
|
49
|
+
// caller did not narrow to a specific action, so this is "any action".
|
|
50
|
+
if (actions.length === 0) return true;
|
|
51
|
+
for (const action of actions) {
|
|
52
|
+
if (typeof action === "function") {
|
|
53
|
+
if (resolveActionRefId(action) === currentActionId) return true;
|
|
54
|
+
} else if (action && typeof action === "object") {
|
|
55
|
+
// Namespace import: match any export of the module.
|
|
56
|
+
for (const value of Object.values(action)) {
|
|
57
|
+
if (resolveActionRefId(value) === currentActionId) return true;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return false;
|
|
62
|
+
};
|
|
32
63
|
}
|
|
33
64
|
|
|
34
65
|
/**
|
|
@@ -95,8 +126,6 @@ export async function evaluateRevalidation<TEnv>(
|
|
|
95
126
|
const paramsChanged = !paramsEqual(nextParams, prevParams);
|
|
96
127
|
const searchChanged = prevUrl.search !== nextUrl.search;
|
|
97
128
|
|
|
98
|
-
// Trace helper: push a structured entry to the request-scoped trace buffer.
|
|
99
|
-
// Guarded by isTraceActive() so object construction is skipped in production.
|
|
100
129
|
function pushTrace(
|
|
101
130
|
defaultVal: boolean,
|
|
102
131
|
finalVal: boolean,
|
|
@@ -115,43 +144,28 @@ export async function evaluateRevalidation<TEnv>(
|
|
|
115
144
|
});
|
|
116
145
|
}
|
|
117
146
|
|
|
118
|
-
// Calculate default revalidation based on segment type and request method
|
|
119
147
|
let defaultShouldRevalidate: boolean;
|
|
120
148
|
let defaultReason: string;
|
|
121
149
|
|
|
122
150
|
if (defaultOverride) {
|
|
123
|
-
// Caller injected the seed (e.g. parallel slot not in clientSegmentIds).
|
|
124
|
-
// Skip the type-derived heuristic — caller knows better in this context.
|
|
125
151
|
defaultShouldRevalidate = defaultOverride.value;
|
|
126
152
|
defaultReason = defaultOverride.reason;
|
|
127
153
|
} else if (request.method === "POST") {
|
|
128
|
-
// Actions: revalidate segments that belong to the route, skip parent chain
|
|
129
154
|
if (segment.type === "route") {
|
|
130
|
-
// Route segment always revalidates on actions
|
|
131
155
|
defaultShouldRevalidate = true;
|
|
132
156
|
defaultReason = "action:route-segment";
|
|
133
157
|
} else if (segment.type === "loader") {
|
|
134
|
-
// Loaders always revalidate on actions - they often contain action-sensitive data
|
|
135
|
-
// (e.g., cart count after add-to-cart action)
|
|
136
158
|
defaultShouldRevalidate = true;
|
|
137
159
|
defaultReason = "action:loader-segment";
|
|
138
160
|
} else if (segment.belongsToRoute) {
|
|
139
|
-
// Segment belongs to route (orphan layouts/parallels) - revalidate
|
|
140
161
|
defaultShouldRevalidate = true;
|
|
141
162
|
defaultReason = "action:belongs-to-route";
|
|
142
163
|
} else {
|
|
143
|
-
// Parent chain segment (shared layouts/parallels) - don't revalidate
|
|
144
164
|
defaultShouldRevalidate = false;
|
|
145
165
|
defaultReason = "action:parent-chain-skip";
|
|
146
166
|
}
|
|
147
167
|
} else {
|
|
148
|
-
// Navigation (GET): Conservative defaults to minimize unnecessary revalidations
|
|
149
|
-
// Only the route segment revalidates by default - all others require explicit opt-in
|
|
150
|
-
|
|
151
168
|
if (segment.type === "route") {
|
|
152
|
-
// Route segments revalidate when path params OR search params change.
|
|
153
|
-
// Search params (e.g., ?page=2&sort=price) are server-parsed via ctx.search,
|
|
154
|
-
// so the handler must re-execute to produce updated content.
|
|
155
169
|
const routeChanged = paramsChanged || searchChanged;
|
|
156
170
|
defaultShouldRevalidate = routeChanged;
|
|
157
171
|
defaultReason = paramsChanged
|
|
@@ -167,8 +181,6 @@ export async function evaluateRevalidation<TEnv>(
|
|
|
167
181
|
});
|
|
168
182
|
}
|
|
169
183
|
} else if (segment.belongsToRoute && (paramsChanged || searchChanged)) {
|
|
170
|
-
// Children of the route path (loaders, orphan layouts/parallels)
|
|
171
|
-
// revalidate when path params or search params change
|
|
172
184
|
defaultShouldRevalidate = true;
|
|
173
185
|
defaultReason = paramsChanged
|
|
174
186
|
? "nav:route-child-params-changed"
|
|
@@ -180,9 +192,6 @@ export async function evaluateRevalidation<TEnv>(
|
|
|
180
192
|
searchChanged,
|
|
181
193
|
});
|
|
182
194
|
} else {
|
|
183
|
-
// Parent layouts and parallels default to no revalidation
|
|
184
|
-
// Cannot assume these segments depend on params without explicit declaration
|
|
185
|
-
// Use custom revalidation functions to opt-in when needed
|
|
186
195
|
defaultShouldRevalidate = false;
|
|
187
196
|
defaultReason = "nav:non-route-skip";
|
|
188
197
|
debugLog("revalidation", "non-route segment skipped by default", {
|
|
@@ -192,7 +201,6 @@ export async function evaluateRevalidation<TEnv>(
|
|
|
192
201
|
}
|
|
193
202
|
}
|
|
194
203
|
|
|
195
|
-
// No custom revalidations defined - return default behavior without prev segment
|
|
196
204
|
if (revalidations.length === 0) {
|
|
197
205
|
if (defaultShouldRevalidate) {
|
|
198
206
|
debugLog("revalidation", "default revalidate=true", {
|
|
@@ -209,14 +217,10 @@ export async function evaluateRevalidation<TEnv>(
|
|
|
209
217
|
return defaultShouldRevalidate;
|
|
210
218
|
}
|
|
211
219
|
|
|
212
|
-
// Custom revalidations exist - may need full prev segment
|
|
213
|
-
// Lazy load prev segment only if getPrevSegment provided
|
|
214
220
|
const prevSegment = getPrevSegment ? await getPrevSegment() : null;
|
|
215
221
|
|
|
216
|
-
// Execute revalidation functions with soft/hard decision pattern
|
|
217
222
|
let currentSuggestion = defaultShouldRevalidate;
|
|
218
223
|
|
|
219
|
-
// Compute public route names (filtered: undefined for auto-generated routes)
|
|
220
224
|
const toRouteName =
|
|
221
225
|
routeKey && !isAutoGeneratedRouteName(routeKey) ? routeKey : undefined;
|
|
222
226
|
const reqCtx = _getRequestContext();
|
|
@@ -240,23 +244,18 @@ export async function evaluateRevalidation<TEnv>(
|
|
|
240
244
|
slotName: segment.slot,
|
|
241
245
|
// Action context (only populated when triggered by server action)
|
|
242
246
|
actionId: actionContext?.actionId,
|
|
247
|
+
isAction: makeIsAction(actionContext?.actionId),
|
|
243
248
|
actionUrl: actionContext?.actionUrl,
|
|
244
249
|
actionResult: actionContext?.actionResult,
|
|
245
250
|
formData: actionContext?.formData,
|
|
246
|
-
method: request.method,
|
|
247
|
-
routeName: toRouteName,
|
|
248
|
-
fromRouteName,
|
|
249
|
-
toRouteName,
|
|
250
|
-
// Stale cache context (only true for background revalidation after stale cache render)
|
|
251
|
+
method: request.method,
|
|
252
|
+
routeName: toRouteName,
|
|
253
|
+
fromRouteName,
|
|
254
|
+
toRouteName,
|
|
251
255
|
stale,
|
|
252
256
|
});
|
|
253
257
|
|
|
254
|
-
// Check return type:
|
|
255
|
-
// - boolean: hard decision, short-circuit immediately
|
|
256
|
-
// - { defaultShouldRevalidate: boolean }: soft decision, update suggestion and continue
|
|
257
|
-
// - null/undefined: use default behavior (equivalent to returning { defaultShouldRevalidate })
|
|
258
258
|
if (typeof result === "boolean") {
|
|
259
|
-
// Hard decision - short-circuit
|
|
260
259
|
debugLog("revalidation", "hard decision", {
|
|
261
260
|
segmentId: segment.id,
|
|
262
261
|
revalidator: name,
|
|
@@ -269,7 +268,6 @@ export async function evaluateRevalidation<TEnv>(
|
|
|
269
268
|
typeof result === "object" &&
|
|
270
269
|
"defaultShouldRevalidate" in result
|
|
271
270
|
) {
|
|
272
|
-
// Soft decision - update suggestion and continue
|
|
273
271
|
currentSuggestion = result.defaultShouldRevalidate;
|
|
274
272
|
debugLog("revalidation", "soft decision", {
|
|
275
273
|
segmentId: segment.id,
|
|
@@ -277,18 +275,14 @@ export async function evaluateRevalidation<TEnv>(
|
|
|
277
275
|
revalidate: currentSuggestion,
|
|
278
276
|
});
|
|
279
277
|
} else if (result === null || result === undefined) {
|
|
280
|
-
// Defer to default - equivalent to { defaultShouldRevalidate: currentSuggestion }
|
|
281
|
-
// This means "I don't care, use whatever the default is"
|
|
282
278
|
debugLog("revalidation", "deferred to current default", {
|
|
283
279
|
segmentId: segment.id,
|
|
284
280
|
revalidator: name,
|
|
285
281
|
revalidate: currentSuggestion,
|
|
286
282
|
});
|
|
287
|
-
// currentSuggestion stays the same, continue to next function
|
|
288
283
|
}
|
|
289
284
|
}
|
|
290
285
|
|
|
291
|
-
// All revalidators completed - use final suggestion
|
|
292
286
|
debugLog("revalidation", "final decision", {
|
|
293
287
|
segmentId: segment.id,
|
|
294
288
|
revalidate: currentSuggestion,
|
|
@@ -230,7 +230,6 @@ export function createRouteSnapshot<TEnv = any>(
|
|
|
230
230
|
entry: {} as any,
|
|
231
231
|
routeKey: "test",
|
|
232
232
|
params: {},
|
|
233
|
-
optionalParams: new Set(),
|
|
234
233
|
} as RouteMatchResult<TEnv>,
|
|
235
234
|
manifestEntry: { type: "route", shortCode: "R0", parent: null } as any,
|
|
236
235
|
entries: [],
|
|
@@ -54,10 +54,8 @@ export interface InterceptResult {
|
|
|
54
54
|
* Instead of passing 20+ parameters, middleware calls getRouterContext() to access them.
|
|
55
55
|
*/
|
|
56
56
|
export interface RouterContext<TEnv = any> {
|
|
57
|
-
// Route matching
|
|
58
57
|
findMatch: (pathname: string) => RouteMatchResult | null;
|
|
59
58
|
|
|
60
|
-
// Manifest loading
|
|
61
59
|
loadManifest: (
|
|
62
60
|
entry: any,
|
|
63
61
|
routeKey: string,
|
|
@@ -66,10 +64,8 @@ export interface RouterContext<TEnv = any> {
|
|
|
66
64
|
isSSR?: boolean,
|
|
67
65
|
) => Promise<EntryData>;
|
|
68
66
|
|
|
69
|
-
// Entry traversal
|
|
70
67
|
traverseBack: (entry: EntryData) => Generator<EntryData>;
|
|
71
68
|
|
|
72
|
-
// Handler context creation
|
|
73
69
|
createHandlerContext: (
|
|
74
70
|
params: Record<string, string>,
|
|
75
71
|
request: Request,
|
|
@@ -83,7 +79,6 @@ export interface RouterContext<TEnv = any> {
|
|
|
83
79
|
isPassthroughRoute?: boolean,
|
|
84
80
|
) => HandlerContext<any, TEnv>;
|
|
85
81
|
|
|
86
|
-
// Loader setup
|
|
87
82
|
setupLoaderAccess: (
|
|
88
83
|
ctx: HandlerContext<any, TEnv>,
|
|
89
84
|
loaderPromises: Map<string, Promise<any>>,
|
|
@@ -94,7 +89,6 @@ export interface RouterContext<TEnv = any> {
|
|
|
94
89
|
loaderPromises: Map<string, Promise<any>>,
|
|
95
90
|
) => void;
|
|
96
91
|
|
|
97
|
-
// Context access
|
|
98
92
|
getContext: () => {
|
|
99
93
|
getOrCreateStore: (key: string) => any;
|
|
100
94
|
runWithStore: <T>(
|
|
@@ -105,16 +99,13 @@ export interface RouterContext<TEnv = any> {
|
|
|
105
99
|
) => T;
|
|
106
100
|
};
|
|
107
101
|
|
|
108
|
-
// Metrics
|
|
109
102
|
getMetricsStore: () => MetricsStore | undefined;
|
|
110
103
|
|
|
111
|
-
// Cache
|
|
112
104
|
createCacheScope: (
|
|
113
105
|
cacheConfig: any,
|
|
114
106
|
parent: CacheScope | null,
|
|
115
107
|
) => CacheScope | null;
|
|
116
108
|
|
|
117
|
-
// Intercept detection
|
|
118
109
|
findInterceptForRoute: (
|
|
119
110
|
routeKey: string,
|
|
120
111
|
parentEntry: EntryData | null,
|
|
@@ -122,7 +113,6 @@ export interface RouterContext<TEnv = any> {
|
|
|
122
113
|
isAction: boolean,
|
|
123
114
|
) => InterceptResult | null;
|
|
124
115
|
|
|
125
|
-
// Segment resolution (with revalidation)
|
|
126
116
|
resolveAllSegmentsWithRevalidation: (
|
|
127
117
|
entries: EntryData[],
|
|
128
118
|
routeKey: string,
|
|
@@ -133,7 +123,6 @@ export interface RouterContext<TEnv = any> {
|
|
|
133
123
|
request: Request,
|
|
134
124
|
prevUrl: URL,
|
|
135
125
|
nextUrl: URL,
|
|
136
|
-
loaderPromises: Map<string, Promise<any>>,
|
|
137
126
|
actionContext: any | undefined,
|
|
138
127
|
interceptResult: InterceptResult | null,
|
|
139
128
|
localRouteName: string,
|
|
@@ -166,12 +155,10 @@ export interface RouterContext<TEnv = any> {
|
|
|
166
155
|
revalidationContext?: RevalidationContext,
|
|
167
156
|
) => Promise<ResolvedSegment[]>;
|
|
168
157
|
|
|
169
|
-
// Collect with markers
|
|
170
158
|
collectWithMarkers?: <T>(
|
|
171
159
|
gen: AsyncGenerator<T | { __type: "id"; id: string }>,
|
|
172
160
|
) => Promise<{ items: T[]; matchedIds: string[] }>;
|
|
173
161
|
|
|
174
|
-
// Revalidation evaluation
|
|
175
162
|
evaluateRevalidation: (params: {
|
|
176
163
|
segment: ResolvedSegment;
|
|
177
164
|
prevParams: Record<string, string>;
|
|
@@ -195,7 +182,6 @@ export interface RouterContext<TEnv = any> {
|
|
|
195
182
|
| "intercept-loader";
|
|
196
183
|
}) => Promise<boolean>;
|
|
197
184
|
|
|
198
|
-
// Request context
|
|
199
185
|
getRequestContext: () =>
|
|
200
186
|
| {
|
|
201
187
|
waitUntil: (fn: () => Promise<void>) => void;
|
|
@@ -203,7 +189,6 @@ export interface RouterContext<TEnv = any> {
|
|
|
203
189
|
}
|
|
204
190
|
| undefined;
|
|
205
191
|
|
|
206
|
-
// Simple segment resolution (without revalidation - for full match)
|
|
207
192
|
resolveAllSegments: (
|
|
208
193
|
entries: EntryData[],
|
|
209
194
|
routeKey: string,
|
|
@@ -213,7 +198,6 @@ export interface RouterContext<TEnv = any> {
|
|
|
213
198
|
options?: { skipLoaders?: boolean },
|
|
214
199
|
) => Promise<ResolvedSegment[]>;
|
|
215
200
|
|
|
216
|
-
// Generator-based simple resolution
|
|
217
201
|
resolveAllSegmentsGenerator?: (
|
|
218
202
|
entries: EntryData[],
|
|
219
203
|
routeKey: string,
|
|
@@ -222,21 +206,17 @@ export interface RouterContext<TEnv = any> {
|
|
|
222
206
|
loaderPromises: Map<string, Promise<any>>,
|
|
223
207
|
) => AsyncGenerator<ResolvedSegment | { __type: "id"; id: string }>;
|
|
224
208
|
|
|
225
|
-
// Collect segments from generator
|
|
226
209
|
collectSegmentsFromGenerator?: <T>(
|
|
227
210
|
gen: AsyncGenerator<T | { __type: "id"; id: string }>,
|
|
228
211
|
) => Promise<T[]>;
|
|
229
212
|
|
|
230
|
-
// Handle store
|
|
231
213
|
createHandleStore: () => any;
|
|
232
214
|
|
|
233
|
-
// Loaders-only resolution (for full match cache hit - no revalidation)
|
|
234
215
|
resolveLoadersOnly?: (
|
|
235
216
|
entries: EntryData[],
|
|
236
217
|
handlerContext: HandlerContext<any, TEnv>,
|
|
237
218
|
) => Promise<ResolvedSegment[]>;
|
|
238
219
|
|
|
239
|
-
// Loaders-only resolution (for cache hit scenarios)
|
|
240
220
|
resolveLoadersOnlyWithRevalidation?: (
|
|
241
221
|
entries: EntryData[],
|
|
242
222
|
handlerContext: HandlerContext<any, TEnv>,
|
|
@@ -258,10 +238,8 @@ export interface RouterContext<TEnv = any> {
|
|
|
258
238
|
// Telemetry sink (optional, no-op when undefined)
|
|
259
239
|
telemetry?: TelemetrySink;
|
|
260
240
|
|
|
261
|
-
// Request ID for telemetry span correlation (set per-request in match handlers)
|
|
262
241
|
requestId?: string;
|
|
263
242
|
|
|
264
|
-
// Intercept loaders only (for cache hit + intercept scenarios)
|
|
265
243
|
resolveInterceptLoadersOnly?: (
|
|
266
244
|
intercept: InterceptEntry,
|
|
267
245
|
entry: EntryData,
|
|
@@ -284,7 +262,6 @@ export interface RouterContext<TEnv = any> {
|
|
|
284
262
|
} | null>;
|
|
285
263
|
}
|
|
286
264
|
|
|
287
|
-
// AsyncLocalStorage instance for router context
|
|
288
265
|
const routerContext = new AsyncLocalStorage<RouterContext<any>>();
|
|
289
266
|
|
|
290
267
|
/**
|
|
@@ -308,10 +285,6 @@ export function getRouterContext<TEnv = any>(): RouterContext<TEnv> {
|
|
|
308
285
|
*
|
|
309
286
|
* All async code within fn() can call getRouterContext() to access router closures.
|
|
310
287
|
* This works across async boundaries thanks to AsyncLocalStorage.
|
|
311
|
-
*
|
|
312
|
-
* @param deps Router dependencies to make available
|
|
313
|
-
* @param fn Function to run with dependencies available
|
|
314
|
-
* @returns Result of fn()
|
|
315
288
|
*/
|
|
316
289
|
export function runWithRouterContext<T, TEnv = any>(
|
|
317
290
|
deps: RouterContext<TEnv>,
|