@rangojs/router 0.0.0-experimental.10 → 0.0.0-experimental.100
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 +1037 -4
- package/dist/bin/rango.js +1619 -157
- package/dist/vite/index.js +5762 -2301
- package/dist/vite/plugins/cloudflare-protocol-loader-hook.mjs +76 -0
- package/package.json +71 -63
- package/skills/breadcrumbs/SKILL.md +252 -0
- package/skills/cache-guide/SKILL.md +294 -0
- package/skills/caching/SKILL.md +93 -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/handler-use/SKILL.md +364 -0
- package/skills/hooks/SKILL.md +367 -71
- package/skills/host-router/SKILL.md +218 -0
- package/skills/i18n/SKILL.md +276 -0
- package/skills/intercept/SKILL.md +176 -8
- package/skills/layout/SKILL.md +124 -3
- package/skills/links/SKILL.md +304 -25
- package/skills/loader/SKILL.md +474 -47
- package/skills/middleware/SKILL.md +207 -37
- package/skills/migrate-nextjs/SKILL.md +562 -0
- package/skills/migrate-react-router/SKILL.md +769 -0
- package/skills/mime-routes/SKILL.md +15 -11
- package/skills/parallel/SKILL.md +272 -1
- package/skills/prerender/SKILL.md +467 -65
- package/skills/rango/SKILL.md +89 -21
- package/skills/response-routes/SKILL.md +152 -91
- package/skills/route/SKILL.md +305 -14
- package/skills/router-setup/SKILL.md +210 -32
- package/skills/server-actions/SKILL.md +739 -0
- package/skills/streams-and-websockets/SKILL.md +283 -0
- package/skills/theme/SKILL.md +9 -8
- package/skills/typesafety/SKILL.md +333 -86
- package/skills/use-cache/SKILL.md +324 -0
- package/skills/view-transitions/SKILL.md +212 -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/app-shell.ts +52 -0
- package/src/browser/app-version.ts +14 -0
- package/src/browser/event-controller.ts +136 -68
- 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 +55 -0
- package/src/browser/merge-segment-loaders.ts +20 -12
- package/src/browser/navigation-bridge.ts +374 -561
- package/src/browser/navigation-client.ts +228 -70
- package/src/browser/navigation-store.ts +97 -55
- package/src/browser/navigation-transaction.ts +297 -0
- package/src/browser/network-error-handler.ts +61 -0
- package/src/browser/partial-update.ts +376 -315
- package/src/browser/prefetch/cache.ts +314 -0
- package/src/browser/prefetch/fetch.ts +282 -0
- package/src/browser/prefetch/observer.ts +65 -0
- package/src/browser/prefetch/policy.ts +48 -0
- package/src/browser/prefetch/queue.ts +191 -0
- package/src/browser/prefetch/resource-ready.ts +77 -0
- package/src/browser/rango-state.ts +152 -0
- package/src/browser/react/Link.tsx +255 -71
- package/src/browser/react/NavigationProvider.tsx +152 -24
- package/src/browser/react/context.ts +11 -0
- package/src/browser/react/filter-segment-order.ts +55 -0
- package/src/browser/react/index.ts +15 -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 +30 -120
- package/src/browser/react/use-link-status.ts +6 -5
- package/src/browser/react/use-navigation.ts +44 -65
- package/src/browser/react/use-params.ts +78 -0
- package/src/browser/react/use-pathname.ts +47 -0
- package/src/browser/react/use-reverse.ts +99 -0
- package/src/browser/react/use-router.ts +83 -0
- package/src/browser/react/use-search-params.ts +56 -0
- package/src/browser/react/use-segments.ts +85 -99
- package/src/browser/response-adapter.ts +73 -0
- package/src/browser/rsc-router.tsx +246 -64
- package/src/browser/scroll-restoration.ts +127 -52
- package/src/browser/segment-reconciler.ts +243 -0
- package/src/browser/segment-structure-assert.ts +16 -0
- package/src/browser/server-action-bridge.ts +510 -603
- package/src/browser/shallow.ts +6 -1
- package/src/browser/types.ts +158 -48
- package/src/browser/validate-redirect-origin.ts +29 -0
- package/src/build/generate-manifest.ts +84 -23
- package/src/build/generate-route-types.ts +39 -828
- package/src/build/index.ts +4 -5
- package/src/build/route-trie.ts +85 -32
- 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 +418 -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 +618 -0
- package/src/build/route-types/scan-filter.ts +85 -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 +167 -307
- package/src/cache/cf/cf-cache-store.ts +573 -21
- 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 +153 -0
- package/src/cache/types.ts +72 -122
- package/src/client.rsc.tsx +6 -1
- package/src/client.tsx +118 -302
- package/src/component-utils.ts +4 -4
- package/src/components/DefaultDocument.tsx +5 -1
- package/src/context-var.ts +156 -0
- package/src/debug.ts +19 -9
- package/src/errors.ts +77 -7
- package/src/handle.ts +55 -10
- 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 +138 -21
- package/src/index.ts +206 -51
- package/src/internal-debug.ts +11 -0
- package/src/loader.rsc.ts +25 -143
- package/src/loader.ts +27 -10
- package/src/network-error-thrower.tsx +3 -1
- package/src/outlet-context.ts +1 -1
- package/src/outlet-provider.tsx +45 -0
- package/src/prerender/param-hash.ts +4 -2
- package/src/prerender/store.ts +159 -13
- package/src/prerender.ts +397 -29
- package/src/response-utils.ts +28 -0
- package/src/reverse.ts +231 -121
- package/src/root-error-boundary.tsx +41 -29
- package/src/route-content-wrapper.tsx +7 -4
- package/src/route-definition/dsl-helpers.ts +1134 -0
- package/src/route-definition/helper-factories.ts +200 -0
- package/src/route-definition/helpers-types.ts +483 -0
- package/src/route-definition/index.ts +55 -0
- package/src/route-definition/redirect.ts +101 -0
- package/src/route-definition/resolve-handler-use.ts +155 -0
- package/src/route-definition.ts +1 -1431
- package/src/route-map-builder.ts +162 -123
- package/src/route-name.ts +53 -0
- package/src/route-types.ts +66 -9
- package/src/router/content-negotiation.ts +215 -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 +418 -86
- package/src/router/intercept-resolution.ts +35 -20
- package/src/router/lazy-includes.ts +237 -0
- package/src/router/loader-resolution.ts +359 -128
- package/src/router/logging.ts +251 -0
- package/src/router/manifest.ts +98 -32
- package/src/router/match-api.ts +196 -261
- package/src/router/match-context.ts +4 -2
- package/src/router/match-handlers.ts +441 -0
- package/src/router/match-middleware/background-revalidation.ts +108 -93
- package/src/router/match-middleware/cache-lookup.ts +415 -86
- package/src/router/match-middleware/cache-store.ts +91 -29
- package/src/router/match-middleware/intercept-resolution.ts +48 -21
- package/src/router/match-middleware/segment-resolution.ts +73 -9
- package/src/router/match-pipelines.ts +10 -45
- package/src/router/match-result.ts +154 -35
- package/src/router/metrics.ts +240 -15
- package/src/router/middleware-cookies.ts +55 -0
- package/src/router/middleware-types.ts +209 -0
- package/src/router/middleware.ts +373 -371
- package/src/router/navigation-snapshot.ts +182 -0
- package/src/router/pattern-matching.ts +292 -52
- package/src/router/prerender-match.ts +502 -0
- package/src/router/preview-match.ts +98 -0
- package/src/router/request-classification.ts +310 -0
- package/src/router/revalidation.ts +152 -39
- package/src/router/route-snapshot.ts +245 -0
- package/src/router/router-context.ts +41 -21
- package/src/router/router-interfaces.ts +484 -0
- package/src/router/router-options.ts +618 -0
- package/src/router/router-registry.ts +24 -0
- package/src/router/segment-resolution/fresh.ts +756 -0
- package/src/router/segment-resolution/helpers.ts +268 -0
- package/src/router/segment-resolution/loader-cache.ts +199 -0
- package/src/router/segment-resolution/revalidation.ts +1407 -0
- package/src/router/segment-resolution/static-store.ts +67 -0
- package/src/router/segment-resolution.ts +21 -1315
- package/src/router/segment-wrappers.ts +291 -0
- package/src/router/substitute-pattern-params.ts +56 -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 +111 -39
- package/src/router/types.ts +17 -9
- package/src/router/url-params.ts +49 -0
- package/src/router.ts +642 -2011
- package/src/rsc/handler-context.ts +45 -0
- package/src/rsc/handler.ts +864 -1114
- package/src/rsc/helpers.ts +181 -19
- package/src/rsc/index.ts +0 -20
- package/src/rsc/loader-fetch.ts +229 -0
- package/src/rsc/manifest-init.ts +90 -0
- package/src/rsc/nonce.ts +14 -0
- package/src/rsc/origin-guard.ts +141 -0
- package/src/rsc/progressive-enhancement.ts +395 -0
- package/src/rsc/response-error.ts +37 -0
- package/src/rsc/response-route-handler.ts +360 -0
- package/src/rsc/rsc-rendering.ts +256 -0
- package/src/rsc/runtime-warnings.ts +42 -0
- package/src/rsc/server-action.ts +360 -0
- package/src/rsc/ssr-setup.ts +128 -0
- package/src/rsc/types.ts +52 -11
- package/src/search-params.ts +230 -0
- package/src/segment-content-promise.ts +67 -0
- package/src/segment-loader-promise.ts +122 -0
- package/src/segment-system.tsx +187 -38
- package/src/server/context.ts +333 -59
- package/src/server/cookie-store.ts +190 -0
- package/src/server/fetchable-loader-store.ts +37 -0
- package/src/server/handle-store.ts +113 -15
- package/src/server/loader-registry.ts +24 -64
- package/src/server/request-context.ts +603 -109
- package/src/server.ts +35 -155
- package/src/ssr/index.tsx +107 -30
- package/src/static-handler.ts +126 -0
- 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 +764 -0
- package/src/types/index.ts +88 -0
- package/src/types/loader-types.ts +209 -0
- package/src/types/request-scope.ts +126 -0
- package/src/types/route-config.ts +170 -0
- package/src/types/route-entry.ts +120 -0
- package/src/types/segments.ts +167 -0
- package/src/types.ts +1 -1757
- package/src/urls/include-helper.ts +207 -0
- package/src/urls/index.ts +53 -0
- package/src/urls/path-helper-types.ts +372 -0
- package/src/urls/path-helper.ts +364 -0
- package/src/urls/pattern-types.ts +107 -0
- package/src/urls/response-types.ts +108 -0
- package/src/urls/type-extraction.ts +372 -0
- package/src/urls/urls-function.ts +98 -0
- package/src/urls.ts +1 -1282
- package/src/use-loader.tsx +161 -81
- package/src/vite/debug.ts +184 -0
- package/src/vite/discovery/bundle-postprocess.ts +181 -0
- package/src/vite/discovery/discover-routers.ts +376 -0
- package/src/vite/discovery/gate-state.ts +171 -0
- package/src/vite/discovery/prerender-collection.ts +486 -0
- package/src/vite/discovery/route-types-writer.ts +258 -0
- package/src/vite/discovery/self-gen-tracking.ts +73 -0
- package/src/vite/discovery/state.ts +117 -0
- package/src/vite/discovery/virtual-module-codegen.ts +203 -0
- package/src/vite/index.ts +15 -2063
- package/src/vite/plugin-types.ts +103 -0
- package/src/vite/plugins/cjs-to-esm.ts +98 -0
- package/src/vite/plugins/client-ref-dedup.ts +131 -0
- package/src/vite/plugins/client-ref-hashing.ts +117 -0
- package/src/vite/plugins/cloudflare-protocol-loader-hook.d.mts +23 -0
- package/src/vite/plugins/cloudflare-protocol-loader-hook.mjs +76 -0
- package/src/vite/plugins/cloudflare-protocol-stub.ts +214 -0
- package/src/vite/{expose-action-id.ts → plugins/expose-action-id.ts} +107 -64
- package/src/vite/plugins/expose-id-utils.ts +299 -0
- package/src/vite/plugins/expose-ids/export-analysis.ts +296 -0
- package/src/vite/plugins/expose-ids/handler-transform.ts +209 -0
- package/src/vite/plugins/expose-ids/loader-transform.ts +74 -0
- package/src/vite/plugins/expose-ids/router-transform.ts +127 -0
- package/src/vite/plugins/expose-ids/types.ts +45 -0
- package/src/vite/plugins/expose-internal-ids.ts +816 -0
- package/src/vite/plugins/performance-tracks.ts +96 -0
- package/src/vite/plugins/refresh-cmd.ts +127 -0
- package/src/vite/plugins/use-cache-transform.ts +336 -0
- package/src/vite/plugins/version-injector.ts +109 -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 +497 -0
- package/src/vite/router-discovery.ts +1423 -0
- package/src/vite/utils/ast-handler-extract.ts +517 -0
- 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/utils/package-resolution.ts +161 -0
- package/src/vite/utils/prerender-utils.ts +222 -0
- package/src/vite/utils/shared-utils.ts +170 -0
- package/CLAUDE.md +0 -43
- 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/urls.gen.ts +0 -8
- package/src/vite/expose-handle-id.ts +0 -209
- package/src/vite/expose-loader-id.ts +0 -426
- package/src/vite/expose-location-state-id.ts +0 -177
- package/src/vite/expose-prerender-handler-id.ts +0 -429
- package/src/vite/package-resolution.ts +0 -125
- /package/src/vite/{version.d.ts → plugins/version.d.ts} +0 -0
package/src/router/match-api.ts
CHANGED
|
@@ -6,43 +6,44 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import { CacheScope, createCacheScope } from "../cache/cache-scope.js";
|
|
9
|
-
import {
|
|
10
|
-
RouteNotFoundError,
|
|
11
|
-
} from "../errors";
|
|
9
|
+
import { RouteNotFoundError } from "../errors";
|
|
12
10
|
import {
|
|
13
11
|
createErrorInfo,
|
|
14
12
|
createErrorSegment,
|
|
15
13
|
findNearestErrorBoundary as findErrorBoundary,
|
|
16
14
|
} from "./error-handling.js";
|
|
17
|
-
import {
|
|
15
|
+
import {
|
|
16
|
+
createHandlerContext,
|
|
17
|
+
stripInternalParams,
|
|
18
|
+
} from "./handler-context.js";
|
|
18
19
|
import { setupLoaderAccess } from "./loader-resolution.js";
|
|
19
20
|
import { loadManifest, clearManifestCache } from "./manifest.js";
|
|
20
21
|
import { collectRouteMiddleware } from "./middleware.js";
|
|
21
22
|
import { traverseBack } from "./pattern-matching.js";
|
|
22
23
|
import { DefaultErrorFallback } from "../default-error-boundary.js";
|
|
23
24
|
import {
|
|
24
|
-
EntryData,
|
|
25
|
-
LoaderEntry,
|
|
25
|
+
type EntryData,
|
|
26
|
+
type LoaderEntry,
|
|
26
27
|
getContext,
|
|
27
|
-
InterceptSelectorContext,
|
|
28
|
-
type MetricsStore,
|
|
28
|
+
type InterceptSelectorContext,
|
|
29
29
|
} from "../server/context";
|
|
30
|
-
import {
|
|
31
|
-
getGlobalRouteMap,
|
|
32
|
-
} from "../route-map-builder.js";
|
|
33
|
-
import type {
|
|
34
|
-
ErrorBoundaryHandler,
|
|
35
|
-
ErrorInfo,
|
|
36
|
-
HandlerContext,
|
|
37
|
-
MatchResult,
|
|
38
|
-
ResolvedSegment,
|
|
39
|
-
} from "../types";
|
|
30
|
+
import type { ErrorBoundaryHandler, ErrorInfo, MatchResult } from "../types";
|
|
40
31
|
import type { ReactNode } from "react";
|
|
41
|
-
import type { MatchContext
|
|
32
|
+
import type { MatchContext } from "./match-context.js";
|
|
42
33
|
import type { MatchApiDeps, ActionContext } from "./types.js";
|
|
43
|
-
import
|
|
44
|
-
|
|
45
|
-
|
|
34
|
+
import {
|
|
35
|
+
getRequestContext,
|
|
36
|
+
setRequestContextPrevRouteKey,
|
|
37
|
+
} from "../server/request-context.js";
|
|
38
|
+
import { isAutoGeneratedRouteName } from "../route-name.js";
|
|
39
|
+
import type { DefaultRouteName } from "../types/global-namespace.js";
|
|
40
|
+
import { debugLog, debugWarn } from "./logging.js";
|
|
41
|
+
import {
|
|
42
|
+
resolveRoute,
|
|
43
|
+
ensureFullRouteSnapshot,
|
|
44
|
+
type RouteSnapshot,
|
|
45
|
+
} from "./route-snapshot.js";
|
|
46
|
+
import { resolveNavigation } from "./navigation-snapshot.js";
|
|
46
47
|
|
|
47
48
|
/**
|
|
48
49
|
* Create match context for full requests (document/SSR).
|
|
@@ -58,61 +59,50 @@ export async function createMatchContextForFull<TEnv>(
|
|
|
58
59
|
|
|
59
60
|
const metricsStore = deps.getMetricsStore();
|
|
60
61
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
});
|
|
69
|
-
}
|
|
62
|
+
// Full renders always resolve fresh with isSSR: true because loadManifest
|
|
63
|
+
// keys its cache on isSSR and stamps Store.isSSR for downstream behavior.
|
|
64
|
+
const result = await resolveRoute<TEnv>(pathname, {
|
|
65
|
+
findMatch: (p) => deps.findMatch(p, metricsStore),
|
|
66
|
+
metricsStore,
|
|
67
|
+
isSSR: true,
|
|
68
|
+
});
|
|
70
69
|
|
|
71
|
-
if (!
|
|
70
|
+
if (!result) {
|
|
72
71
|
throw new RouteNotFoundError(`No route matched for ${pathname}`, {
|
|
73
72
|
cause: { pathname, method: request.method },
|
|
74
73
|
});
|
|
75
74
|
}
|
|
76
75
|
|
|
77
|
-
if (
|
|
76
|
+
if (result.type === "redirect") {
|
|
78
77
|
return {
|
|
79
78
|
type: "redirect",
|
|
80
|
-
redirectUrl:
|
|
79
|
+
redirectUrl: result.redirectTo + url.search,
|
|
81
80
|
};
|
|
82
81
|
}
|
|
83
82
|
|
|
84
|
-
const
|
|
85
|
-
const manifestEntry = await loadManifest(
|
|
86
|
-
matched.entry,
|
|
87
|
-
matched.routeKey,
|
|
88
|
-
pathname,
|
|
89
|
-
metricsStore,
|
|
90
|
-
true,
|
|
91
|
-
);
|
|
92
|
-
if (metricsStore) {
|
|
93
|
-
metricsStore.metrics.push({
|
|
94
|
-
label: "manifest-loading",
|
|
95
|
-
duration: performance.now() - manifestStart,
|
|
96
|
-
startTime: manifestStart - metricsStore.requestStart,
|
|
97
|
-
});
|
|
98
|
-
}
|
|
83
|
+
const snapshot = result.snapshot;
|
|
99
84
|
|
|
100
|
-
const
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
)
|
|
85
|
+
const { matched } = snapshot;
|
|
86
|
+
|
|
87
|
+
// Backward compat: downstream middleware reads matched.pt
|
|
88
|
+
if (snapshot.isPassthrough) {
|
|
89
|
+
matched.pt = true;
|
|
90
|
+
}
|
|
104
91
|
|
|
105
|
-
|
|
92
|
+
// Clean URL without internal _rsc* params for userland access
|
|
93
|
+
const cleanUrl = stripInternalParams(url);
|
|
106
94
|
|
|
107
95
|
const handlerContext = createHandlerContext(
|
|
108
96
|
matched.params,
|
|
109
97
|
request,
|
|
110
|
-
|
|
98
|
+
cleanUrl.searchParams,
|
|
111
99
|
pathname,
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
100
|
+
cleanUrl,
|
|
101
|
+
env,
|
|
102
|
+
deps.getRouteMap(),
|
|
115
103
|
matched.routeKey,
|
|
104
|
+
matched.responseType,
|
|
105
|
+
matched.pt === true,
|
|
116
106
|
);
|
|
117
107
|
|
|
118
108
|
const loaderPromises = new Map<string, Promise<any>>();
|
|
@@ -130,54 +120,47 @@ export async function createMatchContextForFull<TEnv>(
|
|
|
130
120
|
Store.metrics = metricsStore;
|
|
131
121
|
}
|
|
132
122
|
|
|
133
|
-
const entries = [...traverseBack(manifestEntry)];
|
|
134
|
-
let cacheScope: CacheScope | null = null;
|
|
135
|
-
for (const entry of entries) {
|
|
136
|
-
if (entry.cache) {
|
|
137
|
-
cacheScope = createCacheScope(entry.cache, cacheScope);
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
|
|
141
123
|
return {
|
|
142
124
|
request,
|
|
143
|
-
url,
|
|
125
|
+
url: cleanUrl,
|
|
144
126
|
pathname,
|
|
145
127
|
env,
|
|
146
|
-
bindings,
|
|
147
128
|
clientSegmentIds: [],
|
|
148
129
|
clientSegmentSet: new Set(),
|
|
149
130
|
stale: false,
|
|
150
|
-
prevUrl:
|
|
131
|
+
prevUrl: cleanUrl,
|
|
151
132
|
prevParams: {},
|
|
152
133
|
prevMatch: null,
|
|
153
134
|
matched,
|
|
154
|
-
manifestEntry,
|
|
155
|
-
entries,
|
|
135
|
+
manifestEntry: snapshot.manifestEntry,
|
|
136
|
+
entries: snapshot.entries,
|
|
156
137
|
routeKey: matched.routeKey,
|
|
157
|
-
localRouteName:
|
|
158
|
-
? matched.routeKey.split(".").pop()!
|
|
159
|
-
: matched.routeKey,
|
|
138
|
+
localRouteName: snapshot.localRouteName,
|
|
160
139
|
handlerContext,
|
|
161
140
|
loaderPromises,
|
|
162
|
-
routeMap:
|
|
141
|
+
routeMap: deps.getRouteMap(),
|
|
163
142
|
metricsStore,
|
|
164
143
|
Store,
|
|
165
144
|
interceptContextMatch: null,
|
|
166
145
|
interceptSelectorContext: {
|
|
167
|
-
from:
|
|
168
|
-
to:
|
|
146
|
+
from: cleanUrl,
|
|
147
|
+
to: cleanUrl,
|
|
169
148
|
params: matched.params,
|
|
170
149
|
request,
|
|
171
150
|
env,
|
|
172
151
|
segments: { path: [], ids: [] },
|
|
152
|
+
toRouteName:
|
|
153
|
+
matched.routeKey && !isAutoGeneratedRouteName(matched.routeKey)
|
|
154
|
+
? (matched.routeKey as DefaultRouteName)
|
|
155
|
+
: undefined,
|
|
173
156
|
},
|
|
174
157
|
isSameRouteNavigation: false,
|
|
175
158
|
interceptResult: null,
|
|
176
|
-
cacheScope,
|
|
159
|
+
cacheScope: snapshot.cacheScope,
|
|
177
160
|
isIntercept: false,
|
|
178
161
|
actionContext: undefined,
|
|
179
162
|
isAction: false,
|
|
180
|
-
routeMiddleware,
|
|
163
|
+
routeMiddleware: snapshot.routeMiddleware,
|
|
181
164
|
isFullMatch: true,
|
|
182
165
|
};
|
|
183
166
|
}
|
|
@@ -195,104 +178,106 @@ export async function createMatchContextForPartial<TEnv>(
|
|
|
195
178
|
const url = new URL(request.url);
|
|
196
179
|
const pathname = url.pathname;
|
|
197
180
|
|
|
198
|
-
const requestStartTime = performance.now();
|
|
199
181
|
const metricsStore = deps.getMetricsStore();
|
|
200
182
|
|
|
201
|
-
const
|
|
202
|
-
url.searchParams.get("_rsc_segments")?.split(",").filter(Boolean) || [];
|
|
203
|
-
const stale = url.searchParams.get("_rsc_stale") === "true";
|
|
204
|
-
const previousUrl =
|
|
205
|
-
request.headers.get("X-RSC-Router-Client-Path") ||
|
|
206
|
-
request.headers.get("Referer");
|
|
207
|
-
const interceptSourceUrl = request.headers.get(
|
|
208
|
-
"X-RSC-Router-Intercept-Source",
|
|
209
|
-
);
|
|
183
|
+
const isHmr = !!request.headers.get("X-RSC-HMR");
|
|
210
184
|
|
|
211
185
|
// HMR: clear manifest cache so stale handler references are discarded
|
|
212
|
-
if (
|
|
186
|
+
if (isHmr) {
|
|
213
187
|
clearManifestCache();
|
|
214
188
|
}
|
|
215
189
|
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
190
|
+
// Reuse the classified snapshot when available and not invalidated by HMR.
|
|
191
|
+
// classifyRequest already called resolveRoute(lite) with isSSR=false, which
|
|
192
|
+
// matches the partial path. On HMR, discard to pick up manifest changes.
|
|
193
|
+
const classifiedRoute = isHmr
|
|
194
|
+
? undefined
|
|
195
|
+
: getRequestContext()?._classifiedRoute;
|
|
196
|
+
|
|
197
|
+
// Time route matching. On the reuse path, only nav findMatch calls are new
|
|
198
|
+
// (current-route findMatch and manifest-loading were already timed during
|
|
199
|
+
// classifyRequest via its metricsStore). On the fresh path, all findMatch
|
|
200
|
+
// calls are measured together.
|
|
201
|
+
const routeMatchStart = metricsStore ? performance.now() : 0;
|
|
219
202
|
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
203
|
+
let snapshot: RouteSnapshot<TEnv>;
|
|
204
|
+
if (classifiedRoute && classifiedRoute.manifestEntry) {
|
|
205
|
+
snapshot = ensureFullRouteSnapshot(classifiedRoute);
|
|
206
|
+
} else {
|
|
207
|
+
const result = await resolveRoute<TEnv>(pathname, {
|
|
208
|
+
findMatch: (p) => deps.findMatch(p, metricsStore),
|
|
209
|
+
metricsStore,
|
|
210
|
+
isSSR: false,
|
|
211
|
+
skipRouteMatchMetric: true,
|
|
212
|
+
});
|
|
224
213
|
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
: prevMatch;
|
|
214
|
+
if (!result) {
|
|
215
|
+
throw new RouteNotFoundError(`No route matched for ${pathname}`, {
|
|
216
|
+
cause: { pathname, method: request.method },
|
|
217
|
+
});
|
|
218
|
+
}
|
|
231
219
|
|
|
232
|
-
|
|
220
|
+
if (result.type === "redirect") {
|
|
221
|
+
return null;
|
|
222
|
+
}
|
|
233
223
|
|
|
234
|
-
|
|
235
|
-
metricsStore.metrics.push({
|
|
236
|
-
label: "route-matching",
|
|
237
|
-
duration: performance.now() - routeMatchStart,
|
|
238
|
-
startTime: routeMatchStart - metricsStore.requestStart,
|
|
239
|
-
});
|
|
224
|
+
snapshot = result.snapshot;
|
|
240
225
|
}
|
|
241
226
|
|
|
242
|
-
|
|
243
|
-
throw new RouteNotFoundError(`No route matched for ${pathname}`, {
|
|
244
|
-
cause: { pathname, method: request.method, previousUrl },
|
|
245
|
-
});
|
|
246
|
-
}
|
|
227
|
+
const { matched } = snapshot;
|
|
247
228
|
|
|
248
|
-
|
|
249
|
-
|
|
229
|
+
// Backward compat: downstream middleware reads matched.pt
|
|
230
|
+
if (snapshot.isPassthrough) {
|
|
231
|
+
matched.pt = true;
|
|
250
232
|
}
|
|
251
233
|
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
234
|
+
// Navigation state (prev + intercept-source findMatch calls)
|
|
235
|
+
const nav = resolveNavigation(request, url, matched.routeKey, {
|
|
236
|
+
findMatch: deps.findMatch,
|
|
237
|
+
});
|
|
238
|
+
if (!nav) {
|
|
239
|
+
return null;
|
|
256
240
|
}
|
|
257
241
|
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
pathname,
|
|
263
|
-
metricsStore,
|
|
264
|
-
false,
|
|
265
|
-
);
|
|
242
|
+
// Push route-matching metric. On the fresh path this covers all findMatch
|
|
243
|
+
// calls (current + prev + intercept-source). On the reuse path, current-route
|
|
244
|
+
// findMatch was already timed during classification, so this only covers
|
|
245
|
+
// the nav lookups (prev + intercept-source).
|
|
266
246
|
if (metricsStore) {
|
|
247
|
+
const isReuse = !!classifiedRoute;
|
|
267
248
|
metricsStore.metrics.push({
|
|
268
|
-
label: "
|
|
269
|
-
duration: performance.now() -
|
|
270
|
-
startTime:
|
|
249
|
+
label: isReuse ? "route-matching:nav" : "route-matching",
|
|
250
|
+
duration: performance.now() - routeMatchStart,
|
|
251
|
+
startTime: routeMatchStart - metricsStore.requestStart,
|
|
271
252
|
});
|
|
272
253
|
}
|
|
273
254
|
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
255
|
+
if (nav.prevMatch && nav.prevMatch.entry !== matched.entry && !matched.pr) {
|
|
256
|
+
debugLog("matchPartial", "route group changed", {
|
|
257
|
+
from: nav.prevMatch.routeKey,
|
|
258
|
+
to: matched.routeKey,
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
// Clean URL without internal _rsc* params for userland access
|
|
263
|
+
const cleanUrl = stripInternalParams(url);
|
|
278
264
|
|
|
279
|
-
const bindings = (env as any)?.Bindings ?? env;
|
|
280
265
|
const handlerContext = createHandlerContext(
|
|
281
266
|
matched.params,
|
|
282
267
|
request,
|
|
283
|
-
|
|
268
|
+
cleanUrl.searchParams,
|
|
284
269
|
pathname,
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
270
|
+
cleanUrl,
|
|
271
|
+
env,
|
|
272
|
+
deps.getRouteMap(),
|
|
288
273
|
matched.routeKey,
|
|
274
|
+
matched.responseType,
|
|
275
|
+
matched.pt === true,
|
|
289
276
|
);
|
|
290
277
|
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
Array.from(clientSegmentSet),
|
|
295
|
-
);
|
|
278
|
+
debugLog("matchPartial", "client segments", {
|
|
279
|
+
segments: Array.from(nav.clientSegmentSet),
|
|
280
|
+
});
|
|
296
281
|
|
|
297
282
|
const loaderPromises = new Map<string, Promise<any>>();
|
|
298
283
|
setupLoaderAccess(handlerContext, loaderPromises);
|
|
@@ -309,116 +294,112 @@ export async function createMatchContextForPartial<TEnv>(
|
|
|
309
294
|
Store.metrics = metricsStore;
|
|
310
295
|
}
|
|
311
296
|
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
console.log(` - Intercept source: ${interceptSourceUrl}`);
|
|
321
|
-
console.log(` - Context match: ${interceptContextMatch?.routeKey}`);
|
|
322
|
-
console.log(` - Current route: ${matched.routeKey}`);
|
|
323
|
-
console.log(` - Same route navigation: ${isSameRouteNavigation}`);
|
|
297
|
+
if (nav.hasInterceptSource) {
|
|
298
|
+
debugLog("matchPartial.intercept", "intercept context detected", {
|
|
299
|
+
currentUrl: pathname,
|
|
300
|
+
interceptSource: nav.interceptContextUrl.href,
|
|
301
|
+
contextRoute: nav.interceptContextMatch?.routeKey,
|
|
302
|
+
currentRoute: matched.routeKey,
|
|
303
|
+
sameRouteNavigation: nav.isSameRouteNavigation,
|
|
304
|
+
});
|
|
324
305
|
}
|
|
325
306
|
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
307
|
+
// Store previous route key on the request context for revalidation
|
|
308
|
+
// fromRouteName. Uses effectiveFromMatch so intercept-source navigations
|
|
309
|
+
// see the intercept origin route, not the plain previous URL route.
|
|
310
|
+
setRequestContextPrevRouteKey(nav.effectiveFromMatch?.routeKey);
|
|
329
311
|
|
|
330
|
-
const filteredSegmentIds = clientSegmentIds.filter((id) => {
|
|
331
|
-
if (id.includes(".@")) return false;
|
|
332
|
-
if (/D\d+\./.test(id)) return false;
|
|
333
|
-
return true;
|
|
334
|
-
});
|
|
335
312
|
const interceptSelectorContext: InterceptSelectorContext = {
|
|
336
|
-
from:
|
|
337
|
-
to:
|
|
313
|
+
from: nav.effectiveFromUrl,
|
|
314
|
+
to: cleanUrl,
|
|
338
315
|
params: matched.params,
|
|
339
316
|
request,
|
|
340
317
|
env,
|
|
341
318
|
segments: {
|
|
342
|
-
path:
|
|
343
|
-
ids: filteredSegmentIds,
|
|
319
|
+
path: nav.effectiveFromUrl.pathname.split("/").filter(Boolean),
|
|
320
|
+
ids: nav.filteredSegmentIds,
|
|
344
321
|
},
|
|
322
|
+
fromRouteName:
|
|
323
|
+
nav.effectiveFromMatch?.routeKey &&
|
|
324
|
+
!isAutoGeneratedRouteName(nav.effectiveFromMatch.routeKey)
|
|
325
|
+
? (nav.effectiveFromMatch.routeKey as DefaultRouteName)
|
|
326
|
+
: undefined,
|
|
327
|
+
toRouteName:
|
|
328
|
+
matched.routeKey && !isAutoGeneratedRouteName(matched.routeKey)
|
|
329
|
+
? (matched.routeKey as DefaultRouteName)
|
|
330
|
+
: undefined,
|
|
345
331
|
};
|
|
346
332
|
const isAction = !!actionContext;
|
|
347
333
|
|
|
348
|
-
const clientHasInterceptSegments = [...clientSegmentSet].some((id) =>
|
|
334
|
+
const clientHasInterceptSegments = [...nav.clientSegmentSet].some((id) =>
|
|
349
335
|
id.includes(".@"),
|
|
350
336
|
);
|
|
351
337
|
const skipInterceptForAction = isAction && !clientHasInterceptSegments;
|
|
352
338
|
const interceptResult =
|
|
353
|
-
isSameRouteNavigation || skipInterceptForAction
|
|
339
|
+
nav.isSameRouteNavigation || skipInterceptForAction
|
|
354
340
|
? null
|
|
355
341
|
: findInterceptForRoute(
|
|
356
342
|
matched.routeKey,
|
|
357
|
-
manifestEntry.parent,
|
|
343
|
+
snapshot.manifestEntry.parent,
|
|
358
344
|
interceptSelectorContext,
|
|
359
345
|
isAction,
|
|
360
346
|
) ||
|
|
361
|
-
(localRouteName !== matched.routeKey
|
|
347
|
+
(snapshot.localRouteName !== matched.routeKey
|
|
362
348
|
? findInterceptForRoute(
|
|
363
|
-
localRouteName,
|
|
364
|
-
manifestEntry.parent,
|
|
349
|
+
snapshot.localRouteName,
|
|
350
|
+
snapshot.manifestEntry.parent,
|
|
365
351
|
interceptSelectorContext,
|
|
366
352
|
isAction,
|
|
367
353
|
)
|
|
368
354
|
: null);
|
|
369
355
|
|
|
356
|
+
// Make a mutable copy of clientSegmentSet so we can delete entries
|
|
357
|
+
// for same-route navigation forcing
|
|
358
|
+
const clientSegmentSet = new Set(nav.clientSegmentSet);
|
|
359
|
+
|
|
370
360
|
if (
|
|
371
|
-
isSameRouteNavigation &&
|
|
372
|
-
manifestEntry.type === "route" &&
|
|
373
|
-
|
|
361
|
+
nav.isSameRouteNavigation &&
|
|
362
|
+
snapshot.manifestEntry.type === "route" &&
|
|
363
|
+
nav.hasInterceptSource
|
|
374
364
|
) {
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
);
|
|
378
|
-
clientSegmentSet.delete(manifestEntry.shortCode);
|
|
379
|
-
}
|
|
380
|
-
|
|
381
|
-
const entries = [...traverseBack(manifestEntry)];
|
|
382
|
-
let cacheScope: CacheScope | null = null;
|
|
383
|
-
for (const entry of entries) {
|
|
384
|
-
if (entry.cache) {
|
|
385
|
-
cacheScope = createCacheScope(entry.cache, cacheScope);
|
|
386
|
-
}
|
|
365
|
+
debugLog("matchPartial.intercept", "forcing route segment render", {
|
|
366
|
+
segmentId: snapshot.manifestEntry.shortCode,
|
|
367
|
+
});
|
|
368
|
+
clientSegmentSet.delete(snapshot.manifestEntry.shortCode);
|
|
387
369
|
}
|
|
388
370
|
|
|
389
371
|
const isIntercept = !!interceptResult;
|
|
390
372
|
|
|
391
373
|
return {
|
|
392
374
|
request,
|
|
393
|
-
url,
|
|
375
|
+
url: cleanUrl,
|
|
394
376
|
pathname,
|
|
395
377
|
env,
|
|
396
|
-
|
|
397
|
-
clientSegmentIds,
|
|
378
|
+
clientSegmentIds: nav.clientSegmentIds,
|
|
398
379
|
clientSegmentSet,
|
|
399
|
-
stale,
|
|
400
|
-
prevUrl,
|
|
401
|
-
prevParams,
|
|
402
|
-
prevMatch,
|
|
380
|
+
stale: nav.stale,
|
|
381
|
+
prevUrl: nav.prevUrl,
|
|
382
|
+
prevParams: nav.prevParams,
|
|
383
|
+
prevMatch: nav.prevMatch,
|
|
403
384
|
matched,
|
|
404
|
-
manifestEntry,
|
|
405
|
-
entries,
|
|
385
|
+
manifestEntry: snapshot.manifestEntry,
|
|
386
|
+
entries: snapshot.entries,
|
|
406
387
|
routeKey: matched.routeKey,
|
|
407
|
-
localRouteName,
|
|
388
|
+
localRouteName: snapshot.localRouteName,
|
|
408
389
|
handlerContext,
|
|
409
390
|
loaderPromises,
|
|
410
|
-
routeMap:
|
|
391
|
+
routeMap: deps.getRouteMap(),
|
|
411
392
|
metricsStore,
|
|
412
393
|
Store,
|
|
413
|
-
interceptContextMatch,
|
|
394
|
+
interceptContextMatch: nav.interceptContextMatch,
|
|
414
395
|
interceptSelectorContext,
|
|
415
|
-
isSameRouteNavigation,
|
|
396
|
+
isSameRouteNavigation: nav.isSameRouteNavigation,
|
|
416
397
|
interceptResult,
|
|
417
|
-
cacheScope,
|
|
398
|
+
cacheScope: snapshot.cacheScope,
|
|
418
399
|
isIntercept,
|
|
419
400
|
actionContext,
|
|
420
401
|
isAction,
|
|
421
|
-
routeMiddleware,
|
|
402
|
+
routeMiddleware: snapshot.routeMiddleware,
|
|
422
403
|
isFullMatch: false,
|
|
423
404
|
};
|
|
424
405
|
}
|
|
@@ -437,11 +418,11 @@ export async function matchError<TEnv>(
|
|
|
437
418
|
const url = new URL(request.url);
|
|
438
419
|
const pathname = url.pathname;
|
|
439
420
|
|
|
440
|
-
|
|
421
|
+
debugLog("matchError", "matching error", { pathname });
|
|
441
422
|
|
|
442
423
|
const matched = deps.findMatch(pathname);
|
|
443
424
|
if (!matched) {
|
|
444
|
-
|
|
425
|
+
debugWarn("matchError", "no route matched", { pathname });
|
|
445
426
|
return null;
|
|
446
427
|
}
|
|
447
428
|
|
|
@@ -545,10 +526,7 @@ export async function matchError<TEnv>(
|
|
|
545
526
|
|
|
546
527
|
const reqCtx = getRequestContext();
|
|
547
528
|
if (reqCtx) {
|
|
548
|
-
reqCtx.
|
|
549
|
-
status: 500,
|
|
550
|
-
headers: reqCtx.res.headers,
|
|
551
|
-
});
|
|
529
|
+
reqCtx._setStatus(500);
|
|
552
530
|
}
|
|
553
531
|
|
|
554
532
|
const effectiveFallback = fallback || DefaultErrorFallback;
|
|
@@ -560,62 +538,19 @@ export async function matchError<TEnv>(
|
|
|
560
538
|
);
|
|
561
539
|
|
|
562
540
|
if (useDefaultFallback) {
|
|
563
|
-
|
|
564
|
-
`[Router.matchError] Using default error boundary (no user-defined boundary found)`,
|
|
565
|
-
);
|
|
541
|
+
debugLog("matchError", "using default error boundary");
|
|
566
542
|
}
|
|
567
543
|
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
544
|
+
debugLog("matchError", "resolved boundary", {
|
|
545
|
+
boundarySegmentId: boundaryEntry.shortCode,
|
|
546
|
+
outletSegmentId: outletEntry.shortCode,
|
|
547
|
+
});
|
|
571
548
|
|
|
572
549
|
return {
|
|
573
550
|
segments: [errorSegment],
|
|
574
551
|
matched: matchedIds,
|
|
575
552
|
diff: [errorSegment.id],
|
|
553
|
+
resolvedIds: [errorSegment.id],
|
|
576
554
|
params: matched.params,
|
|
577
555
|
};
|
|
578
556
|
}
|
|
579
|
-
|
|
580
|
-
/**
|
|
581
|
-
* Preview match - returns route middleware without segment resolution.
|
|
582
|
-
*/
|
|
583
|
-
export async function previewMatch<TEnv>(
|
|
584
|
-
request: Request,
|
|
585
|
-
context: TEnv,
|
|
586
|
-
deps: MatchApiDeps<TEnv>,
|
|
587
|
-
): Promise<{
|
|
588
|
-
routeMiddleware?: Array<{
|
|
589
|
-
handler: import("./middleware.js").MiddlewareFn;
|
|
590
|
-
params: Record<string, string>;
|
|
591
|
-
}>;
|
|
592
|
-
} | null> {
|
|
593
|
-
const url = new URL(request.url);
|
|
594
|
-
const pathname = url.pathname;
|
|
595
|
-
|
|
596
|
-
const matched = deps.findMatch(pathname);
|
|
597
|
-
if (!matched) {
|
|
598
|
-
return null;
|
|
599
|
-
}
|
|
600
|
-
|
|
601
|
-
if (matched.redirectTo) {
|
|
602
|
-
return { routeMiddleware: undefined };
|
|
603
|
-
}
|
|
604
|
-
|
|
605
|
-
const manifestEntry = await loadManifest(
|
|
606
|
-
matched.entry,
|
|
607
|
-
matched.routeKey,
|
|
608
|
-
pathname,
|
|
609
|
-
undefined,
|
|
610
|
-
false,
|
|
611
|
-
);
|
|
612
|
-
|
|
613
|
-
const routeMiddleware = collectRouteMiddleware(
|
|
614
|
-
traverseBack(manifestEntry),
|
|
615
|
-
matched.params,
|
|
616
|
-
);
|
|
617
|
-
|
|
618
|
-
return {
|
|
619
|
-
routeMiddleware: routeMiddleware.length > 0 ? routeMiddleware : undefined,
|
|
620
|
-
};
|
|
621
|
-
}
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
* - request, url, pathname: The incoming HTTP request
|
|
46
46
|
*
|
|
47
47
|
* Environment:
|
|
48
|
-
* - env
|
|
48
|
+
* - env: Server environment (Cloudflare bindings, etc.)
|
|
49
49
|
*
|
|
50
50
|
* Client State (from RSC request headers):
|
|
51
51
|
* - clientSegmentIds: Segments the client currently has
|
|
@@ -140,7 +140,6 @@ export interface MatchContext<TEnv = any> {
|
|
|
140
140
|
|
|
141
141
|
// Environment
|
|
142
142
|
env: TEnv;
|
|
143
|
-
bindings: TEnv;
|
|
144
143
|
|
|
145
144
|
// Client state
|
|
146
145
|
clientSegmentIds: string[];
|
|
@@ -211,6 +210,9 @@ export interface MatchPipelineState {
|
|
|
211
210
|
// Whether cache should be revalidated (SWR)
|
|
212
211
|
shouldRevalidate?: boolean;
|
|
213
212
|
|
|
213
|
+
// Source of cache hit ("runtime" or "prerender")
|
|
214
|
+
cacheSource?: "runtime" | "prerender";
|
|
215
|
+
|
|
214
216
|
// Resolved segments from pipeline
|
|
215
217
|
segments: ResolvedSegment[];
|
|
216
218
|
matchedIds: string[];
|