@rangojs/router 0.0.0-experimental.13 → 0.0.0-experimental.13221847
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/AGENTS.md +9 -0
- package/README.md +884 -4
- package/dist/bin/rango.js +1531 -212
- package/dist/vite/index.js +3995 -2489
- package/package.json +57 -52
- package/skills/breadcrumbs/SKILL.md +250 -0
- package/skills/cache-guide/SKILL.md +262 -0
- package/skills/caching/SKILL.md +85 -23
- package/skills/composability/SKILL.md +172 -0
- package/skills/debug-manifest/SKILL.md +12 -8
- package/skills/document-cache/SKILL.md +18 -16
- package/skills/fonts/SKILL.md +6 -4
- package/skills/hooks/SKILL.md +328 -70
- package/skills/host-router/SKILL.md +218 -0
- package/skills/intercept/SKILL.md +131 -8
- package/skills/layout/SKILL.md +100 -3
- package/skills/links/SKILL.md +62 -15
- package/skills/loader/SKILL.md +368 -42
- package/skills/middleware/SKILL.md +171 -34
- package/skills/mime-routes/SKILL.md +14 -10
- package/skills/parallel/SKILL.md +137 -1
- package/skills/prerender/SKILL.md +366 -28
- package/skills/rango/SKILL.md +85 -21
- package/skills/response-routes/SKILL.md +136 -83
- package/skills/route/SKILL.md +195 -21
- package/skills/router-setup/SKILL.md +123 -30
- package/skills/theme/SKILL.md +9 -8
- package/skills/typesafety/SKILL.md +240 -102
- package/skills/use-cache/SKILL.md +324 -0
- package/src/__internal.ts +102 -4
- package/src/bin/rango.ts +312 -15
- package/src/browser/action-coordinator.ts +97 -0
- package/src/browser/action-response-classifier.ts +99 -0
- package/src/browser/event-controller.ts +92 -64
- package/src/browser/history-state.ts +80 -0
- package/src/browser/intercept-utils.ts +52 -0
- package/src/browser/link-interceptor.ts +24 -4
- package/src/browser/logging.ts +11 -0
- package/src/browser/merge-segment-loaders.ts +20 -12
- package/src/browser/navigation-bridge.ts +266 -558
- package/src/browser/navigation-client.ts +132 -75
- package/src/browser/navigation-store.ts +33 -50
- package/src/browser/navigation-transaction.ts +297 -0
- package/src/browser/network-error-handler.ts +61 -0
- package/src/browser/partial-update.ts +303 -309
- package/src/browser/prefetch/cache.ts +206 -0
- package/src/browser/prefetch/fetch.ts +144 -0
- package/src/browser/prefetch/observer.ts +65 -0
- package/src/browser/prefetch/policy.ts +48 -0
- package/src/browser/prefetch/queue.ts +128 -0
- package/src/browser/rango-state.ts +112 -0
- package/src/browser/react/Link.tsx +190 -70
- package/src/browser/react/NavigationProvider.tsx +78 -11
- package/src/browser/react/context.ts +6 -0
- package/src/browser/react/filter-segment-order.ts +11 -0
- package/src/browser/react/index.ts +12 -12
- package/src/browser/react/location-state-shared.ts +95 -53
- package/src/browser/react/location-state.ts +60 -15
- package/src/browser/react/mount-context.ts +6 -1
- package/src/browser/react/nonce-context.ts +23 -0
- package/src/browser/react/shallow-equal.ts +27 -0
- package/src/browser/react/use-action.ts +29 -51
- package/src/browser/react/use-client-cache.ts +5 -3
- package/src/browser/react/use-handle.ts +29 -70
- package/src/browser/react/use-link-status.ts +6 -5
- package/src/browser/react/use-navigation.ts +22 -63
- package/src/browser/react/use-params.ts +65 -0
- package/src/browser/react/use-pathname.ts +47 -0
- package/src/browser/react/use-router.ts +63 -0
- package/src/browser/react/use-search-params.ts +56 -0
- package/src/browser/react/use-segments.ts +80 -97
- package/src/browser/response-adapter.ts +73 -0
- package/src/browser/rsc-router.tsx +188 -57
- package/src/browser/scroll-restoration.ts +117 -44
- package/src/browser/segment-reconciler.ts +221 -0
- package/src/browser/segment-structure-assert.ts +16 -0
- package/src/browser/server-action-bridge.ts +488 -606
- package/src/browser/shallow.ts +6 -1
- package/src/browser/types.ts +116 -47
- package/src/browser/validate-redirect-origin.ts +29 -0
- package/src/build/generate-manifest.ts +63 -21
- package/src/build/generate-route-types.ts +36 -1038
- package/src/build/index.ts +2 -5
- package/src/build/route-trie.ts +38 -12
- package/src/build/route-types/ast-helpers.ts +25 -0
- package/src/build/route-types/ast-route-extraction.ts +98 -0
- package/src/build/route-types/codegen.ts +102 -0
- package/src/build/route-types/include-resolution.ts +411 -0
- package/src/build/route-types/param-extraction.ts +48 -0
- package/src/build/route-types/per-module-writer.ts +128 -0
- package/src/build/route-types/router-processing.ts +479 -0
- package/src/build/route-types/scan-filter.ts +78 -0
- package/src/build/runtime-discovery.ts +231 -0
- package/src/cache/background-task.ts +34 -0
- package/src/cache/cache-key-utils.ts +44 -0
- package/src/cache/cache-policy.ts +125 -0
- package/src/cache/cache-runtime.ts +342 -0
- package/src/cache/cache-scope.ts +122 -303
- package/src/cache/cf/cf-cache-store.ts +571 -17
- package/src/cache/cf/index.ts +13 -3
- package/src/cache/document-cache.ts +116 -77
- package/src/cache/handle-capture.ts +81 -0
- package/src/cache/handle-snapshot.ts +41 -0
- package/src/cache/index.ts +1 -15
- package/src/cache/memory-segment-store.ts +191 -13
- package/src/cache/profile-registry.ts +73 -0
- package/src/cache/read-through-swr.ts +134 -0
- package/src/cache/segment-codec.ts +256 -0
- package/src/cache/taint.ts +98 -0
- package/src/cache/types.ts +72 -122
- package/src/client.rsc.tsx +3 -1
- package/src/client.tsx +84 -126
- package/src/component-utils.ts +4 -4
- package/src/components/DefaultDocument.tsx +5 -1
- package/src/context-var.ts +86 -0
- package/src/debug.ts +19 -9
- package/src/errors.ts +77 -7
- package/src/handle.ts +12 -7
- package/src/handles/MetaTags.tsx +73 -20
- package/src/handles/breadcrumbs.ts +66 -0
- package/src/handles/index.ts +1 -0
- package/src/handles/meta.ts +30 -13
- package/src/host/cookie-handler.ts +21 -15
- package/src/host/errors.ts +8 -8
- package/src/host/index.ts +4 -7
- package/src/host/pattern-matcher.ts +27 -27
- package/src/host/router.ts +61 -39
- package/src/host/testing.ts +8 -8
- package/src/host/types.ts +15 -7
- package/src/host/utils.ts +1 -1
- package/src/href-client.ts +65 -45
- package/src/index.rsc.ts +104 -40
- package/src/index.ts +122 -67
- package/src/internal-debug.ts +9 -3
- package/src/loader.rsc.ts +18 -93
- package/src/loader.ts +26 -9
- package/src/network-error-thrower.tsx +3 -1
- package/src/outlet-provider.tsx +45 -0
- package/src/prerender/param-hash.ts +4 -2
- package/src/prerender/store.ts +121 -17
- package/src/prerender.ts +325 -20
- package/src/reverse.ts +144 -124
- package/src/root-error-boundary.tsx +41 -29
- package/src/route-content-wrapper.tsx +7 -4
- package/src/route-definition/dsl-helpers.ts +959 -0
- package/src/route-definition/helper-factories.ts +200 -0
- package/src/route-definition/helpers-types.ts +430 -0
- package/src/route-definition/index.ts +52 -0
- package/src/route-definition/redirect.ts +93 -0
- package/src/route-definition.ts +1 -1450
- package/src/route-map-builder.ts +87 -133
- package/src/route-name.ts +53 -0
- package/src/route-types.ts +41 -6
- package/src/router/content-negotiation.ts +116 -0
- package/src/router/debug-manifest.ts +72 -0
- package/src/router/error-handling.ts +9 -9
- package/src/router/find-match.ts +160 -0
- package/src/router/handler-context.ts +324 -116
- package/src/router/intercept-resolution.ts +11 -4
- package/src/router/lazy-includes.ts +237 -0
- package/src/router/loader-resolution.ts +179 -133
- package/src/router/logging.ts +112 -6
- package/src/router/manifest.ts +58 -19
- package/src/router/match-api.ts +89 -88
- package/src/router/match-context.ts +4 -2
- package/src/router/match-handlers.ts +440 -0
- package/src/router/match-middleware/background-revalidation.ts +86 -89
- package/src/router/match-middleware/cache-lookup.ts +295 -49
- package/src/router/match-middleware/cache-store.ts +56 -13
- package/src/router/match-middleware/intercept-resolution.ts +45 -22
- package/src/router/match-middleware/segment-resolution.ts +20 -9
- package/src/router/match-pipelines.ts +10 -45
- package/src/router/match-result.ts +44 -21
- package/src/router/metrics.ts +240 -15
- package/src/router/middleware-cookies.ts +55 -0
- package/src/router/middleware-types.ts +222 -0
- package/src/router/middleware.ts +327 -369
- package/src/router/pattern-matching.ts +169 -31
- package/src/router/prerender-match.ts +402 -0
- package/src/router/preview-match.ts +170 -0
- package/src/router/revalidation.ts +105 -14
- package/src/router/router-context.ts +40 -21
- package/src/router/router-interfaces.ts +452 -0
- package/src/router/router-options.ts +592 -0
- package/src/router/router-registry.ts +24 -0
- package/src/router/segment-resolution/fresh.ts +677 -0
- package/src/router/segment-resolution/helpers.ts +263 -0
- package/src/router/segment-resolution/loader-cache.ts +199 -0
- package/src/router/segment-resolution/revalidation.ts +1296 -0
- package/src/router/segment-resolution/static-store.ts +67 -0
- package/src/router/segment-resolution.ts +21 -1354
- package/src/router/segment-wrappers.ts +291 -0
- package/src/router/telemetry-otel.ts +299 -0
- package/src/router/telemetry.ts +300 -0
- package/src/router/timeout.ts +148 -0
- package/src/router/trie-matching.ts +96 -29
- package/src/router/types.ts +15 -9
- package/src/router.ts +642 -2366
- package/src/rsc/handler-context.ts +45 -0
- package/src/rsc/handler.ts +639 -1027
- package/src/rsc/helpers.ts +140 -6
- package/src/rsc/index.ts +0 -20
- package/src/rsc/loader-fetch.ts +209 -0
- package/src/rsc/manifest-init.ts +86 -0
- package/src/rsc/nonce.ts +14 -0
- package/src/rsc/origin-guard.ts +141 -0
- package/src/rsc/progressive-enhancement.ts +379 -0
- package/src/rsc/response-error.ts +37 -0
- package/src/rsc/response-route-handler.ts +347 -0
- package/src/rsc/rsc-rendering.ts +237 -0
- package/src/rsc/runtime-warnings.ts +42 -0
- package/src/rsc/server-action.ts +348 -0
- package/src/rsc/ssr-setup.ts +128 -0
- package/src/rsc/types.ts +38 -11
- package/src/search-params.ts +66 -54
- package/src/segment-system.tsx +165 -17
- package/src/server/context.ts +237 -54
- package/src/server/cookie-store.ts +190 -0
- package/src/server/fetchable-loader-store.ts +11 -6
- package/src/server/handle-store.ts +94 -15
- package/src/server/loader-registry.ts +15 -56
- package/src/server/request-context.ts +438 -71
- package/src/server.ts +26 -164
- package/src/ssr/index.tsx +101 -31
- package/src/static-handler.ts +22 -4
- package/src/theme/ThemeProvider.tsx +21 -15
- package/src/theme/ThemeScript.tsx +5 -5
- package/src/theme/constants.ts +5 -2
- package/src/theme/index.ts +4 -14
- package/src/theme/theme-context.ts +4 -30
- package/src/theme/theme-script.ts +21 -18
- package/src/types/boundaries.ts +158 -0
- package/src/types/cache-types.ts +198 -0
- package/src/types/error-types.ts +192 -0
- package/src/types/global-namespace.ts +100 -0
- package/src/types/handler-context.ts +773 -0
- package/src/types/index.ts +88 -0
- package/src/types/loader-types.ts +183 -0
- package/src/types/route-config.ts +170 -0
- package/src/types/route-entry.ts +109 -0
- package/src/types/segments.ts +150 -0
- package/src/types.ts +1 -1795
- package/src/urls/include-helper.ts +197 -0
- package/src/urls/index.ts +53 -0
- package/src/urls/path-helper-types.ts +339 -0
- package/src/urls/path-helper.ts +329 -0
- package/src/urls/pattern-types.ts +95 -0
- package/src/urls/response-types.ts +106 -0
- package/src/urls/type-extraction.ts +372 -0
- package/src/urls/urls-function.ts +98 -0
- package/src/urls.ts +1 -1323
- package/src/use-loader.tsx +85 -77
- package/src/vite/discovery/bundle-postprocess.ts +184 -0
- package/src/vite/discovery/discover-routers.ts +344 -0
- package/src/vite/discovery/prerender-collection.ts +385 -0
- package/src/vite/discovery/route-types-writer.ts +258 -0
- package/src/vite/discovery/self-gen-tracking.ts +47 -0
- package/src/vite/discovery/state.ts +108 -0
- package/src/vite/discovery/virtual-module-codegen.ts +203 -0
- package/src/vite/index.ts +11 -2259
- package/src/vite/plugin-types.ts +48 -0
- package/src/vite/plugins/cjs-to-esm.ts +93 -0
- package/src/vite/plugins/client-ref-dedup.ts +115 -0
- package/src/vite/plugins/client-ref-hashing.ts +105 -0
- package/src/vite/{expose-action-id.ts → plugins/expose-action-id.ts} +72 -47
- package/src/vite/{expose-id-utils.ts → plugins/expose-id-utils.ts} +8 -43
- package/src/vite/plugins/expose-ids/export-analysis.ts +296 -0
- package/src/vite/plugins/expose-ids/handler-transform.ts +179 -0
- package/src/vite/plugins/expose-ids/loader-transform.ts +74 -0
- package/src/vite/plugins/expose-ids/router-transform.ts +110 -0
- package/src/vite/plugins/expose-ids/types.ts +45 -0
- package/src/vite/plugins/expose-internal-ids.ts +569 -0
- package/src/vite/plugins/refresh-cmd.ts +65 -0
- package/src/vite/plugins/use-cache-transform.ts +323 -0
- package/src/vite/plugins/version-injector.ts +83 -0
- package/src/vite/plugins/version-plugin.ts +266 -0
- package/src/vite/{virtual-entries.ts → plugins/virtual-entries.ts} +23 -14
- package/src/vite/plugins/virtual-stub-plugin.ts +29 -0
- package/src/vite/rango.ts +445 -0
- package/src/vite/router-discovery.ts +777 -0
- package/src/vite/{ast-handler-extract.ts → utils/ast-handler-extract.ts} +181 -9
- package/src/vite/utils/banner.ts +36 -0
- package/src/vite/utils/bundle-analysis.ts +137 -0
- package/src/vite/utils/manifest-utils.ts +70 -0
- package/src/vite/{package-resolution.ts → utils/package-resolution.ts} +25 -29
- package/src/vite/utils/prerender-utils.ts +189 -0
- package/src/vite/utils/shared-utils.ts +169 -0
- package/CLAUDE.md +0 -43
- package/dist/vite/index.named-routes.gen.ts +0 -103
- package/src/browser/lru-cache.ts +0 -69
- package/src/browser/request-controller.ts +0 -164
- package/src/cache/memory-store.ts +0 -253
- package/src/href-context.ts +0 -33
- package/src/router.gen.ts +0 -6
- package/src/static-handler.gen.ts +0 -5
- package/src/urls.gen.ts +0 -8
- package/src/vite/expose-internal-ids.ts +0 -1167
- /package/src/vite/{version.d.ts → plugins/version.d.ts} +0 -0
|
@@ -6,7 +6,30 @@
|
|
|
6
6
|
|
|
7
7
|
import type { ResolvedSegment, HandlerContext } from "../types";
|
|
8
8
|
import type { ActionContext } from "./types";
|
|
9
|
-
import {
|
|
9
|
+
import {
|
|
10
|
+
debugLog,
|
|
11
|
+
pushRevalidationTraceEntry,
|
|
12
|
+
isTraceActive,
|
|
13
|
+
} from "./logging.js";
|
|
14
|
+
import type { RevalidationTraceEntry } from "./logging.js";
|
|
15
|
+
import { _getRequestContext } from "../server/request-context.js";
|
|
16
|
+
import { isAutoGeneratedRouteName } from "../route-name.js";
|
|
17
|
+
|
|
18
|
+
function paramsEqual(
|
|
19
|
+
a: Record<string, string>,
|
|
20
|
+
b: Record<string, string>,
|
|
21
|
+
): boolean {
|
|
22
|
+
if (a === b) return true;
|
|
23
|
+
|
|
24
|
+
const keysA = Object.keys(a);
|
|
25
|
+
if (keysA.length !== Object.keys(b).length) return false;
|
|
26
|
+
|
|
27
|
+
for (const key of keysA) {
|
|
28
|
+
if (a[key] !== b[key]) return false;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return true;
|
|
32
|
+
}
|
|
10
33
|
|
|
11
34
|
/**
|
|
12
35
|
* Options for revalidation evaluation
|
|
@@ -34,6 +57,8 @@ interface EvaluateRevalidationOptions<TEnv> {
|
|
|
34
57
|
actionContext?: ActionContext;
|
|
35
58
|
/** If true, this is a stale cache revalidation request */
|
|
36
59
|
stale?: boolean;
|
|
60
|
+
/** Trace source hint for the revalidation trace */
|
|
61
|
+
traceSource?: RevalidationTraceEntry["source"];
|
|
37
62
|
}
|
|
38
63
|
|
|
39
64
|
/**
|
|
@@ -41,7 +66,7 @@ interface EvaluateRevalidationOptions<TEnv> {
|
|
|
41
66
|
* Optimized to use prevParams directly and avoid building previous segments
|
|
42
67
|
*/
|
|
43
68
|
export async function evaluateRevalidation<TEnv>(
|
|
44
|
-
options: EvaluateRevalidationOptions<TEnv
|
|
69
|
+
options: EvaluateRevalidationOptions<TEnv>,
|
|
45
70
|
): Promise<boolean> {
|
|
46
71
|
const {
|
|
47
72
|
segment,
|
|
@@ -55,51 +80,97 @@ export async function evaluateRevalidation<TEnv>(
|
|
|
55
80
|
context,
|
|
56
81
|
actionContext,
|
|
57
82
|
stale,
|
|
83
|
+
traceSource,
|
|
58
84
|
} = options;
|
|
59
85
|
const nextParams = segment.params || {};
|
|
60
|
-
const paramsChanged =
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
86
|
+
const paramsChanged = !paramsEqual(nextParams, prevParams);
|
|
87
|
+
const searchChanged = prevUrl.search !== nextUrl.search;
|
|
88
|
+
|
|
89
|
+
// Trace helper: push a structured entry to the request-scoped trace buffer.
|
|
90
|
+
// Guarded by isTraceActive() so object construction is skipped in production.
|
|
91
|
+
function pushTrace(
|
|
92
|
+
defaultVal: boolean,
|
|
93
|
+
finalVal: boolean,
|
|
94
|
+
reason: string,
|
|
95
|
+
): void {
|
|
96
|
+
if (!isTraceActive()) return;
|
|
97
|
+
pushRevalidationTraceEntry({
|
|
98
|
+
segmentId: segment.id,
|
|
99
|
+
segmentType: segment.type,
|
|
100
|
+
belongsToRoute: segment.belongsToRoute ?? false,
|
|
101
|
+
source: traceSource ?? "segment-resolution",
|
|
102
|
+
defaultShouldRevalidate: defaultVal,
|
|
103
|
+
finalShouldRevalidate: finalVal,
|
|
104
|
+
reason,
|
|
105
|
+
customRevalidators: revalidations.length || undefined,
|
|
106
|
+
});
|
|
107
|
+
}
|
|
65
108
|
|
|
66
109
|
// Calculate default revalidation based on segment type and request method
|
|
67
110
|
let defaultShouldRevalidate: boolean;
|
|
111
|
+
let defaultReason: string;
|
|
68
112
|
|
|
69
113
|
if (request.method === "POST") {
|
|
70
114
|
// Actions: revalidate segments that belong to the route, skip parent chain
|
|
71
115
|
if (segment.type === "route") {
|
|
72
116
|
// Route segment always revalidates on actions
|
|
73
117
|
defaultShouldRevalidate = true;
|
|
118
|
+
defaultReason = "action:route-segment";
|
|
74
119
|
} else if (segment.type === "loader") {
|
|
75
120
|
// Loaders always revalidate on actions - they often contain action-sensitive data
|
|
76
121
|
// (e.g., cart count after add-to-cart action)
|
|
77
122
|
defaultShouldRevalidate = true;
|
|
123
|
+
defaultReason = "action:loader-segment";
|
|
78
124
|
} else if (segment.belongsToRoute) {
|
|
79
125
|
// Segment belongs to route (orphan layouts/parallels) - revalidate
|
|
80
126
|
defaultShouldRevalidate = true;
|
|
127
|
+
defaultReason = "action:belongs-to-route";
|
|
81
128
|
} else {
|
|
82
129
|
// Parent chain segment (shared layouts/parallels) - don't revalidate
|
|
83
130
|
defaultShouldRevalidate = false;
|
|
131
|
+
defaultReason = "action:parent-chain-skip";
|
|
84
132
|
}
|
|
85
133
|
} else {
|
|
86
134
|
// Navigation (GET): Conservative defaults to minimize unnecessary revalidations
|
|
87
135
|
// Only the route segment revalidates by default - all others require explicit opt-in
|
|
88
136
|
|
|
89
137
|
if (segment.type === "route") {
|
|
90
|
-
// Route segments revalidate when params change
|
|
91
|
-
//
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
138
|
+
// Route segments revalidate when path params OR search params change.
|
|
139
|
+
// Search params (e.g., ?page=2&sort=price) are server-parsed via ctx.search,
|
|
140
|
+
// so the handler must re-execute to produce updated content.
|
|
141
|
+
const routeChanged = paramsChanged || searchChanged;
|
|
142
|
+
defaultShouldRevalidate = routeChanged;
|
|
143
|
+
defaultReason = paramsChanged
|
|
144
|
+
? "nav:params-changed"
|
|
145
|
+
: searchChanged
|
|
146
|
+
? "nav:search-changed"
|
|
147
|
+
: "nav:params-unchanged";
|
|
148
|
+
if (routeChanged) {
|
|
149
|
+
debugLog("revalidation", "route revalidating", {
|
|
95
150
|
segmentId: segment.id,
|
|
151
|
+
paramsChanged,
|
|
152
|
+
searchChanged,
|
|
96
153
|
});
|
|
97
154
|
}
|
|
155
|
+
} else if (segment.belongsToRoute && (paramsChanged || searchChanged)) {
|
|
156
|
+
// Children of the route path (loaders, orphan layouts/parallels)
|
|
157
|
+
// revalidate when path params or search params change
|
|
158
|
+
defaultShouldRevalidate = true;
|
|
159
|
+
defaultReason = paramsChanged
|
|
160
|
+
? "nav:route-child-params-changed"
|
|
161
|
+
: "nav:route-child-search-changed";
|
|
162
|
+
debugLog("revalidation", "route child revalidating", {
|
|
163
|
+
segmentId: segment.id,
|
|
164
|
+
segmentType: segment.type,
|
|
165
|
+
paramsChanged,
|
|
166
|
+
searchChanged,
|
|
167
|
+
});
|
|
98
168
|
} else {
|
|
99
|
-
//
|
|
169
|
+
// Parent layouts and parallels default to no revalidation
|
|
100
170
|
// Cannot assume these segments depend on params without explicit declaration
|
|
101
171
|
// Use custom revalidation functions to opt-in when needed
|
|
102
172
|
defaultShouldRevalidate = false;
|
|
173
|
+
defaultReason = "nav:non-route-skip";
|
|
103
174
|
debugLog("revalidation", "non-route segment skipped by default", {
|
|
104
175
|
segmentId: segment.id,
|
|
105
176
|
segmentType: segment.type,
|
|
@@ -120,6 +191,7 @@ export async function evaluateRevalidation<TEnv>(
|
|
|
120
191
|
segmentId: segment.id,
|
|
121
192
|
});
|
|
122
193
|
}
|
|
194
|
+
pushTrace(defaultShouldRevalidate, defaultShouldRevalidate, defaultReason);
|
|
123
195
|
return defaultShouldRevalidate;
|
|
124
196
|
}
|
|
125
197
|
|
|
@@ -130,6 +202,16 @@ export async function evaluateRevalidation<TEnv>(
|
|
|
130
202
|
// Execute revalidation functions with soft/hard decision pattern
|
|
131
203
|
let currentSuggestion = defaultShouldRevalidate;
|
|
132
204
|
|
|
205
|
+
// Compute public route names (filtered: undefined for auto-generated routes)
|
|
206
|
+
const toRouteName =
|
|
207
|
+
routeKey && !isAutoGeneratedRouteName(routeKey) ? routeKey : undefined;
|
|
208
|
+
const reqCtx = _getRequestContext();
|
|
209
|
+
const prevRouteKey = reqCtx?._prevRouteKey;
|
|
210
|
+
const fromRouteName =
|
|
211
|
+
prevRouteKey && !isAutoGeneratedRouteName(prevRouteKey)
|
|
212
|
+
? prevRouteKey
|
|
213
|
+
: undefined;
|
|
214
|
+
|
|
133
215
|
for (const { name, fn } of revalidations) {
|
|
134
216
|
const result = fn({
|
|
135
217
|
currentParams: prevSegment?.params || prevParams, // Use segment params if available, else route params
|
|
@@ -148,7 +230,9 @@ export async function evaluateRevalidation<TEnv>(
|
|
|
148
230
|
actionResult: actionContext?.actionResult,
|
|
149
231
|
formData: actionContext?.formData,
|
|
150
232
|
method: request.method, // GET for navigation, POST for actions
|
|
151
|
-
routeName:
|
|
233
|
+
routeName: toRouteName, // Navigation target route name (filtered)
|
|
234
|
+
fromRouteName, // Navigation source route name (filtered)
|
|
235
|
+
toRouteName, // Navigation target route name (filtered)
|
|
152
236
|
// Stale cache context (only true for background revalidation after stale cache render)
|
|
153
237
|
stale,
|
|
154
238
|
});
|
|
@@ -164,6 +248,7 @@ export async function evaluateRevalidation<TEnv>(
|
|
|
164
248
|
revalidator: name,
|
|
165
249
|
revalidate: result,
|
|
166
250
|
});
|
|
251
|
+
pushTrace(defaultShouldRevalidate, result, `hard:${name}`);
|
|
167
252
|
return result;
|
|
168
253
|
} else if (
|
|
169
254
|
result &&
|
|
@@ -194,5 +279,11 @@ export async function evaluateRevalidation<TEnv>(
|
|
|
194
279
|
segmentId: segment.id,
|
|
195
280
|
revalidate: currentSuggestion,
|
|
196
281
|
});
|
|
282
|
+
const softNames = revalidations.map((r) => r.name).join(",");
|
|
283
|
+
pushTrace(
|
|
284
|
+
defaultShouldRevalidate,
|
|
285
|
+
currentSuggestion,
|
|
286
|
+
`soft-chain:${softNames}`,
|
|
287
|
+
);
|
|
197
288
|
return currentSuggestion;
|
|
198
289
|
}
|
|
@@ -18,6 +18,7 @@ import type {
|
|
|
18
18
|
ShouldRevalidateFn,
|
|
19
19
|
} from "../types.js";
|
|
20
20
|
import type { RouteMatchResult } from "./pattern-matching.js";
|
|
21
|
+
import type { TelemetrySink } from "./telemetry.js";
|
|
21
22
|
|
|
22
23
|
/**
|
|
23
24
|
* Revalidation context passed to segment resolution
|
|
@@ -62,7 +63,7 @@ export interface RouterContext<TEnv = any> {
|
|
|
62
63
|
routeKey: string,
|
|
63
64
|
pathname: string,
|
|
64
65
|
metricsStore?: MetricsStore,
|
|
65
|
-
isSSR?: boolean
|
|
66
|
+
isSSR?: boolean,
|
|
66
67
|
) => Promise<EntryData>;
|
|
67
68
|
|
|
68
69
|
// Entry traversal
|
|
@@ -77,18 +78,20 @@ export interface RouterContext<TEnv = any> {
|
|
|
77
78
|
url: URL,
|
|
78
79
|
bindings?: any,
|
|
79
80
|
routeMap?: Record<string, string>,
|
|
80
|
-
routeName?: string
|
|
81
|
+
routeName?: string,
|
|
82
|
+
responseType?: string,
|
|
83
|
+
isPassthroughRoute?: boolean,
|
|
81
84
|
) => HandlerContext<any, TEnv>;
|
|
82
85
|
|
|
83
86
|
// Loader setup
|
|
84
87
|
setupLoaderAccess: (
|
|
85
88
|
ctx: HandlerContext<any, TEnv>,
|
|
86
|
-
loaderPromises: Map<string, Promise<any
|
|
89
|
+
loaderPromises: Map<string, Promise<any>>,
|
|
87
90
|
) => void;
|
|
88
91
|
|
|
89
92
|
setupLoaderAccessSilent: (
|
|
90
93
|
ctx: HandlerContext<any, TEnv>,
|
|
91
|
-
loaderPromises: Map<string, Promise<any
|
|
94
|
+
loaderPromises: Map<string, Promise<any>>,
|
|
92
95
|
) => void;
|
|
93
96
|
|
|
94
97
|
// Context access
|
|
@@ -98,7 +101,7 @@ export interface RouterContext<TEnv = any> {
|
|
|
98
101
|
store: any,
|
|
99
102
|
namespace: string,
|
|
100
103
|
parent: any,
|
|
101
|
-
fn: () => T
|
|
104
|
+
fn: () => T,
|
|
102
105
|
) => T;
|
|
103
106
|
};
|
|
104
107
|
|
|
@@ -108,7 +111,7 @@ export interface RouterContext<TEnv = any> {
|
|
|
108
111
|
// Cache
|
|
109
112
|
createCacheScope: (
|
|
110
113
|
cacheConfig: any,
|
|
111
|
-
parent: CacheScope | null
|
|
114
|
+
parent: CacheScope | null,
|
|
112
115
|
) => CacheScope | null;
|
|
113
116
|
|
|
114
117
|
// Intercept detection
|
|
@@ -116,7 +119,7 @@ export interface RouterContext<TEnv = any> {
|
|
|
116
119
|
routeKey: string,
|
|
117
120
|
parentEntry: EntryData | null,
|
|
118
121
|
selectorContext: InterceptSelectorContext,
|
|
119
|
-
isAction: boolean
|
|
122
|
+
isAction: boolean,
|
|
120
123
|
) => InterceptResult | null;
|
|
121
124
|
|
|
122
125
|
// Segment resolution (with revalidation)
|
|
@@ -134,7 +137,8 @@ export interface RouterContext<TEnv = any> {
|
|
|
134
137
|
actionContext: any | undefined,
|
|
135
138
|
interceptResult: InterceptResult | null,
|
|
136
139
|
localRouteName: string,
|
|
137
|
-
pathname: string
|
|
140
|
+
pathname: string,
|
|
141
|
+
stale?: boolean,
|
|
138
142
|
) => Promise<{ segments: ResolvedSegment[]; matchedIds: string[] }>;
|
|
139
143
|
|
|
140
144
|
// Generator-based segment resolution (for pipeline)
|
|
@@ -149,7 +153,7 @@ export interface RouterContext<TEnv = any> {
|
|
|
149
153
|
prevUrl: URL,
|
|
150
154
|
nextUrl: URL,
|
|
151
155
|
loaderPromises: Map<string, Promise<any>>,
|
|
152
|
-
actionContext?: any
|
|
156
|
+
actionContext?: any,
|
|
153
157
|
) => AsyncGenerator<ResolvedSegment | { __type: "id"; id: string }>;
|
|
154
158
|
|
|
155
159
|
// Intercept resolution
|
|
@@ -159,12 +163,12 @@ export interface RouterContext<TEnv = any> {
|
|
|
159
163
|
params: Record<string, string>,
|
|
160
164
|
handlerContext: HandlerContext<any, TEnv>,
|
|
161
165
|
belongsToRoute: boolean,
|
|
162
|
-
revalidationContext?: RevalidationContext
|
|
166
|
+
revalidationContext?: RevalidationContext,
|
|
163
167
|
) => Promise<ResolvedSegment[]>;
|
|
164
168
|
|
|
165
169
|
// Collect with markers
|
|
166
170
|
collectWithMarkers?: <T>(
|
|
167
|
-
gen: AsyncGenerator<T | { __type: "id"; id: string }
|
|
171
|
+
gen: AsyncGenerator<T | { __type: "id"; id: string }>,
|
|
168
172
|
) => Promise<{ items: T[]; matchedIds: string[] }>;
|
|
169
173
|
|
|
170
174
|
// Revalidation evaluation
|
|
@@ -180,6 +184,15 @@ export interface RouterContext<TEnv = any> {
|
|
|
180
184
|
context: HandlerContext<any, TEnv>;
|
|
181
185
|
actionContext?: any;
|
|
182
186
|
stale?: boolean;
|
|
187
|
+
traceSource?:
|
|
188
|
+
| "segment-resolution"
|
|
189
|
+
| "cache-hit"
|
|
190
|
+
| "loader"
|
|
191
|
+
| "parallel"
|
|
192
|
+
| "orphan-layout"
|
|
193
|
+
| "route-handler"
|
|
194
|
+
| "layout-handler"
|
|
195
|
+
| "intercept-loader";
|
|
183
196
|
}) => Promise<boolean>;
|
|
184
197
|
|
|
185
198
|
// Request context
|
|
@@ -196,7 +209,7 @@ export interface RouterContext<TEnv = any> {
|
|
|
196
209
|
routeKey: string,
|
|
197
210
|
params: Record<string, string>,
|
|
198
211
|
handlerContext: HandlerContext<any, TEnv>,
|
|
199
|
-
loaderPromises: Map<string, Promise<any
|
|
212
|
+
loaderPromises: Map<string, Promise<any>>,
|
|
200
213
|
) => Promise<ResolvedSegment[]>;
|
|
201
214
|
|
|
202
215
|
// Generator-based simple resolution
|
|
@@ -205,12 +218,12 @@ export interface RouterContext<TEnv = any> {
|
|
|
205
218
|
routeKey: string,
|
|
206
219
|
params: Record<string, string>,
|
|
207
220
|
handlerContext: HandlerContext<any, TEnv>,
|
|
208
|
-
loaderPromises: Map<string, Promise<any
|
|
221
|
+
loaderPromises: Map<string, Promise<any>>,
|
|
209
222
|
) => AsyncGenerator<ResolvedSegment | { __type: "id"; id: string }>;
|
|
210
223
|
|
|
211
224
|
// Collect segments from generator
|
|
212
225
|
collectSegmentsFromGenerator?: <T>(
|
|
213
|
-
gen: AsyncGenerator<T | { __type: "id"; id: string }
|
|
226
|
+
gen: AsyncGenerator<T | { __type: "id"; id: string }>,
|
|
214
227
|
) => Promise<T[]>;
|
|
215
228
|
|
|
216
229
|
// Handle store
|
|
@@ -219,7 +232,7 @@ export interface RouterContext<TEnv = any> {
|
|
|
219
232
|
// Loaders-only resolution (for full match cache hit - no revalidation)
|
|
220
233
|
resolveLoadersOnly?: (
|
|
221
234
|
entries: EntryData[],
|
|
222
|
-
handlerContext: HandlerContext<any, TEnv
|
|
235
|
+
handlerContext: HandlerContext<any, TEnv>,
|
|
223
236
|
) => Promise<ResolvedSegment[]>;
|
|
224
237
|
|
|
225
238
|
// Loaders-only resolution (for cache hit scenarios)
|
|
@@ -232,14 +245,21 @@ export interface RouterContext<TEnv = any> {
|
|
|
232
245
|
prevUrl: URL,
|
|
233
246
|
nextUrl: URL,
|
|
234
247
|
routeKey: string,
|
|
235
|
-
actionContext?: any
|
|
248
|
+
actionContext?: any,
|
|
249
|
+
stale?: boolean,
|
|
236
250
|
) => Promise<{ segments: ResolvedSegment[]; matchedIds: string[] }>;
|
|
237
251
|
|
|
238
252
|
// Entry revalidation map
|
|
239
253
|
buildEntryRevalidateMap?: (
|
|
240
|
-
entries: EntryData[]
|
|
254
|
+
entries: EntryData[],
|
|
241
255
|
) => Map<string, { revalidate: ShouldRevalidateFn[] }>;
|
|
242
256
|
|
|
257
|
+
// Telemetry sink (optional, no-op when undefined)
|
|
258
|
+
telemetry?: TelemetrySink;
|
|
259
|
+
|
|
260
|
+
// Request ID for telemetry span correlation (set per-request in match handlers)
|
|
261
|
+
requestId?: string;
|
|
262
|
+
|
|
243
263
|
// Intercept loaders only (for cache hit + intercept scenarios)
|
|
244
264
|
resolveInterceptLoadersOnly?: (
|
|
245
265
|
intercept: InterceptEntry,
|
|
@@ -256,7 +276,7 @@ export interface RouterContext<TEnv = any> {
|
|
|
256
276
|
routeKey: string;
|
|
257
277
|
actionContext?: any;
|
|
258
278
|
stale?: boolean;
|
|
259
|
-
}
|
|
279
|
+
},
|
|
260
280
|
) => Promise<{
|
|
261
281
|
loaderDataPromise: Promise<any[]> | any[];
|
|
262
282
|
loaderIds: string[];
|
|
@@ -276,7 +296,7 @@ export function getRouterContext<TEnv = any>(): RouterContext<TEnv> {
|
|
|
276
296
|
if (!deps) {
|
|
277
297
|
throw new Error(
|
|
278
298
|
"getRouterContext() called outside of router context. " +
|
|
279
|
-
"Ensure code is running inside runWithRouterContext()."
|
|
299
|
+
"Ensure code is running inside runWithRouterContext().",
|
|
280
300
|
);
|
|
281
301
|
}
|
|
282
302
|
return deps as RouterContext<TEnv>;
|
|
@@ -294,8 +314,7 @@ export function getRouterContext<TEnv = any>(): RouterContext<TEnv> {
|
|
|
294
314
|
*/
|
|
295
315
|
export function runWithRouterContext<T, TEnv = any>(
|
|
296
316
|
deps: RouterContext<TEnv>,
|
|
297
|
-
fn: () => T
|
|
317
|
+
fn: () => T,
|
|
298
318
|
): T {
|
|
299
319
|
return routerContext.run(deps, fn);
|
|
300
320
|
}
|
|
301
|
-
|