@rangojs/router 0.24.4 → 0.25.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.
- package/README.md +1 -0
- package/dist/bin/rango.js +363 -39
- package/dist/testing/vitest.js +37 -4
- package/dist/types/browser/event-controller.d.ts +24 -5
- package/dist/types/browser/intercept-utils.d.ts +5 -2
- package/dist/types/browser/merge-segment-loaders.d.ts +0 -23
- package/dist/types/browser/navigation-transaction.d.ts +5 -5
- package/dist/types/browser/partial-update.d.ts +21 -13
- package/dist/types/browser/prefetch/cache.d.ts +8 -0
- package/dist/types/browser/rango-marker.d.ts +7 -0
- package/dist/types/browser/react/filter-segment-order.d.ts +10 -0
- package/dist/types/browser/react/use-handle.d.ts +20 -0
- package/dist/types/browser/react/use-href.d.ts +6 -0
- package/dist/types/browser/react/use-router.d.ts +6 -1
- package/dist/types/browser/response-adapter.d.ts +5 -3
- package/dist/types/browser/scroll-restoration.d.ts +9 -3
- package/dist/types/browser/segment-reconciler.d.ts +10 -13
- package/dist/types/browser/types.d.ts +38 -8
- package/dist/types/build/route-types/per-module-writer.d.ts +12 -0
- package/dist/types/cache/cf/cf-shell-frame.d.ts +2 -0
- package/dist/types/cache/types.d.ts +8 -0
- package/dist/types/client-urls/client-urls.d.ts +6 -2
- package/dist/types/client-urls/revalidate-registry.d.ts +1 -1
- package/dist/types/client-urls/server-projection.d.ts +9 -5
- package/dist/types/client-urls/types.d.ts +29 -16
- package/dist/types/client.d.ts +2 -2
- package/dist/types/client.rsc.d.ts +2 -2
- package/dist/types/decode-loader-results.d.ts +28 -7
- package/dist/types/href-client.d.ts +3 -1
- package/dist/types/index.rsc.d.ts +1 -1
- package/dist/types/loader-redirect.d.ts +2 -3
- package/dist/types/outlet-context.d.ts +7 -6
- package/dist/types/prefetch-markers.d.ts +14 -5
- package/dist/types/route-content-wrapper.d.ts +17 -14
- package/dist/types/route-definition/helpers-types.d.ts +7 -2
- package/dist/types/route-definition/resolve-handler-use.d.ts +6 -1
- package/dist/types/route-definition/rewrite.d.ts +48 -5
- package/dist/types/route-types.d.ts +2 -2
- package/dist/types/router/handler-context.d.ts +14 -2
- package/dist/types/router/intercept-resolution.d.ts +19 -46
- package/dist/types/router/lazy-includes.d.ts +7 -0
- package/dist/types/router/match-middleware/intercept-resolution.d.ts +2 -2
- package/dist/types/router/middleware.d.ts +0 -16
- package/dist/types/router/navigation-snapshot.d.ts +2 -0
- package/dist/types/router/prefetch-cache-ttl.d.ts +8 -11
- package/dist/types/router/revalidation.d.ts +8 -1
- package/dist/types/router/router-context.d.ts +4 -16
- package/dist/types/router/router-interfaces.d.ts +0 -6
- package/dist/types/router/router-options.d.ts +4 -7
- package/dist/types/router/segment-resolution/prefetch-deferral.d.ts +31 -8
- package/dist/types/router/segment-resolution/revalidation.d.ts +38 -4
- package/dist/types/router/segment-resolution.d.ts +1 -1
- package/dist/types/router/segment-wrappers.d.ts +3 -5
- package/dist/types/router/substitute-pattern-params.d.ts +3 -2
- package/dist/types/router/tracing.d.ts +2 -2
- package/dist/types/rsc/full-payload.d.ts +14 -2
- package/dist/types/rsc/helpers.d.ts +8 -0
- package/dist/types/rsc/manifest-init.d.ts +20 -0
- package/dist/types/rsc/prefetch-render-error.d.ts +22 -0
- package/dist/types/rsc/progressive-enhancement.d.ts +20 -0
- package/dist/types/rsc/rewrite-passes.d.ts +12 -2
- package/dist/types/rsc/server-action.d.ts +6 -0
- package/dist/types/rsc/shell-capture-constants.d.ts +10 -1
- package/dist/types/rsc/shell-capture.d.ts +7 -0
- package/dist/types/rsc/types.d.ts +5 -0
- package/dist/types/segment-system.d.ts +15 -0
- package/dist/types/server/context.d.ts +64 -4
- package/dist/types/server/request-context.d.ts +41 -4
- package/dist/types/server/request-headers.d.ts +12 -0
- package/dist/types/server/rewrite-trail.d.ts +8 -1
- package/dist/types/testing/e2e/index.d.ts +1 -1
- package/dist/types/testing/flight.entry.d.ts +1 -1
- package/dist/types/testing/index.d.ts +1 -1
- package/dist/types/testing/internal/client-urls-projection.d.ts +4 -3
- package/dist/types/testing/render-route.d.ts +21 -11
- package/dist/types/testing/run-loader.d.ts +7 -0
- package/dist/types/testing/run-middleware.d.ts +7 -0
- package/dist/types/testing/run-revalidate.d.ts +5 -4
- package/dist/types/testing/serve-shell-request.d.ts +41 -4
- package/dist/types/testing/shell-status.d.ts +17 -0
- package/dist/types/testing/vitest-stubs/version.d.ts +1 -0
- package/dist/types/testing/vitest.d.ts +10 -1
- package/dist/types/thenable-status.d.ts +0 -6
- package/dist/types/types/handler-context.d.ts +12 -1
- package/dist/types/types/loader-types.d.ts +4 -3
- package/dist/types/types/route-entry.d.ts +2 -1
- package/dist/types/urls/path-helper-types.d.ts +4 -2
- package/dist/types/vite/discovery/client-urls-projection.d.ts +55 -5
- package/dist/types/vite/discovery/state.d.ts +20 -0
- package/dist/types/vite/plugins/client-urls-revalidate-hoist.d.ts +28 -16
- package/dist/types/vite/plugins/hoist/source.d.ts +8 -7
- package/dist/types/vite/plugins/virtual-entries.d.ts +6 -0
- package/dist/types/vite/utils/prerender-utils.d.ts +7 -0
- package/dist/vite/index.js +6816 -6547
- package/package.json +1 -1
- package/skills/app-structure/SKILL.md +255 -0
- package/skills/app-structure/content-site.md +333 -0
- package/skills/app-structure/e-commerce.md +435 -0
- package/skills/app-structure/large-app.md +885 -0
- package/skills/app-structure/multi-app.md +280 -0
- package/skills/breadcrumbs/SKILL.md +6 -1
- package/skills/caching/SKILL.md +3 -1
- package/skills/catalog.json +12 -0
- package/skills/client-urls/SKILL.md +185 -32
- package/skills/composability/SKILL.md +10 -8
- package/skills/handler-use/SKILL.md +48 -9
- package/skills/hooks/handle-and-actions.md +104 -0
- package/skills/hooks/navigation.md +24 -10
- package/skills/hooks/urls.md +1 -1
- package/skills/i18n/SKILL.md +2 -1
- package/skills/intercept/SKILL.md +60 -29
- package/skills/layout/SKILL.md +6 -3
- package/skills/links/SKILL.md +151 -17
- package/skills/loader/SKILL.md +32 -10
- package/skills/middleware/SKILL.md +111 -15
- package/skills/observability/SKILL.md +11 -0
- package/skills/parallel/SKILL.md +5 -5
- package/skills/ppr/SKILL.md +43 -8
- package/skills/prerender/SKILL.md +1 -2
- package/skills/rango/SKILL.md +3 -0
- package/skills/response-routes/SKILL.md +4 -1
- package/skills/scripts/SKILL.md +12 -1
- package/skills/server-actions/SKILL.md +60 -20
- package/skills/testing/SKILL.md +1 -0
- package/skills/testing/client-components.md +13 -10
- package/skills/testing/loader.md +25 -24
- package/skills/testing/middleware.md +11 -11
- package/skills/testing/response-routes.md +4 -1
- package/skills/testing/serve-shell-request.md +85 -21
- package/skills/ux-architecture/SKILL.md +980 -0
- package/skills/view-transitions/SKILL.md +43 -10
- package/src/__augment-tests__/augmented.check.ts +28 -0
- package/src/browser/event-controller.ts +44 -18
- package/src/browser/intercept-utils.ts +3 -2
- package/src/browser/merge-segment-loaders.ts +0 -85
- package/src/browser/navigation-bridge.ts +112 -84
- package/src/browser/navigation-client.ts +20 -15
- package/src/browser/navigation-store.ts +4 -2
- package/src/browser/navigation-transaction.ts +9 -8
- package/src/browser/partial-update.ts +90 -32
- package/src/browser/prefetch/cache.ts +8 -0
- package/src/browser/prefetch/fetch.ts +13 -3
- package/src/browser/rango-marker.ts +13 -0
- package/src/browser/react/NavigationProvider.tsx +25 -7
- package/src/browser/react/filter-segment-order.ts +13 -0
- package/src/browser/react/use-action.ts +9 -15
- package/src/browser/react/use-handle.ts +63 -71
- package/src/browser/react/use-href.tsx +24 -5
- package/src/browser/react/use-link-status.ts +1 -1
- package/src/browser/react/use-navigation.ts +30 -40
- package/src/browser/react/use-router.ts +37 -6
- package/src/browser/react/use-segments.ts +8 -12
- package/src/browser/response-adapter.ts +11 -5
- package/src/browser/rsc-router.tsx +3 -1
- package/src/browser/scroll-restoration.ts +34 -20
- package/src/browser/segment-reconciler.ts +11 -29
- package/src/browser/server-action-bridge.ts +52 -16
- package/src/browser/types.ts +40 -8
- package/src/build/generate-manifest.ts +12 -1
- package/src/build/route-types/codegen.ts +6 -2
- package/src/build/route-types/per-module-writer.ts +94 -61
- package/src/cache/cache-runtime.ts +9 -0
- package/src/cache/cache-scope.ts +2 -1
- package/src/cache/cf/cf-cache-store.ts +2 -0
- package/src/cache/cf/cf-shell-frame.ts +3 -0
- package/src/cache/types.ts +8 -0
- package/src/cache/vercel/vercel-cache-store.ts +6 -1
- package/src/client-urls/client-urls.ts +202 -153
- package/src/client-urls/revalidate-registry.ts +12 -3
- package/src/client-urls/server-projection.ts +137 -66
- package/src/client-urls/types.ts +30 -15
- package/src/client.rsc.tsx +11 -1
- package/src/client.tsx +9 -1
- package/src/decode-loader-results.ts +64 -31
- package/src/href-client.ts +3 -1
- package/src/index.rsc.ts +1 -0
- package/src/index.ts +12 -4
- package/src/loader-redirect.tsx +2 -3
- package/src/outlet-context.ts +7 -6
- package/src/prefetch-markers.ts +15 -5
- package/src/reverse.ts +3 -3
- package/src/route-content-wrapper.tsx +19 -17
- package/src/route-definition/dsl-helpers.ts +27 -7
- package/src/route-definition/helpers-types.ts +7 -2
- package/src/route-definition/resolve-handler-use.ts +23 -10
- package/src/route-definition/rewrite.ts +86 -19
- package/src/route-types.ts +1 -2
- package/src/router/find-match.ts +37 -1
- package/src/router/handler-context.ts +85 -40
- package/src/router/intercept-resolution.ts +161 -307
- package/src/router/lazy-includes.ts +43 -27
- package/src/router/loader-resolution.ts +21 -1
- package/src/router/manifest.ts +6 -8
- package/src/router/match-api.ts +11 -1
- package/src/router/match-middleware/background-revalidation.ts +2 -4
- package/src/router/match-middleware/cache-lookup.ts +16 -20
- package/src/router/match-middleware/intercept-resolution.ts +41 -60
- package/src/router/match-result.ts +31 -2
- package/src/router/middleware.ts +6 -147
- package/src/router/navigation-snapshot.ts +38 -2
- package/src/router/prefetch-cache-ttl.ts +10 -18
- package/src/router/prerender-match.ts +2 -1
- package/src/router/revalidation.ts +24 -3
- package/src/router/router-context.ts +5 -18
- package/src/router/router-interfaces.ts +0 -7
- package/src/router/router-options.ts +4 -7
- package/src/router/segment-resolution/fresh.ts +6 -2
- package/src/router/segment-resolution/helpers.ts +7 -1
- package/src/router/segment-resolution/prefetch-deferral.ts +62 -12
- package/src/router/segment-resolution/revalidation.ts +75 -35
- package/src/router/segment-resolution.ts +0 -1
- package/src/router/segment-wrappers.ts +8 -13
- package/src/router/substitute-pattern-params.ts +3 -2
- package/src/router/tracing.ts +2 -2
- package/src/router.ts +2 -9
- package/src/rsc/full-payload.ts +26 -4
- package/src/rsc/handler.ts +83 -41
- package/src/rsc/helpers.ts +13 -0
- package/src/rsc/manifest-init.ts +56 -3
- package/src/rsc/prefetch-render-error.ts +38 -0
- package/src/rsc/progressive-enhancement.ts +161 -211
- package/src/rsc/rewrite-passes.ts +56 -9
- package/src/rsc/rsc-rendering.ts +79 -23
- package/src/rsc/server-action.ts +25 -2
- package/src/rsc/shell-capture-constants.ts +22 -0
- package/src/rsc/shell-capture.ts +11 -0
- package/src/rsc/types.ts +5 -0
- package/src/segment-system.tsx +125 -119
- package/src/server/context.ts +96 -5
- package/src/server/handle-store.ts +3 -2
- package/src/server/request-context.ts +42 -3
- package/src/server/request-headers.ts +32 -0
- package/src/server/rewrite-trail.ts +55 -9
- package/src/ssr/ssr-root.tsx +6 -10
- package/src/testing/dispatch.ts +4 -5
- package/src/testing/e2e/index.ts +1 -0
- package/src/testing/flight.entry.ts +1 -0
- package/src/testing/index.ts +1 -0
- package/src/testing/internal/client-urls-projection.ts +31 -11
- package/src/testing/render-route.tsx +83 -40
- package/src/testing/run-loader.ts +26 -2
- package/src/testing/run-middleware.ts +10 -0
- package/src/testing/run-revalidate.ts +13 -6
- package/src/testing/serve-shell-request.ts +77 -4
- package/src/testing/shell-status.ts +40 -0
- package/src/testing/vitest-stubs/version.ts +1 -0
- package/src/testing/vitest.ts +74 -7
- package/src/thenable-status.ts +0 -11
- package/src/types/handler-context.ts +12 -1
- package/src/types/loader-types.ts +4 -3
- package/src/types/route-entry.ts +2 -1
- package/src/urls/include-helper.ts +38 -11
- package/src/urls/path-helper-types.ts +4 -2
- package/src/vite/discovery/client-urls-projection.ts +205 -16
- package/src/vite/discovery/discover-routers.ts +2 -2
- package/src/vite/discovery/prerender-collection.ts +2 -6
- package/src/vite/discovery/state.ts +26 -0
- package/src/vite/plugins/client-urls-revalidate-hoist.ts +190 -77
- package/src/vite/plugins/expose-internal-ids.ts +46 -40
- package/src/vite/plugins/hoist/source.ts +8 -7
- package/src/vite/plugins/transition-when-hoist.ts +1 -0
- package/src/vite/plugins/version-plugin.ts +7 -0
- package/src/vite/plugins/version.d.ts +7 -0
- package/src/vite/plugins/virtual-entries.ts +20 -0
- package/src/vite/rango.ts +4 -1
- package/src/vite/router-discovery.ts +39 -7
- package/src/vite/utils/prerender-utils.ts +17 -0
|
@@ -1,9 +1,5 @@
|
|
|
1
1
|
import type { ResolvedSegment } from "./types.js";
|
|
2
|
-
import {
|
|
3
|
-
mergeSegmentLoaders,
|
|
4
|
-
needsLoaderMerge,
|
|
5
|
-
insertMissingDiffSegments,
|
|
6
|
-
} from "./merge-segment-loaders.js";
|
|
2
|
+
import { insertMissingDiffSegments } from "./merge-segment-loaders.js";
|
|
7
3
|
import { assertSegmentStructure } from "./segment-structure-assert.js";
|
|
8
4
|
import { splitInterceptSegments } from "./intercept-utils.js";
|
|
9
5
|
import { debugLog, IS_BROWSER_DEBUG } from "./logging.js";
|
|
@@ -11,15 +7,17 @@ import { debugLog, IS_BROWSER_DEBUG } from "./logging.js";
|
|
|
11
7
|
/**
|
|
12
8
|
* Determines the merging behavior for segment reconciliation.
|
|
13
9
|
*
|
|
14
|
-
* - 'action': From server-action-bridge's own merge. Always
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
* on cached segments not in server diff.
|
|
10
|
+
* - 'action': From server-action-bridge's own merge. Always preserves cached
|
|
11
|
+
* loading (even undefined), never clears cached segment loading.
|
|
12
|
+
* - 'navigation': From partial-update during normal navigation. Preserves
|
|
13
|
+
* cached loading only when defined, clears truthy loading on cached
|
|
14
|
+
* segments not in server diff.
|
|
20
15
|
* - 'stale-revalidation': From partial-update during stale revalidation or
|
|
21
|
-
* action-triggered refetch.
|
|
22
|
-
*
|
|
16
|
+
* action-triggered refetch. Always preserves cached loading (same as
|
|
17
|
+
* action), clears truthy loading on cached segments not in server diff.
|
|
18
|
+
*
|
|
19
|
+
* No actor merges loader data: a loader the server skipped, an intercept's
|
|
20
|
+
* included, is its own cached segment in `matched`.
|
|
23
21
|
*/
|
|
24
22
|
export type ReconcileActor = "navigation" | "action" | "stale-revalidation";
|
|
25
23
|
|
|
@@ -64,11 +62,6 @@ export interface ReconcileResult {
|
|
|
64
62
|
* (not undefined). When cached is undefined, lets server value through
|
|
65
63
|
* because we're building a new tree.
|
|
66
64
|
*
|
|
67
|
-
* Loader merging:
|
|
68
|
-
* - action/stale-revalidation: Merges partial loader data when server returns
|
|
69
|
-
* fewer loaders than cached (revalidation only updated some loaders).
|
|
70
|
-
* - navigation: Does not merge (full navigation fetches complete data).
|
|
71
|
-
*
|
|
72
65
|
* Cached segment handling (segments in matched but not in server response):
|
|
73
66
|
* - action: Returns cached segment as-is (preserve tree structure).
|
|
74
67
|
* - navigation/stale-revalidation: Clears truthy loading to undefined
|
|
@@ -77,7 +70,6 @@ export interface ReconcileResult {
|
|
|
77
70
|
*/
|
|
78
71
|
export function reconcileSegments(input: ReconcileInput): ReconcileResult {
|
|
79
72
|
const { actor, matched, diff, insertMissingDiff } = input;
|
|
80
|
-
const shouldMergeLoaders = actor !== "navigation";
|
|
81
73
|
const context = actor === "action" ? "action-bridge" : "partial-update";
|
|
82
74
|
|
|
83
75
|
// Build lookup maps from arrays
|
|
@@ -119,16 +111,6 @@ export function reconcileSegments(input: ReconcileInput): ReconcileResult {
|
|
|
119
111
|
|
|
120
112
|
if (fromServer) {
|
|
121
113
|
const inDiff = diffSet.has(segId);
|
|
122
|
-
// Merge partial loader data when server returns fewer loaders than cached
|
|
123
|
-
if (shouldMergeLoaders && needsLoaderMerge(fromServer, fromCache)) {
|
|
124
|
-
if (IS_BROWSER_DEBUG) {
|
|
125
|
-
debugLog(
|
|
126
|
-
`[reconcile] ${segId}: MERGE loaders (server partial, ${inDiff ? "in diff" : "not in diff"})`,
|
|
127
|
-
);
|
|
128
|
-
}
|
|
129
|
-
return mergeSegmentLoaders(fromServer, fromCache);
|
|
130
|
-
}
|
|
131
|
-
|
|
132
114
|
// Preserve cached structural properties to maintain consistent React tree.
|
|
133
115
|
// Changing these between renders alters the element nesting
|
|
134
116
|
// (with/without RouteContentWrapper, MountContextProvider, etc.),
|
|
@@ -3,8 +3,10 @@ import type {
|
|
|
3
3
|
ServerActionBridgeConfig,
|
|
4
4
|
RscPayload,
|
|
5
5
|
ResolvedSegment,
|
|
6
|
+
NavigationUpdate,
|
|
7
|
+
UpdateSubscriber,
|
|
6
8
|
} from "./types.js";
|
|
7
|
-
import { createPartialUpdater } from "./partial-update.js";
|
|
9
|
+
import { addTransitionType, createPartialUpdater } from "./partial-update.js";
|
|
8
10
|
import { enterActionFence, exitActionFence } from "./action-fence.js";
|
|
9
11
|
import { KEEP_CACHE_HEADER } from "./cookie-name.js";
|
|
10
12
|
import { createNavigationTransaction } from "./navigation-transaction.js";
|
|
@@ -39,6 +41,7 @@ import {
|
|
|
39
41
|
import { mergeLocationState } from "./history-state.js";
|
|
40
42
|
import { stampLocationState } from "./react/location-state-shared.js";
|
|
41
43
|
import { classifyActionOutcome } from "./action-coordinator.js";
|
|
44
|
+
import { revalidationErrorOf } from "../decode-loader-results.js";
|
|
42
45
|
import { getAppVersion } from "./app-version.js";
|
|
43
46
|
import {
|
|
44
47
|
decideCommitGatedOff,
|
|
@@ -99,6 +102,24 @@ function applyActionLocationState(
|
|
|
99
102
|
}
|
|
100
103
|
}
|
|
101
104
|
|
|
105
|
+
/**
|
|
106
|
+
* An action's commit: urgent when transition({ when }) gated it off, like
|
|
107
|
+
* every gated-off commit, else a transition tagged `action` (#1165).
|
|
108
|
+
*/
|
|
109
|
+
function commitAction(
|
|
110
|
+
onUpdate: UpdateSubscriber,
|
|
111
|
+
update: NavigationUpdate,
|
|
112
|
+
gatedOff: boolean,
|
|
113
|
+
): void {
|
|
114
|
+
if (gatedOff) onUpdate(update);
|
|
115
|
+
else
|
|
116
|
+
startTransition(() => {
|
|
117
|
+
addTransitionType?.("action");
|
|
118
|
+
update.inTransition = true;
|
|
119
|
+
onUpdate(update);
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
|
|
102
123
|
/**
|
|
103
124
|
* Create a server action bridge for handling RSC server actions
|
|
104
125
|
*
|
|
@@ -173,6 +194,7 @@ export function createServerActionBridge(
|
|
|
173
194
|
* Refetch current route via a navigation transaction.
|
|
174
195
|
* Encapsulates the repeated pattern of creating a navTx + fetchPartialUpdate
|
|
175
196
|
* used by navigated-away, hmr-missing, and consolidation-needed scenarios.
|
|
197
|
+
* Resolves with the error of a loader that threw on the refetch.
|
|
176
198
|
*/
|
|
177
199
|
async function refetchRoute(opts?: {
|
|
178
200
|
segments?: string[];
|
|
@@ -180,7 +202,7 @@ export function createServerActionBridge(
|
|
|
180
202
|
actionId?: string;
|
|
181
203
|
/** transition({ when }) `action` fields for the refetch commit. */
|
|
182
204
|
action?: TransitionWhenActionInput;
|
|
183
|
-
}): Promise<
|
|
205
|
+
}): Promise<Error | undefined> {
|
|
184
206
|
const src = opts?.interceptSourceUrl ?? null;
|
|
185
207
|
const navTx = createNavigationTransaction(
|
|
186
208
|
store,
|
|
@@ -189,7 +211,7 @@ export function createServerActionBridge(
|
|
|
189
211
|
{ replace: true, skipLoadingState: true },
|
|
190
212
|
);
|
|
191
213
|
try {
|
|
192
|
-
await fetchPartialUpdate(
|
|
214
|
+
return await fetchPartialUpdate(
|
|
193
215
|
window.location.href,
|
|
194
216
|
opts?.segments ?? [],
|
|
195
217
|
false,
|
|
@@ -302,6 +324,11 @@ export function createServerActionBridge(
|
|
|
302
324
|
if (rid) {
|
|
303
325
|
url.searchParams.set("_rsc_rid", rid);
|
|
304
326
|
}
|
|
327
|
+
// The page's rewrite target: the server diffs the re-render against it.
|
|
328
|
+
const rewriteTarget = store.getHistoryEntryMemory()?.rewriteTarget;
|
|
329
|
+
if (rewriteTarget) {
|
|
330
|
+
url.searchParams.set("_rsc_rt", rewriteTarget);
|
|
331
|
+
}
|
|
305
332
|
|
|
306
333
|
// Encode arguments
|
|
307
334
|
const encodedBody = await deps.encodeReply(args, { temporaryReferences });
|
|
@@ -618,12 +645,13 @@ export function createServerActionBridge(
|
|
|
618
645
|
);
|
|
619
646
|
store.rememberDisplayedEntry();
|
|
620
647
|
|
|
621
|
-
// Update UI with error boundary
|
|
622
|
-
// gated it off, like every gated-off commit.
|
|
623
|
-
const errorUpdate = { root: errorTree, metadata: metadata! };
|
|
648
|
+
// Update UI with error boundary.
|
|
624
649
|
if (process.env.NODE_ENV !== "production") auditTreeCause("action");
|
|
625
|
-
|
|
626
|
-
|
|
650
|
+
commitAction(
|
|
651
|
+
onUpdate,
|
|
652
|
+
{ root: errorTree, metadata: metadata! },
|
|
653
|
+
errorGatedOff,
|
|
654
|
+
);
|
|
627
655
|
|
|
628
656
|
// Throw the error so the action promise rejects
|
|
629
657
|
if (returnValue && !returnValue.ok) {
|
|
@@ -677,6 +705,8 @@ export function createServerActionBridge(
|
|
|
677
705
|
const fullSegments = reconciled.segments;
|
|
678
706
|
|
|
679
707
|
const returnData = returnValue?.data;
|
|
708
|
+
// A loader that threw while it re-ran: reported, not thrown.
|
|
709
|
+
let revalidationError: Error | undefined;
|
|
680
710
|
|
|
681
711
|
if (returnValue && !returnValue.ok) {
|
|
682
712
|
handle.fail(returnValue.data);
|
|
@@ -754,7 +784,7 @@ export function createServerActionBridge(
|
|
|
754
784
|
// route. Invalidation is deferred to finalizeAction(); here we only
|
|
755
785
|
// trigger the revalidation refetch (suppressed on keep).
|
|
756
786
|
if (!keepCache) {
|
|
757
|
-
await refetchRoute({
|
|
787
|
+
revalidationError = await refetchRoute({
|
|
758
788
|
interceptSourceUrl: store.getInterceptSourceUrl(),
|
|
759
789
|
actionId: id,
|
|
760
790
|
action: whenAction,
|
|
@@ -771,7 +801,7 @@ export function createServerActionBridge(
|
|
|
771
801
|
// resolving last must discharge a directive-free sibling's repair.
|
|
772
802
|
// See the keep row in docs/design/rango-state-cookie.md (the all-keep
|
|
773
803
|
// edge, and the benign re-mark-stale-after-refetch end-state delta).
|
|
774
|
-
await refetchRoute({
|
|
804
|
+
revalidationError = await refetchRoute({
|
|
775
805
|
interceptSourceUrl,
|
|
776
806
|
actionId: id,
|
|
777
807
|
action: whenAction,
|
|
@@ -794,7 +824,7 @@ export function createServerActionBridge(
|
|
|
794
824
|
handle.clearConsolidation();
|
|
795
825
|
|
|
796
826
|
// Ungated on keepCache, same as hmr-missing above (see the keep row).
|
|
797
|
-
await refetchRoute({
|
|
827
|
+
revalidationError = await refetchRoute({
|
|
798
828
|
segments: segmentsToSend,
|
|
799
829
|
interceptSourceUrl,
|
|
800
830
|
actionId: id,
|
|
@@ -824,6 +854,9 @@ export function createServerActionBridge(
|
|
|
824
854
|
currentHandleData,
|
|
825
855
|
);
|
|
826
856
|
}
|
|
857
|
+
// Not rendered: the sibling's refetch reruns these loaders and
|
|
858
|
+
// reports its own. Resolve when the metadata lands, without waiting
|
|
859
|
+
// for this answer's loader chunks.
|
|
827
860
|
break;
|
|
828
861
|
}
|
|
829
862
|
|
|
@@ -854,6 +887,7 @@ export function createServerActionBridge(
|
|
|
854
887
|
? reconciled.interceptSegments
|
|
855
888
|
: undefined,
|
|
856
889
|
});
|
|
890
|
+
revalidationError = await revalidationErrorOf(segments);
|
|
857
891
|
|
|
858
892
|
// Re-check if user navigated away (could happen during async renderSegments)
|
|
859
893
|
if (window.location.pathname !== actionStartPathname) {
|
|
@@ -891,12 +925,14 @@ export function createServerActionBridge(
|
|
|
891
925
|
fullSegments,
|
|
892
926
|
currentHandleData,
|
|
893
927
|
);
|
|
894
|
-
store.rememberDisplayedEntry(metadata
|
|
928
|
+
store.rememberDisplayedEntry(metadata);
|
|
895
929
|
|
|
896
|
-
const actionUpdate = { root: newTree, metadata: metadata! };
|
|
897
930
|
if (process.env.NODE_ENV !== "production") auditTreeCause("action");
|
|
898
|
-
|
|
899
|
-
|
|
931
|
+
commitAction(
|
|
932
|
+
onUpdate,
|
|
933
|
+
{ root: newTree, metadata: metadata! },
|
|
934
|
+
gatedOff,
|
|
935
|
+
);
|
|
900
936
|
// Invalidation deferred to finalizeAction() (runs after this caches
|
|
901
937
|
// the fresh segments), suppressed when the action called
|
|
902
938
|
// keepClientCache().
|
|
@@ -904,7 +940,7 @@ export function createServerActionBridge(
|
|
|
904
940
|
}
|
|
905
941
|
}
|
|
906
942
|
|
|
907
|
-
handle.complete(returnData);
|
|
943
|
+
handle.complete(returnData, revalidationError);
|
|
908
944
|
return returnData;
|
|
909
945
|
} catch (error) {
|
|
910
946
|
// What the call rejects with (a revalidation render that threw, a
|
package/src/browser/types.ts
CHANGED
|
@@ -36,6 +36,11 @@ export type HandleData = Record<string, Record<string, unknown[]>>;
|
|
|
36
36
|
*/
|
|
37
37
|
export interface RscMetadata {
|
|
38
38
|
pathname: string;
|
|
39
|
+
/**
|
|
40
|
+
* Path and search of the URL the route rendered, when middleware rewrote
|
|
41
|
+
* the request there. Kept per history entry and sent back as `_rsc_rt`.
|
|
42
|
+
*/
|
|
43
|
+
rewriteTarget?: string;
|
|
39
44
|
segments: ResolvedSegment[];
|
|
40
45
|
/** Router instance ID — the current app's identity. A mismatch with the
|
|
41
46
|
* client's id (sent as _rsc_rid) is detected server-side and answered with
|
|
@@ -248,6 +253,13 @@ export interface TrackedActionState {
|
|
|
248
253
|
|
|
249
254
|
/** Result data from the action (preserved after completion) */
|
|
250
255
|
result: unknown | null;
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* The error of a loader that threw while it re-ran after this successful
|
|
259
|
+
* action (the first, when several did). The loader also throws at its
|
|
260
|
+
* useLoader read, where the nearest error boundary catches it.
|
|
261
|
+
*/
|
|
262
|
+
revalidationError: unknown | null;
|
|
251
263
|
}
|
|
252
264
|
|
|
253
265
|
/**
|
|
@@ -292,13 +304,24 @@ export interface SegmentState {
|
|
|
292
304
|
currentSegmentIds: string[];
|
|
293
305
|
}
|
|
294
306
|
|
|
307
|
+
/**
|
|
308
|
+
* What a committed payload says about the page it shows, remembered per
|
|
309
|
+
* history entry (NavigationStore.rememberDisplayedEntry).
|
|
310
|
+
*
|
|
311
|
+
* @internal This type is an implementation detail and may change without notice.
|
|
312
|
+
*/
|
|
313
|
+
export interface ShownEntry {
|
|
314
|
+
readonly routeName?: string;
|
|
315
|
+
readonly rewriteTarget?: string;
|
|
316
|
+
}
|
|
317
|
+
|
|
295
318
|
/**
|
|
296
319
|
* What the router remembers about one history entry for transition({ when })
|
|
297
|
-
* (NavigationStore.rememberDisplayedEntry).
|
|
320
|
+
* and the requests made from it (NavigationStore.rememberDisplayedEntry).
|
|
298
321
|
*
|
|
299
322
|
* @internal This type is an implementation detail and may change without notice.
|
|
300
323
|
*/
|
|
301
|
-
export interface HistoryEntryMemory {
|
|
324
|
+
export interface HistoryEntryMemory extends ShownEntry {
|
|
302
325
|
readonly routeName: string | undefined;
|
|
303
326
|
/** The entry's `history.state` as last recorded. */
|
|
304
327
|
readonly state: unknown;
|
|
@@ -326,6 +349,12 @@ export interface NavigationUpdate {
|
|
|
326
349
|
/** Function to check if streaming is in progress */
|
|
327
350
|
isStreaming?: () => boolean;
|
|
328
351
|
};
|
|
352
|
+
/**
|
|
353
|
+
* Handed to React inside startTransition (commitInTransition, an action's
|
|
354
|
+
* commit, a cached back/forward's): NavigationProvider joins the route
|
|
355
|
+
* state that arrives while React holds it to its commit.
|
|
356
|
+
*/
|
|
357
|
+
inTransition?: true;
|
|
329
358
|
}
|
|
330
359
|
|
|
331
360
|
/**
|
|
@@ -587,12 +616,12 @@ export interface NavigationStore {
|
|
|
587
616
|
/**
|
|
588
617
|
* Per-history-entry memory for transition({ when }) sources: record the
|
|
589
618
|
* entry on screen (keyed by its `history.state.key`) with its current
|
|
590
|
-
* `history.state` and, when given, its route name
|
|
591
|
-
* record otherwise; every push/replace
|
|
592
|
-
* never carries to another entry).
|
|
593
|
-
* state merge.
|
|
619
|
+
* `history.state` and, when `shown` is given, its route name and rewrite
|
|
620
|
+
* target (both kept from the last record otherwise; every push/replace
|
|
621
|
+
* creates a new key, so a stale record never carries to another entry).
|
|
622
|
+
* Called after every commit, restore and state merge.
|
|
594
623
|
*/
|
|
595
|
-
rememberDisplayedEntry(
|
|
624
|
+
rememberDisplayedEntry(shown?: ShownEntry): void;
|
|
596
625
|
/**
|
|
597
626
|
* The memory of the entry on screen, or of `entryKey`. At popstate
|
|
598
627
|
* history.state already belongs to the destination, so back/forward reads
|
|
@@ -683,6 +712,8 @@ export interface FetchPartialOptions {
|
|
|
683
712
|
targetUrl: string;
|
|
684
713
|
segmentIds: string[];
|
|
685
714
|
previousUrl: string;
|
|
715
|
+
/** The page's RscMetadata.rewriteTarget, sent as `_rsc_rt`. */
|
|
716
|
+
rewriteTarget?: string;
|
|
686
717
|
signal?: AbortSignal;
|
|
687
718
|
/** If true, this is a stale cache revalidation request - server should force revalidators */
|
|
688
719
|
staleRevalidation?: boolean;
|
|
@@ -772,7 +803,8 @@ export interface ServerActionBridgeConfig {
|
|
|
772
803
|
export interface NavigationBridge {
|
|
773
804
|
navigate(url: string, options?: NavigateOptionsInternal): Promise<void>;
|
|
774
805
|
refresh(): Promise<void>;
|
|
775
|
-
|
|
806
|
+
/** `event`: the popstate event; a traversal the browser animated itself (hasUAVisualTransition) is not animated again. */
|
|
807
|
+
handlePopstate(event?: PopStateEvent): Promise<void>;
|
|
776
808
|
registerLinkInterception(): () => void;
|
|
777
809
|
registerDelegatedPrefetch(): () => void;
|
|
778
810
|
/** Current RSC version (live, reflects the latest updateVersion). */
|
|
@@ -16,7 +16,11 @@ import {
|
|
|
16
16
|
RangoContext,
|
|
17
17
|
runWithPrefixes,
|
|
18
18
|
} from "../server/context.js";
|
|
19
|
-
import type {
|
|
19
|
+
import type {
|
|
20
|
+
EntryData,
|
|
21
|
+
IncludeScopePosition,
|
|
22
|
+
TrackedInclude,
|
|
23
|
+
} from "../server/context.js";
|
|
20
24
|
import type { TrailingSlashMode } from "../types.js";
|
|
21
25
|
import { createRouteHelpers } from "../route-definition.js";
|
|
22
26
|
import MapRootLayout from "../server/root-layout.js";
|
|
@@ -179,6 +183,7 @@ async function buildPrefixTreeNode(
|
|
|
179
183
|
routeSearchSchemas?: Record<string, Record<string, string>>,
|
|
180
184
|
routerId?: string,
|
|
181
185
|
validateTransitionWhen?: boolean,
|
|
186
|
+
position?: IncludeScopePosition,
|
|
182
187
|
): Promise<PrefixTreeNode> {
|
|
183
188
|
// Resolve an async include provider (`() => import("./routes")`) so its routes
|
|
184
189
|
// are walked into the build-time manifest/types/href. Runtime matching still
|
|
@@ -222,6 +227,10 @@ async function buildPrefixTreeNode(
|
|
|
222
227
|
mountIndex,
|
|
223
228
|
...(routerId ? { routerId } : {}),
|
|
224
229
|
trackedIncludes, // Enable nested include tracking
|
|
230
|
+
// The same position runtime expansion runs this include at
|
|
231
|
+
// (lazy-includes.ts), so nested hidden names agree across realms.
|
|
232
|
+
scopePath: position?.scopePath,
|
|
233
|
+
hiddenScopePath: position?.hiddenScopePath,
|
|
225
234
|
},
|
|
226
235
|
() => {
|
|
227
236
|
const helpers = createRouteHelpers();
|
|
@@ -304,6 +313,7 @@ async function buildPrefixTreeNode(
|
|
|
304
313
|
routeSearchSchemas,
|
|
305
314
|
routerId,
|
|
306
315
|
validateTransitionWhen,
|
|
316
|
+
include,
|
|
307
317
|
),
|
|
308
318
|
);
|
|
309
319
|
|
|
@@ -505,6 +515,7 @@ export async function generateManifestFull<TEnv>(
|
|
|
505
515
|
routeSearchSchemas,
|
|
506
516
|
options?.routerId,
|
|
507
517
|
options?.validateTransitionWhen,
|
|
518
|
+
include,
|
|
508
519
|
),
|
|
509
520
|
);
|
|
510
521
|
|
|
@@ -48,7 +48,11 @@ export function generatePerModuleTypesSource(
|
|
|
48
48
|
}
|
|
49
49
|
deduped.set(name, { pattern, params, search });
|
|
50
50
|
}
|
|
51
|
-
|
|
51
|
+
// Locale pinned: the machine's default locale reorders names (Czech sorts
|
|
52
|
+
// "ch" after "h"), and generated files must be identical on every machine.
|
|
53
|
+
const sorted = [...deduped.entries()].sort(([a], [b]) =>
|
|
54
|
+
a.localeCompare(b, "en"),
|
|
55
|
+
);
|
|
52
56
|
const body = sorted
|
|
53
57
|
.map(([name, { pattern, params, search }]) => {
|
|
54
58
|
const key = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(name) ? name : `"${name}"`;
|
|
@@ -69,7 +73,7 @@ export function generateRouteTypesSource(
|
|
|
69
73
|
): string {
|
|
70
74
|
const entries = Object.entries(routeManifest)
|
|
71
75
|
.filter(([name]) => !isAutoGeneratedRouteName(name))
|
|
72
|
-
.sort(([a], [b]) => a.localeCompare(b));
|
|
76
|
+
.sort(([a], [b]) => a.localeCompare(b, "en"));
|
|
73
77
|
|
|
74
78
|
const filteredSearchSchemas = searchSchemas
|
|
75
79
|
? Object.fromEntries(
|
|
@@ -62,70 +62,107 @@ export function findUrlsVariableNames(code: string): string[] {
|
|
|
62
62
|
return names;
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
+
export interface PerModuleRouteTypesPlan {
|
|
66
|
+
genPath: string;
|
|
67
|
+
/** A urls()/clientUrls() variable resolved to zero routes; content is empty. */
|
|
68
|
+
isPlaceholder: boolean;
|
|
69
|
+
content: string;
|
|
70
|
+
}
|
|
71
|
+
|
|
65
72
|
/**
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
*
|
|
69
|
-
* routes.
|
|
73
|
+
* Pure half of the per-module writer: reads sources, never writes. Returns
|
|
74
|
+
* null when the file has no `urls(`/`clientUrls(` or no named routes and no
|
|
75
|
+
* urls() variable. Throws on failure.
|
|
70
76
|
*/
|
|
71
|
-
export function
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
77
|
+
export function planPerModuleRouteTypesForFile(
|
|
78
|
+
filePath: string,
|
|
79
|
+
): PerModuleRouteTypesPlan | null {
|
|
80
|
+
const source = readFileSync(filePath, "utf-8");
|
|
81
|
+
if (!source.includes("urls(") && !source.includes("clientUrls(")) return null;
|
|
75
82
|
|
|
76
|
-
|
|
83
|
+
const varNames = findUrlsVariableNames(source);
|
|
77
84
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
+
type Route = {
|
|
86
|
+
name: string;
|
|
87
|
+
pattern: string;
|
|
88
|
+
params?: Record<string, string>;
|
|
89
|
+
search?: Record<string, string>;
|
|
90
|
+
};
|
|
91
|
+
let routes: Route[];
|
|
85
92
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
}
|
|
93
|
+
if (varNames.length > 0) {
|
|
94
|
+
// Follow includes recursively via the combined route map builder.
|
|
95
|
+
// The visited set in buildCombinedRouteMapWithSearch prevents infinite loops.
|
|
96
|
+
// Share one per-file scan memo across all urls() variables so a shared
|
|
97
|
+
// include target is read+parsed once for this file, not once per variable.
|
|
98
|
+
routes = [];
|
|
99
|
+
const memo = createScanMemo();
|
|
100
|
+
for (const varName of varNames) {
|
|
101
|
+
const { routes: routeMap, searchSchemas } =
|
|
102
|
+
buildCombinedRouteMapWithSearch(
|
|
103
|
+
filePath,
|
|
104
|
+
varName,
|
|
105
|
+
undefined,
|
|
106
|
+
undefined,
|
|
107
|
+
undefined,
|
|
108
|
+
memo,
|
|
109
|
+
);
|
|
110
|
+
for (const [name, pattern] of Object.entries(routeMap)) {
|
|
111
|
+
const params = extractParamsFromPattern(pattern);
|
|
112
|
+
routes.push({
|
|
113
|
+
name,
|
|
114
|
+
pattern,
|
|
115
|
+
...(params ? { params } : {}),
|
|
116
|
+
...(searchSchemas[name] ? { search: searchSchemas[name] } : {}),
|
|
117
|
+
});
|
|
112
118
|
}
|
|
113
|
-
} else {
|
|
114
|
-
// Fallback: no urls() variable found, extract path() calls directly
|
|
115
|
-
routes = extractRoutesFromSource(source);
|
|
116
119
|
}
|
|
120
|
+
} else {
|
|
121
|
+
// Fallback: no urls() variable found, extract path() calls directly
|
|
122
|
+
routes = extractRoutesFromSource(source);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// Match .ts/.tsx/.js/.jsx (same as router-processing.ts / router-transform.ts).
|
|
126
|
+
// Without the jsx? branch a .jsx/.js source produced genPath === filePath,
|
|
127
|
+
// overwriting the source file instead of writing a sibling .gen.ts.
|
|
128
|
+
const genPath = filePath.replace(/\.(tsx?|jsx?)$/, ".gen.ts");
|
|
117
129
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
130
|
+
if (routes.length === 0) {
|
|
131
|
+
if (varNames.length === 0) return null;
|
|
132
|
+
return {
|
|
133
|
+
genPath,
|
|
134
|
+
isPlaceholder: true,
|
|
135
|
+
content: generatePerModuleTypesSource([]),
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
return {
|
|
139
|
+
genPath,
|
|
140
|
+
isPlaceholder: false,
|
|
141
|
+
content: generatePerModuleTypesSource(routes),
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Generate per-module route types for a single url module file.
|
|
147
|
+
* Follows include() calls recursively to produce the full route tree.
|
|
148
|
+
* No-ops if the file doesn't contain `urls(`/`clientUrls(` or has no named
|
|
149
|
+
* routes.
|
|
150
|
+
*/
|
|
151
|
+
export function writePerModuleRouteTypesForFile(filePath: string): void {
|
|
152
|
+
try {
|
|
153
|
+
const plan = planPerModuleRouteTypesForFile(filePath);
|
|
154
|
+
if (!plan) return;
|
|
155
|
+
const { genPath, isPlaceholder, content } = plan;
|
|
156
|
+
const exists = existsSync(genPath);
|
|
122
157
|
|
|
123
|
-
//
|
|
124
|
-
//
|
|
125
|
-
//
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
158
|
+
// A urls() variable whose static resolution yields zero routes gets an
|
|
159
|
+
// empty placeholder so an import of the sibling .gen.ts resolves. Nothing
|
|
160
|
+
// fills it in later: runtime discovery writes only *.named-routes.gen.ts
|
|
161
|
+
// (runtime-discovery.ts), so it stays `routes = {}` until a static run can
|
|
162
|
+
// resolve the module's includes and overwrites it.
|
|
163
|
+
if (isPlaceholder) {
|
|
164
|
+
if (!exists) {
|
|
165
|
+
writeFileSync(genPath, content);
|
|
129
166
|
console.log(
|
|
130
167
|
`[rango] Generated route types (placeholder) -> ${genPath}`,
|
|
131
168
|
);
|
|
@@ -133,12 +170,8 @@ export function writePerModuleRouteTypesForFile(filePath: string): void {
|
|
|
133
170
|
return;
|
|
134
171
|
}
|
|
135
172
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
? readFileSync(genPath, "utf-8")
|
|
139
|
-
: null;
|
|
140
|
-
if (existing !== genSource) {
|
|
141
|
-
writeFileSync(genPath, genSource);
|
|
173
|
+
if (!exists || readFileSync(genPath, "utf-8") !== content) {
|
|
174
|
+
writeFileSync(genPath, content);
|
|
142
175
|
console.log(`[rango] Generated route types -> ${genPath}`);
|
|
143
176
|
}
|
|
144
177
|
} catch (err) {
|
|
@@ -508,6 +508,15 @@ export function registerCachedFunction<T extends (...args: any[]) => any>(
|
|
|
508
508
|
if (ctx._routeName) {
|
|
509
509
|
keyArgs.push(ctx._routeName);
|
|
510
510
|
}
|
|
511
|
+
// A layout's / parallel's / their loader's ctx resolves dot names
|
|
512
|
+
// in its own module (withReverseScope), so one route's segments
|
|
513
|
+
// can reverse the same name differently.
|
|
514
|
+
const scope = ctx._reverseScope;
|
|
515
|
+
if (scope) {
|
|
516
|
+
keyArgs.push(
|
|
517
|
+
`reverse-scope:${scope.prefix ?? ""}:${scope.rootScoped}`,
|
|
518
|
+
);
|
|
519
|
+
}
|
|
511
520
|
keyArgs.push(ctx.pathname, ctx.params);
|
|
512
521
|
if (ctx._responseType) {
|
|
513
522
|
keyArgs.push(ctx._responseType);
|
package/src/cache/cache-scope.ts
CHANGED
|
@@ -24,6 +24,7 @@ import {
|
|
|
24
24
|
runInSegmentTagScope,
|
|
25
25
|
} from "./cache-tag.js";
|
|
26
26
|
import { reportCacheError } from "./cache-error.js";
|
|
27
|
+
import { isInterceptSegment } from "../browser/intercept-utils.js";
|
|
27
28
|
import {
|
|
28
29
|
predatesInvalidation,
|
|
29
30
|
type ExecutionStart,
|
|
@@ -373,7 +374,7 @@ export class CacheScope {
|
|
|
373
374
|
const next = id.charCodeAt(boundary.length);
|
|
374
375
|
return !(next >= 48 && next <= 57);
|
|
375
376
|
}
|
|
376
|
-
return
|
|
377
|
+
return isInterceptSegment({ namespace });
|
|
377
378
|
}
|
|
378
379
|
|
|
379
380
|
/**
|
|
@@ -422,6 +422,7 @@ function shellHeadToEntry(head: ShellFrameHead): ShellEntryHead {
|
|
|
422
422
|
reactVersion: head.rv,
|
|
423
423
|
buildVersion: head.bv,
|
|
424
424
|
initialTheme: head.i,
|
|
425
|
+
pathname: head.lp,
|
|
425
426
|
docKey: head.dk,
|
|
426
427
|
prunedRecords: head.pr,
|
|
427
428
|
navigationOnly: head.no,
|
|
@@ -2695,6 +2696,7 @@ export class CFCacheStore<TEnv = unknown> implements SegmentCacheStore<TEnv> {
|
|
|
2695
2696
|
t: tags,
|
|
2696
2697
|
ta: taggedAt,
|
|
2697
2698
|
i: entry.initialTheme,
|
|
2699
|
+
lp: entry.pathname,
|
|
2698
2700
|
dk: entry.docKey,
|
|
2699
2701
|
pr: entry.prunedRecords,
|
|
2700
2702
|
no: entry.navigationOnly,
|