@rangojs/router 0.0.0-experimental.9c9afef3 → 0.0.0-experimental.a014d2b7
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 +8 -0
- package/README.md +245 -49
- package/dist/bin/rango.js +440 -133
- package/dist/testing/vitest.js +82 -0
- package/dist/vite/index.js +3373 -1176
- package/dist/vite/index.js.bak +5448 -0
- package/dist/vite/plugins/cloudflare-protocol-loader-hook.mjs +76 -0
- package/package.json +68 -14
- package/skills/api-client/SKILL.md +211 -0
- package/skills/breadcrumbs/SKILL.md +64 -2
- package/skills/bundle-analysis/SKILL.md +159 -0
- package/skills/cache-guide/SKILL.md +224 -32
- package/skills/caching/SKILL.md +279 -17
- package/skills/composability/SKILL.md +27 -3
- package/skills/css/SKILL.md +76 -0
- package/skills/debug-manifest/SKILL.md +4 -2
- package/skills/document-cache/SKILL.md +78 -55
- package/skills/handler-use/SKILL.md +364 -0
- package/skills/hooks/SKILL.md +250 -30
- package/skills/host-router/SKILL.md +83 -23
- package/skills/i18n/SKILL.md +276 -0
- package/skills/intercept/SKILL.md +87 -18
- package/skills/layout/SKILL.md +35 -9
- package/skills/links/SKILL.md +249 -17
- package/skills/loader/SKILL.md +235 -9
- package/skills/middleware/SKILL.md +52 -13
- package/skills/migrate-nextjs/SKILL.md +584 -0
- package/skills/migrate-react-router/SKILL.md +771 -0
- package/skills/mime-routes/SKILL.md +28 -1
- package/skills/observability/SKILL.md +172 -0
- package/skills/parallel/SKILL.md +77 -7
- package/skills/prerender/SKILL.md +172 -125
- package/skills/rango/SKILL.md +251 -22
- package/skills/react-compiler/SKILL.md +168 -0
- package/skills/response-routes/SKILL.md +123 -48
- package/skills/route/SKILL.md +70 -5
- package/skills/router-setup/SKILL.md +65 -8
- package/skills/scripts/SKILL.md +179 -0
- package/skills/server-actions/SKILL.md +775 -0
- package/skills/streams-and-websockets/SKILL.md +283 -0
- package/skills/tailwind/SKILL.md +27 -3
- package/skills/testing/SKILL.md +130 -0
- package/skills/testing/bindings.md +103 -0
- package/skills/testing/cache-prerender.md +127 -0
- package/skills/testing/client-components.md +124 -0
- package/skills/testing/e2e-parity.md +125 -0
- package/skills/testing/flight.md +91 -0
- package/skills/testing/handles.md +129 -0
- package/skills/testing/loader.md +128 -0
- package/skills/testing/middleware.md +99 -0
- package/skills/testing/render-handler.md +122 -0
- package/skills/testing/response-routes.md +95 -0
- package/skills/testing/reverse-and-types.md +84 -0
- package/skills/testing/server-actions.md +107 -0
- package/skills/testing/server-tree.md +128 -0
- package/skills/testing/setup.md +123 -0
- package/skills/typesafety/SKILL.md +322 -29
- package/skills/use-cache/SKILL.md +57 -14
- package/skills/view-transitions/SKILL.md +337 -0
- package/src/__augment-tests__/augment.ts +81 -0
- package/src/__augment-tests__/augmented.check.ts +116 -0
- package/src/__internal.ts +1 -66
- package/src/browser/action-coordinator.ts +53 -36
- package/src/browser/action-fence.ts +47 -0
- package/src/browser/app-shell.ts +39 -0
- package/src/browser/app-version.ts +14 -0
- package/src/browser/connection-warmup.ts +134 -0
- package/src/browser/cookie-name.ts +140 -0
- package/src/browser/event-controller.ts +192 -150
- package/src/browser/history-state.ts +21 -0
- package/src/browser/index.ts +3 -3
- package/src/browser/invalidate-client-cache.ts +52 -0
- package/src/browser/navigation-bridge.ts +131 -30
- package/src/browser/navigation-client.ts +186 -100
- package/src/browser/navigation-store-handle.ts +38 -0
- package/src/browser/navigation-store.ts +157 -74
- package/src/browser/navigation-transaction.ts +9 -59
- package/src/browser/network-error-handler.ts +34 -7
- package/src/browser/partial-update.ts +165 -112
- package/src/browser/prefetch/cache.ts +205 -62
- package/src/browser/prefetch/fetch.ts +347 -39
- package/src/browser/prefetch/queue.ts +42 -8
- package/src/browser/rango-state.ts +158 -76
- package/src/browser/react/Link.tsx +102 -15
- package/src/browser/react/NavigationProvider.tsx +295 -119
- package/src/browser/react/ScrollRestoration.tsx +10 -6
- package/src/browser/react/context.ts +7 -2
- package/src/browser/react/deferred-handle-resolution.ts +75 -0
- package/src/browser/react/filter-segment-order.ts +66 -7
- package/src/browser/react/index.ts +0 -48
- package/src/browser/react/location-state-shared.ts +178 -8
- package/src/browser/react/location-state.ts +39 -14
- package/src/browser/react/use-action.ts +6 -15
- package/src/browser/react/use-handle.ts +23 -69
- package/src/browser/react/use-href.tsx +8 -1
- package/src/browser/react/use-link-status.ts +33 -8
- package/src/browser/react/use-navigation.ts +32 -7
- package/src/browser/react/use-params.ts +20 -10
- package/src/browser/react/use-reverse.ts +106 -0
- package/src/browser/react/use-router.ts +46 -11
- package/src/browser/react/use-search-params.ts +0 -5
- package/src/browser/react/use-segments.ts +11 -21
- package/src/browser/response-adapter.ts +99 -8
- package/src/browser/rsc-router.tsx +114 -24
- package/src/browser/scroll-restoration.ts +37 -22
- package/src/browser/segment-reconciler.ts +36 -14
- package/src/browser/segment-structure-assert.ts +2 -2
- package/src/browser/server-action-bridge.ts +222 -72
- package/src/browser/types.ts +102 -12
- package/src/browser/validate-redirect-origin.ts +43 -16
- package/src/build/collect-fallback-refs.ts +107 -0
- package/src/build/generate-manifest.ts +65 -40
- package/src/build/generate-route-types.ts +5 -1
- package/src/build/index.ts +8 -2
- package/src/build/prefix-tree-utils.ts +123 -0
- package/src/build/route-trie.ts +165 -36
- package/src/build/route-types/ast-route-extraction.ts +15 -8
- package/src/build/route-types/codegen.ts +16 -5
- package/src/build/route-types/include-resolution.ts +125 -24
- package/src/build/route-types/param-extraction.ts +6 -3
- package/src/build/route-types/per-module-writer.ts +22 -6
- package/src/build/route-types/router-processing.ts +260 -94
- package/src/build/route-types/scan-filter.ts +9 -2
- package/src/build/route-types/source-scan.ts +216 -0
- package/src/build/runtime-discovery.ts +9 -20
- package/src/cache/cache-error.ts +104 -0
- package/src/cache/cache-key-utils.ts +29 -13
- package/src/cache/cache-policy.ts +108 -34
- package/src/cache/cache-runtime.ts +224 -41
- package/src/cache/cache-scope.ts +188 -82
- package/src/cache/cache-tag.ts +103 -0
- package/src/cache/cf/cf-base64.ts +33 -0
- package/src/cache/cf/cf-cache-constants.ts +127 -0
- package/src/cache/cf/cf-cache-store.ts +1989 -378
- package/src/cache/cf/cf-cache-types.ts +349 -0
- package/src/cache/cf/cf-kv-utils.ts +46 -0
- package/src/cache/cf/cf-tag-marker-memo.ts +105 -0
- package/src/cache/cf/index.ts +6 -16
- package/src/cache/document-cache.ts +89 -21
- package/src/cache/handle-snapshot.ts +70 -0
- package/src/cache/index.ts +10 -20
- package/src/cache/memory-segment-store.ts +136 -37
- package/src/cache/profile-registry.ts +46 -31
- package/src/cache/read-through-swr.ts +56 -12
- package/src/cache/segment-codec.ts +9 -17
- package/src/cache/tag-invalidation.ts +230 -0
- package/src/cache/types.ts +37 -100
- package/src/client.rsc.tsx +44 -21
- package/src/client.tsx +119 -290
- package/src/cloudflare/index.ts +11 -0
- package/src/cloudflare/tracing.ts +109 -0
- package/src/component-utils.ts +19 -0
- package/src/components/DefaultDocument.tsx +8 -2
- package/src/context-var.ts +18 -6
- package/src/decode-loader-results.ts +52 -0
- package/src/defer.ts +196 -0
- package/src/deps/ssr.ts +0 -1
- package/src/encode-kv.ts +49 -0
- package/src/errors.ts +30 -4
- package/src/escape-script.ts +52 -0
- package/src/handle.ts +70 -22
- package/src/handles/MetaTags.tsx +62 -19
- package/src/handles/Scripts.tsx +183 -0
- package/src/handles/breadcrumbs.ts +37 -8
- package/src/handles/is-thenable.ts +19 -0
- package/src/handles/meta.ts +51 -40
- package/src/handles/script.ts +244 -0
- package/src/host/cookie-handler.ts +9 -60
- package/src/host/errors.ts +0 -24
- package/src/host/index.ts +8 -2
- package/src/host/pattern-matcher.ts +23 -52
- package/src/host/router.ts +107 -99
- package/src/host/testing.ts +40 -27
- package/src/host/types.ts +37 -4
- package/src/host/utils.ts +1 -1
- package/src/href-client.ts +137 -22
- package/src/index.rsc.ts +99 -13
- package/src/index.ts +139 -19
- package/src/internal-debug.ts +11 -10
- package/src/loader-store.ts +500 -0
- package/src/loader.rsc.ts +20 -13
- package/src/loader.ts +12 -11
- package/src/missing-id-error.ts +68 -0
- package/src/outlet-context.ts +1 -1
- package/src/outlet-provider.tsx +1 -5
- package/src/prerender/param-hash.ts +16 -16
- package/src/prerender/store.ts +37 -41
- package/src/prerender.ts +198 -82
- package/src/redirect-origin.ts +100 -0
- package/src/regex-escape.ts +8 -0
- package/src/render-error-thrower.tsx +20 -0
- package/src/response-utils.ts +62 -0
- package/src/reverse.ts +65 -15
- package/src/root-error-boundary.tsx +1 -19
- package/src/route-content-wrapper.tsx +19 -77
- package/src/route-definition/dsl-helpers.ts +461 -304
- package/src/route-definition/helper-factories.ts +28 -140
- package/src/route-definition/helpers-types.ts +143 -69
- package/src/route-definition/index.ts +4 -2
- package/src/route-definition/redirect.ts +51 -10
- package/src/route-definition/resolve-handler-use.ts +160 -0
- package/src/route-definition/use-item-types.ts +29 -0
- package/src/route-map-builder.ts +0 -16
- package/src/route-types.ts +37 -46
- package/src/router/basename.ts +14 -0
- package/src/router/content-negotiation.ts +164 -17
- package/src/router/error-handling.ts +45 -18
- package/src/router/find-match.ts +44 -23
- package/src/router/handler-context.ts +52 -31
- package/src/router/instrument.ts +350 -0
- package/src/router/intercept-resolution.ts +48 -24
- package/src/router/lazy-includes.ts +15 -52
- package/src/router/loader-resolution.ts +268 -56
- package/src/router/logging.ts +0 -6
- package/src/router/manifest.ts +40 -42
- package/src/router/match-api.ts +124 -204
- package/src/router/match-context.ts +0 -22
- package/src/router/match-handlers.ts +58 -58
- package/src/router/match-middleware/background-revalidation.ts +40 -24
- package/src/router/match-middleware/cache-lookup.ts +170 -276
- package/src/router/match-middleware/cache-store.ts +64 -52
- package/src/router/match-middleware/intercept-resolution.ts +0 -22
- package/src/router/match-middleware/segment-resolution.ts +45 -14
- package/src/router/match-pipelines.ts +1 -42
- package/src/router/match-result.ts +87 -39
- package/src/router/metrics.ts +0 -34
- package/src/router/middleware-types.ts +7 -140
- package/src/router/middleware.ts +266 -169
- package/src/router/navigation-snapshot.ts +131 -0
- package/src/router/params-util.ts +23 -0
- package/src/router/pattern-matching.ts +132 -90
- package/src/router/prefetch-cache-ttl.ts +51 -0
- package/src/router/prerender-match.ts +195 -56
- package/src/router/preview-match.ts +32 -102
- package/src/router/request-classification.ts +276 -0
- package/src/router/revalidation.ts +123 -73
- package/src/router/route-snapshot.ts +244 -0
- package/src/router/router-context.ts +3 -28
- package/src/router/router-interfaces.ts +115 -35
- package/src/router/router-options.ts +172 -15
- package/src/router/router-registry.ts +2 -5
- package/src/router/segment-resolution/fresh.ts +162 -84
- package/src/router/segment-resolution/helpers.ts +86 -6
- package/src/router/segment-resolution/loader-cache.ts +76 -39
- package/src/router/segment-resolution/revalidation.ts +351 -321
- package/src/router/segment-resolution/static-store.ts +19 -5
- package/src/router/segment-resolution/streamed-handler-telemetry.ts +52 -0
- package/src/router/segment-resolution/view-transition-default.ts +56 -0
- package/src/router/segment-resolution.ts +5 -1
- package/src/router/segment-wrappers.ts +6 -5
- package/src/router/state-cookie-name.ts +33 -0
- package/src/router/substitute-pattern-params.ts +56 -0
- package/src/router/telemetry-otel.ts +161 -199
- package/src/router/telemetry.ts +96 -19
- package/src/router/timeout.ts +0 -20
- package/src/router/tracing.ts +206 -0
- package/src/router/trie-matching.ts +163 -59
- package/src/router/types.ts +9 -63
- package/src/router/url-params.ts +44 -0
- package/src/router.ts +157 -54
- package/src/rsc/handler-context.ts +3 -2
- package/src/rsc/handler.ts +655 -529
- package/src/rsc/helpers.ts +168 -46
- package/src/rsc/index.ts +2 -5
- package/src/rsc/json-route-result.ts +38 -0
- package/src/rsc/loader-fetch.ts +122 -31
- package/src/rsc/manifest-init.ts +33 -42
- package/src/rsc/origin-guard.ts +39 -25
- package/src/rsc/progressive-enhancement.ts +131 -14
- package/src/rsc/redirect-guard.ts +99 -0
- package/src/rsc/response-cache-serve.ts +238 -0
- package/src/rsc/response-error.ts +79 -12
- package/src/rsc/response-route-handler.ts +99 -189
- package/src/rsc/rsc-rendering.ts +109 -74
- package/src/rsc/runtime-warnings.ts +23 -10
- package/src/rsc/server-action.ts +287 -115
- package/src/rsc/ssr-setup.ts +18 -2
- package/src/rsc/transition-gate.ts +89 -0
- package/src/rsc/types.ts +29 -9
- package/src/runtime-env.ts +18 -0
- package/src/search-params.ts +35 -30
- package/src/segment-content-promise.ts +67 -0
- package/src/segment-loader-promise.ts +149 -0
- package/src/segment-system.tsx +236 -202
- package/src/serialize.ts +243 -0
- package/src/server/context.ts +224 -52
- package/src/server/cookie-parse.ts +32 -0
- package/src/server/cookie-store.ts +80 -5
- package/src/server/handle-store.ts +40 -38
- package/src/server/loader-registry.ts +38 -46
- package/src/server/request-context.ts +401 -173
- package/src/ssr/index.tsx +24 -16
- package/src/static-handler.ts +27 -18
- package/src/testing/cache-status.ts +162 -0
- package/src/testing/collect-handle.ts +40 -0
- package/src/testing/dispatch.ts +701 -0
- package/src/testing/dom.entry.ts +22 -0
- package/src/testing/e2e/fixture.ts +188 -0
- package/src/testing/e2e/index.ts +128 -0
- package/src/testing/e2e/matchers.ts +35 -0
- package/src/testing/e2e/page-helpers.ts +272 -0
- package/src/testing/e2e/parity.ts +387 -0
- package/src/testing/e2e/server.ts +195 -0
- package/src/testing/flight-matchers.ts +97 -0
- package/src/testing/flight-normalize.ts +11 -0
- package/src/testing/flight-runtime.d.ts +57 -0
- package/src/testing/flight-tree.ts +682 -0
- package/src/testing/flight.entry.ts +52 -0
- package/src/testing/flight.ts +257 -0
- package/src/testing/generated-routes.ts +183 -0
- package/src/testing/index.ts +105 -0
- package/src/testing/internal/context.ts +371 -0
- package/src/testing/internal/flight-client-globals.ts +30 -0
- package/src/testing/internal/seed-vars.ts +54 -0
- package/src/testing/render-handler.ts +357 -0
- package/src/testing/render-route.tsx +581 -0
- package/src/testing/run-loader.ts +385 -0
- package/src/testing/run-middleware.ts +205 -0
- package/src/testing/run-transition-when.ts +164 -0
- package/src/testing/vitest-stubs/cloudflare-email.ts +9 -0
- package/src/testing/vitest-stubs/cloudflare-workers.ts +21 -0
- package/src/testing/vitest-stubs/plugin-rsc.ts +16 -0
- package/src/testing/vitest-stubs/version.ts +5 -0
- package/src/testing/vitest.ts +305 -0
- package/src/theme/ThemeProvider.tsx +20 -58
- package/src/theme/ThemeScript.tsx +7 -9
- package/src/theme/constants.ts +52 -13
- package/src/theme/index.ts +0 -7
- package/src/theme/theme-context.ts +1 -5
- package/src/theme/theme-script.ts +22 -21
- package/src/theme/use-theme.ts +0 -3
- package/src/types/boundaries.ts +0 -35
- package/src/types/cache-types.ts +17 -8
- package/src/types/error-types.ts +30 -90
- package/src/types/global-namespace.ts +54 -41
- package/src/types/handler-context.ts +125 -71
- package/src/types/index.ts +3 -10
- package/src/types/loader-types.ts +40 -11
- package/src/types/request-scope.ts +112 -0
- package/src/types/route-config.ts +6 -50
- package/src/types/route-entry.ts +12 -7
- package/src/types/segments.ts +136 -15
- package/src/urls/include-helper.ts +33 -70
- package/src/urls/index.ts +1 -11
- package/src/urls/path-helper-types.ts +68 -18
- package/src/urls/path-helper.ts +57 -111
- package/src/urls/pattern-types.ts +48 -19
- package/src/urls/response-types.ts +25 -22
- package/src/urls/type-extraction.ts +58 -139
- package/src/urls/urls-function.ts +1 -19
- package/src/use-loader.tsx +346 -89
- package/src/vite/debug.ts +185 -0
- package/src/vite/discovery/bundle-postprocess.ts +36 -38
- package/src/vite/discovery/discover-routers.ts +130 -85
- package/src/vite/discovery/discovery-errors.ts +194 -0
- package/src/vite/discovery/gate-state.ts +171 -0
- package/src/vite/discovery/prerender-collection.ts +214 -132
- package/src/vite/discovery/route-types-writer.ts +40 -84
- package/src/vite/discovery/self-gen-tracking.ts +27 -1
- package/src/vite/discovery/state.ts +57 -4
- package/src/vite/discovery/virtual-module-codegen.ts +14 -34
- package/src/vite/index.ts +6 -0
- package/src/vite/inject-client-debug.ts +36 -0
- package/src/vite/plugin-types.ts +178 -5
- package/src/vite/plugins/cjs-to-esm.ts +16 -19
- package/src/vite/plugins/client-ref-dedup.ts +16 -11
- package/src/vite/plugins/client-ref-hashing.ts +28 -15
- 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 +194 -0
- package/src/vite/plugins/expose-action-id.ts +48 -95
- package/src/vite/plugins/expose-id-utils.ts +96 -51
- package/src/vite/plugins/expose-ids/export-analysis.ts +101 -34
- package/src/vite/plugins/expose-ids/handler-transform.ts +15 -64
- package/src/vite/plugins/expose-ids/loader-transform.ts +14 -24
- package/src/vite/plugins/expose-ids/router-transform.ts +118 -29
- package/src/vite/plugins/expose-internal-ids.ts +553 -317
- package/src/vite/plugins/performance-tracks.ts +64 -170
- package/src/vite/plugins/refresh-cmd.ts +89 -27
- package/src/vite/plugins/use-cache-transform.ts +73 -83
- package/src/vite/plugins/version-injector.ts +40 -29
- package/src/vite/plugins/version-plugin.ts +37 -40
- package/src/vite/plugins/virtual-entries.ts +39 -25
- package/src/vite/rango.ts +118 -114
- package/src/vite/router-discovery.ts +941 -142
- package/src/vite/utils/ast-handler-extract.ts +26 -35
- package/src/vite/utils/banner.ts +1 -1
- package/src/vite/utils/bundle-analysis.ts +10 -15
- package/src/vite/utils/client-chunks.ts +184 -0
- package/src/vite/utils/directive-prologue.ts +40 -0
- package/src/vite/utils/forward-user-plugins.ts +171 -0
- package/src/vite/utils/manifest-utils.ts +4 -59
- package/src/vite/utils/package-resolution.ts +20 -52
- package/src/vite/utils/prerender-utils.ts +81 -34
- package/src/vite/utils/shared-utils.ts +92 -42
- package/src/browser/action-response-classifier.ts +0 -99
- package/src/browser/debug-channel.ts +0 -93
- package/src/browser/react/use-client-cache.ts +0 -58
- package/src/browser/shallow.ts +0 -40
- package/src/handles/index.ts +0 -7
- package/src/network-error-thrower.tsx +0 -23
- package/src/router/middleware-cookies.ts +0 -55
package/src/router/match-api.ts
CHANGED
|
@@ -1,10 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Match API
|
|
3
|
-
*
|
|
4
|
-
* Extracted from createRouter closure. Contains match context creation functions
|
|
5
|
-
* and the matchError function for error boundary resolution.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
1
|
import { CacheScope, createCacheScope } from "../cache/cache-scope.js";
|
|
9
2
|
import { RouteNotFoundError } from "../errors";
|
|
10
3
|
import {
|
|
@@ -22,10 +15,10 @@ import { collectRouteMiddleware } from "./middleware.js";
|
|
|
22
15
|
import { traverseBack } from "./pattern-matching.js";
|
|
23
16
|
import { DefaultErrorFallback } from "../default-error-boundary.js";
|
|
24
17
|
import {
|
|
25
|
-
EntryData,
|
|
26
|
-
LoaderEntry,
|
|
18
|
+
type EntryData,
|
|
19
|
+
type LoaderEntry,
|
|
27
20
|
getContext,
|
|
28
|
-
InterceptSelectorContext,
|
|
21
|
+
type InterceptSelectorContext,
|
|
29
22
|
} from "../server/context";
|
|
30
23
|
import type { ErrorBoundaryHandler, ErrorInfo, MatchResult } from "../types";
|
|
31
24
|
import type { ReactNode } from "react";
|
|
@@ -36,7 +29,14 @@ import {
|
|
|
36
29
|
setRequestContextPrevRouteKey,
|
|
37
30
|
} from "../server/request-context.js";
|
|
38
31
|
import { isAutoGeneratedRouteName } from "../route-name.js";
|
|
32
|
+
import type { DefaultRouteName } from "../types/global-namespace.js";
|
|
39
33
|
import { debugLog, debugWarn } from "./logging.js";
|
|
34
|
+
import {
|
|
35
|
+
resolveRoute,
|
|
36
|
+
ensureFullRouteSnapshot,
|
|
37
|
+
type RouteSnapshot,
|
|
38
|
+
} from "./route-snapshot.js";
|
|
39
|
+
import { resolveNavigation } from "./navigation-snapshot.js";
|
|
40
40
|
|
|
41
41
|
/**
|
|
42
42
|
* Create match context for full requests (document/SSR).
|
|
@@ -52,58 +52,33 @@ export async function createMatchContextForFull<TEnv>(
|
|
|
52
52
|
|
|
53
53
|
const metricsStore = deps.getMetricsStore();
|
|
54
54
|
|
|
55
|
-
const
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
duration: performance.now() - routeMatchStart,
|
|
61
|
-
startTime: routeMatchStart - metricsStore.requestStart,
|
|
62
|
-
});
|
|
63
|
-
}
|
|
55
|
+
const result = await resolveRoute<TEnv>(pathname, {
|
|
56
|
+
findMatch: (p) => deps.findMatch(p, metricsStore),
|
|
57
|
+
metricsStore,
|
|
58
|
+
isSSR: true,
|
|
59
|
+
});
|
|
64
60
|
|
|
65
|
-
if (!
|
|
61
|
+
if (!result) {
|
|
66
62
|
throw new RouteNotFoundError(`No route matched for ${pathname}`, {
|
|
67
63
|
cause: { pathname, method: request.method },
|
|
68
64
|
});
|
|
69
65
|
}
|
|
70
66
|
|
|
71
|
-
if (
|
|
67
|
+
if (result.type === "redirect") {
|
|
72
68
|
return {
|
|
73
69
|
type: "redirect",
|
|
74
|
-
redirectUrl:
|
|
70
|
+
redirectUrl: result.redirectTo + url.search,
|
|
75
71
|
};
|
|
76
72
|
}
|
|
77
73
|
|
|
78
|
-
const
|
|
79
|
-
const manifestEntry = await loadManifest(
|
|
80
|
-
matched.entry,
|
|
81
|
-
matched.routeKey,
|
|
82
|
-
pathname,
|
|
83
|
-
metricsStore,
|
|
84
|
-
true,
|
|
85
|
-
);
|
|
86
|
-
if (metricsStore) {
|
|
87
|
-
metricsStore.metrics.push({
|
|
88
|
-
label: "manifest-loading",
|
|
89
|
-
duration: performance.now() - manifestStart,
|
|
90
|
-
startTime: manifestStart - metricsStore.requestStart,
|
|
91
|
-
});
|
|
92
|
-
}
|
|
74
|
+
const snapshot = result.snapshot;
|
|
93
75
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
) {
|
|
76
|
+
const { matched } = snapshot;
|
|
77
|
+
|
|
78
|
+
if (snapshot.isPassthrough) {
|
|
98
79
|
matched.pt = true;
|
|
99
80
|
}
|
|
100
81
|
|
|
101
|
-
const routeMiddleware = collectRouteMiddleware(
|
|
102
|
-
traverseBack(manifestEntry),
|
|
103
|
-
matched.params,
|
|
104
|
-
);
|
|
105
|
-
|
|
106
|
-
// Clean URL without internal _rsc* params for userland access
|
|
107
82
|
const cleanUrl = stripInternalParams(url);
|
|
108
83
|
|
|
109
84
|
const handlerContext = createHandlerContext(
|
|
@@ -134,14 +109,6 @@ export async function createMatchContextForFull<TEnv>(
|
|
|
134
109
|
Store.metrics = metricsStore;
|
|
135
110
|
}
|
|
136
111
|
|
|
137
|
-
const entries = [...traverseBack(manifestEntry)];
|
|
138
|
-
let cacheScope: CacheScope | null = null;
|
|
139
|
-
for (const entry of entries) {
|
|
140
|
-
if (entry.cache) {
|
|
141
|
-
cacheScope = createCacheScope(entry.cache, cacheScope);
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
|
|
145
112
|
return {
|
|
146
113
|
request,
|
|
147
114
|
url: cleanUrl,
|
|
@@ -154,12 +121,10 @@ export async function createMatchContextForFull<TEnv>(
|
|
|
154
121
|
prevParams: {},
|
|
155
122
|
prevMatch: null,
|
|
156
123
|
matched,
|
|
157
|
-
manifestEntry,
|
|
158
|
-
entries,
|
|
124
|
+
manifestEntry: snapshot.manifestEntry,
|
|
125
|
+
entries: snapshot.entries,
|
|
159
126
|
routeKey: matched.routeKey,
|
|
160
|
-
localRouteName:
|
|
161
|
-
? matched.routeKey.split(".").pop()!
|
|
162
|
-
: matched.routeKey,
|
|
127
|
+
localRouteName: snapshot.localRouteName,
|
|
163
128
|
handlerContext,
|
|
164
129
|
loaderPromises,
|
|
165
130
|
routeMap: deps.getRouteMap(),
|
|
@@ -175,16 +140,16 @@ export async function createMatchContextForFull<TEnv>(
|
|
|
175
140
|
segments: { path: [], ids: [] },
|
|
176
141
|
toRouteName:
|
|
177
142
|
matched.routeKey && !isAutoGeneratedRouteName(matched.routeKey)
|
|
178
|
-
? matched.routeKey
|
|
143
|
+
? (matched.routeKey as DefaultRouteName)
|
|
179
144
|
: undefined,
|
|
180
145
|
},
|
|
181
146
|
isSameRouteNavigation: false,
|
|
182
147
|
interceptResult: null,
|
|
183
|
-
cacheScope,
|
|
148
|
+
cacheScope: snapshot.cacheScope,
|
|
184
149
|
isIntercept: false,
|
|
185
150
|
actionContext: undefined,
|
|
186
151
|
isAction: false,
|
|
187
|
-
routeMiddleware,
|
|
152
|
+
routeMiddleware: snapshot.routeMiddleware,
|
|
188
153
|
isFullMatch: true,
|
|
189
154
|
};
|
|
190
155
|
}
|
|
@@ -204,104 +169,80 @@ export async function createMatchContextForPartial<TEnv>(
|
|
|
204
169
|
|
|
205
170
|
const metricsStore = deps.getMetricsStore();
|
|
206
171
|
|
|
207
|
-
const
|
|
208
|
-
url.searchParams.get("_rsc_segments")?.split(",").filter(Boolean) || [];
|
|
209
|
-
const stale = url.searchParams.get("_rsc_stale") === "true";
|
|
210
|
-
const previousUrl =
|
|
211
|
-
request.headers.get("X-RSC-Router-Client-Path") ||
|
|
212
|
-
request.headers.get("Referer");
|
|
213
|
-
const interceptSourceUrl = request.headers.get(
|
|
214
|
-
"X-RSC-Router-Intercept-Source",
|
|
215
|
-
);
|
|
172
|
+
const isHmr = !!request.headers.get("X-RSC-HMR");
|
|
216
173
|
|
|
217
174
|
// HMR: clear manifest cache so stale handler references are discarded
|
|
218
|
-
if (
|
|
175
|
+
if (isHmr) {
|
|
219
176
|
clearManifestCache();
|
|
220
177
|
}
|
|
221
178
|
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
179
|
+
// Reuse the classified snapshot when available and not invalidated by HMR.
|
|
180
|
+
// classifyRequest already called resolveRoute(lite) with isSSR=false, which
|
|
181
|
+
// matches the partial path. On HMR, discard to pick up manifest changes.
|
|
182
|
+
const classifiedRoute = isHmr
|
|
183
|
+
? undefined
|
|
184
|
+
: getRequestContext()?._classifiedRoute;
|
|
185
|
+
|
|
186
|
+
// Time route matching. On the reuse path, only nav findMatch calls are new
|
|
187
|
+
// (current-route findMatch and manifest-loading were already timed during
|
|
188
|
+
// classifyRequest via its metricsStore). On the fresh path, all findMatch
|
|
189
|
+
// calls are measured together.
|
|
190
|
+
const routeMatchStart = metricsStore ? performance.now() : 0;
|
|
232
191
|
|
|
233
|
-
let
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
192
|
+
let snapshot: RouteSnapshot<TEnv>;
|
|
193
|
+
if (classifiedRoute && classifiedRoute.manifestEntry) {
|
|
194
|
+
snapshot = ensureFullRouteSnapshot(classifiedRoute);
|
|
195
|
+
} else {
|
|
196
|
+
const result = await resolveRoute<TEnv>(pathname, {
|
|
197
|
+
findMatch: (p) => deps.findMatch(p, metricsStore),
|
|
198
|
+
metricsStore,
|
|
199
|
+
isSSR: false,
|
|
200
|
+
skipRouteMatchMetric: true,
|
|
201
|
+
});
|
|
241
202
|
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
: prevMatch;
|
|
203
|
+
if (!result) {
|
|
204
|
+
throw new RouteNotFoundError(`No route matched for ${pathname}`, {
|
|
205
|
+
cause: { pathname, method: request.method },
|
|
206
|
+
});
|
|
207
|
+
}
|
|
248
208
|
|
|
249
|
-
|
|
209
|
+
if (result.type === "redirect") {
|
|
210
|
+
return null;
|
|
211
|
+
}
|
|
250
212
|
|
|
251
|
-
|
|
252
|
-
metricsStore.metrics.push({
|
|
253
|
-
label: "route-matching",
|
|
254
|
-
duration: performance.now() - routeMatchStart,
|
|
255
|
-
startTime: routeMatchStart - metricsStore.requestStart,
|
|
256
|
-
});
|
|
213
|
+
snapshot = result.snapshot;
|
|
257
214
|
}
|
|
258
215
|
|
|
259
|
-
|
|
260
|
-
throw new RouteNotFoundError(`No route matched for ${pathname}`, {
|
|
261
|
-
cause: { pathname, method: request.method, previousUrl },
|
|
262
|
-
});
|
|
263
|
-
}
|
|
216
|
+
const { matched } = snapshot;
|
|
264
217
|
|
|
265
|
-
|
|
266
|
-
|
|
218
|
+
// Backward compat: downstream middleware reads matched.pt
|
|
219
|
+
if (snapshot.isPassthrough) {
|
|
220
|
+
matched.pt = true;
|
|
267
221
|
}
|
|
268
222
|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
223
|
+
const nav = resolveNavigation(request, url, matched.routeKey, {
|
|
224
|
+
findMatch: deps.findMatch,
|
|
225
|
+
});
|
|
226
|
+
if (!nav) {
|
|
227
|
+
return null;
|
|
274
228
|
}
|
|
275
229
|
|
|
276
|
-
const manifestStart = metricsStore ? performance.now() : 0;
|
|
277
|
-
const manifestEntry = await loadManifest(
|
|
278
|
-
matched.entry,
|
|
279
|
-
matched.routeKey,
|
|
280
|
-
pathname,
|
|
281
|
-
metricsStore,
|
|
282
|
-
false,
|
|
283
|
-
);
|
|
284
230
|
if (metricsStore) {
|
|
231
|
+
const isReuse = !!classifiedRoute;
|
|
285
232
|
metricsStore.metrics.push({
|
|
286
|
-
label: "
|
|
287
|
-
duration: performance.now() -
|
|
288
|
-
startTime:
|
|
233
|
+
label: isReuse ? "route-matching:nav" : "route-matching",
|
|
234
|
+
duration: performance.now() - routeMatchStart,
|
|
235
|
+
startTime: routeMatchStart - metricsStore.requestStart,
|
|
289
236
|
});
|
|
290
237
|
}
|
|
291
238
|
|
|
292
|
-
if (
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
239
|
+
if (nav.prevMatch && nav.prevMatch.entry !== matched.entry && !matched.pr) {
|
|
240
|
+
debugLog("matchPartial", "route group changed", {
|
|
241
|
+
from: nav.prevMatch.routeKey,
|
|
242
|
+
to: matched.routeKey,
|
|
243
|
+
});
|
|
297
244
|
}
|
|
298
245
|
|
|
299
|
-
const routeMiddleware = collectRouteMiddleware(
|
|
300
|
-
traverseBack(manifestEntry),
|
|
301
|
-
matched.params,
|
|
302
|
-
);
|
|
303
|
-
|
|
304
|
-
// Clean URL without internal _rsc* params for userland access
|
|
305
246
|
const cleanUrl = stripInternalParams(url);
|
|
306
247
|
|
|
307
248
|
const handlerContext = createHandlerContext(
|
|
@@ -317,9 +258,8 @@ export async function createMatchContextForPartial<TEnv>(
|
|
|
317
258
|
matched.pt === true,
|
|
318
259
|
);
|
|
319
260
|
|
|
320
|
-
const clientSegmentSet = new Set(clientSegmentIds);
|
|
321
261
|
debugLog("matchPartial", "client segments", {
|
|
322
|
-
segments: Array.from(clientSegmentSet),
|
|
262
|
+
segments: Array.from(nav.clientSegmentSet),
|
|
323
263
|
});
|
|
324
264
|
|
|
325
265
|
const loaderPromises = new Map<string, Promise<any>>();
|
|
@@ -337,100 +277,79 @@ export async function createMatchContextForPartial<TEnv>(
|
|
|
337
277
|
Store.metrics = metricsStore;
|
|
338
278
|
}
|
|
339
279
|
|
|
340
|
-
|
|
341
|
-
interceptContextMatch && interceptContextMatch.routeKey === matched.routeKey
|
|
342
|
-
);
|
|
343
|
-
|
|
344
|
-
if (interceptSourceUrl) {
|
|
280
|
+
if (nav.hasInterceptSource) {
|
|
345
281
|
debugLog("matchPartial.intercept", "intercept context detected", {
|
|
346
282
|
currentUrl: pathname,
|
|
347
|
-
interceptSource:
|
|
348
|
-
contextRoute: interceptContextMatch?.routeKey,
|
|
283
|
+
interceptSource: nav.interceptContextUrl.href,
|
|
284
|
+
contextRoute: nav.interceptContextMatch?.routeKey,
|
|
349
285
|
currentRoute: matched.routeKey,
|
|
350
|
-
sameRouteNavigation: isSameRouteNavigation,
|
|
286
|
+
sameRouteNavigation: nav.isSameRouteNavigation,
|
|
351
287
|
});
|
|
352
288
|
}
|
|
353
289
|
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
if (id.includes(".@")) return false;
|
|
360
|
-
if (/D\d+\./.test(id)) return false;
|
|
361
|
-
return true;
|
|
362
|
-
});
|
|
363
|
-
const effectiveFromUrl = interceptSourceUrl ? interceptContextUrl : prevUrl;
|
|
364
|
-
const effectiveFromMatch = interceptSourceUrl
|
|
365
|
-
? interceptContextMatch
|
|
366
|
-
: prevMatch;
|
|
367
|
-
|
|
368
|
-
// Store previous route key on the request context for revalidation
|
|
369
|
-
// fromRouteName. Uses effectiveFromMatch so intercept-source navigations
|
|
370
|
-
// see the intercept origin route, not the plain previous URL route.
|
|
371
|
-
setRequestContextPrevRouteKey(effectiveFromMatch?.routeKey);
|
|
290
|
+
setRequestContextPrevRouteKey(
|
|
291
|
+
nav.effectiveFromMatch?.routeKey,
|
|
292
|
+
nav.effectiveFromUrl,
|
|
293
|
+
nav.effectiveFromMatch?.params ?? nav.prevParams,
|
|
294
|
+
);
|
|
372
295
|
|
|
373
296
|
const interceptSelectorContext: InterceptSelectorContext = {
|
|
374
|
-
from: effectiveFromUrl,
|
|
297
|
+
from: nav.effectiveFromUrl,
|
|
375
298
|
to: cleanUrl,
|
|
376
299
|
params: matched.params,
|
|
377
300
|
request,
|
|
378
301
|
env,
|
|
379
302
|
segments: {
|
|
380
|
-
path: effectiveFromUrl.pathname.split("/").filter(Boolean),
|
|
381
|
-
ids: filteredSegmentIds,
|
|
303
|
+
path: nav.effectiveFromUrl.pathname.split("/").filter(Boolean),
|
|
304
|
+
ids: nav.filteredSegmentIds,
|
|
382
305
|
},
|
|
383
306
|
fromRouteName:
|
|
384
|
-
effectiveFromMatch?.routeKey &&
|
|
385
|
-
!isAutoGeneratedRouteName(effectiveFromMatch.routeKey)
|
|
386
|
-
? effectiveFromMatch.routeKey
|
|
307
|
+
nav.effectiveFromMatch?.routeKey &&
|
|
308
|
+
!isAutoGeneratedRouteName(nav.effectiveFromMatch.routeKey)
|
|
309
|
+
? (nav.effectiveFromMatch.routeKey as DefaultRouteName)
|
|
387
310
|
: undefined,
|
|
388
311
|
toRouteName:
|
|
389
312
|
matched.routeKey && !isAutoGeneratedRouteName(matched.routeKey)
|
|
390
|
-
? matched.routeKey
|
|
313
|
+
? (matched.routeKey as DefaultRouteName)
|
|
391
314
|
: undefined,
|
|
392
315
|
};
|
|
393
316
|
const isAction = !!actionContext;
|
|
394
317
|
|
|
395
|
-
const clientHasInterceptSegments = [...clientSegmentSet].some((id) =>
|
|
318
|
+
const clientHasInterceptSegments = [...nav.clientSegmentSet].some((id) =>
|
|
396
319
|
id.includes(".@"),
|
|
397
320
|
);
|
|
398
321
|
const skipInterceptForAction = isAction && !clientHasInterceptSegments;
|
|
399
322
|
const interceptResult =
|
|
400
|
-
isSameRouteNavigation || skipInterceptForAction
|
|
323
|
+
nav.isSameRouteNavigation || skipInterceptForAction
|
|
401
324
|
? null
|
|
402
325
|
: findInterceptForRoute(
|
|
403
326
|
matched.routeKey,
|
|
404
|
-
manifestEntry.parent,
|
|
327
|
+
snapshot.manifestEntry.parent,
|
|
405
328
|
interceptSelectorContext,
|
|
406
329
|
isAction,
|
|
407
330
|
) ||
|
|
408
|
-
(localRouteName !== matched.routeKey
|
|
331
|
+
(snapshot.localRouteName !== matched.routeKey
|
|
409
332
|
? findInterceptForRoute(
|
|
410
|
-
localRouteName,
|
|
411
|
-
manifestEntry.parent,
|
|
333
|
+
snapshot.localRouteName,
|
|
334
|
+
snapshot.manifestEntry.parent,
|
|
412
335
|
interceptSelectorContext,
|
|
413
336
|
isAction,
|
|
414
337
|
)
|
|
415
338
|
: null);
|
|
416
339
|
|
|
340
|
+
// Make a mutable copy of clientSegmentSet so we can delete entries
|
|
341
|
+
// for same-route navigation forcing
|
|
342
|
+
const clientSegmentSet = new Set(nav.clientSegmentSet);
|
|
343
|
+
|
|
417
344
|
if (
|
|
418
|
-
isSameRouteNavigation &&
|
|
419
|
-
manifestEntry.type === "route" &&
|
|
420
|
-
|
|
345
|
+
nav.isSameRouteNavigation &&
|
|
346
|
+
snapshot.manifestEntry.type === "route" &&
|
|
347
|
+
nav.hasInterceptSource
|
|
421
348
|
) {
|
|
422
349
|
debugLog("matchPartial.intercept", "forcing route segment render", {
|
|
423
|
-
segmentId: manifestEntry.shortCode,
|
|
350
|
+
segmentId: snapshot.manifestEntry.shortCode,
|
|
424
351
|
});
|
|
425
|
-
clientSegmentSet.delete(manifestEntry.shortCode);
|
|
426
|
-
}
|
|
427
|
-
|
|
428
|
-
const entries = [...traverseBack(manifestEntry)];
|
|
429
|
-
let cacheScope: CacheScope | null = null;
|
|
430
|
-
for (const entry of entries) {
|
|
431
|
-
if (entry.cache) {
|
|
432
|
-
cacheScope = createCacheScope(entry.cache, cacheScope);
|
|
433
|
-
}
|
|
352
|
+
clientSegmentSet.delete(snapshot.manifestEntry.shortCode);
|
|
434
353
|
}
|
|
435
354
|
|
|
436
355
|
const isIntercept = !!interceptResult;
|
|
@@ -440,31 +359,31 @@ export async function createMatchContextForPartial<TEnv>(
|
|
|
440
359
|
url: cleanUrl,
|
|
441
360
|
pathname,
|
|
442
361
|
env,
|
|
443
|
-
clientSegmentIds,
|
|
362
|
+
clientSegmentIds: nav.clientSegmentIds,
|
|
444
363
|
clientSegmentSet,
|
|
445
|
-
stale,
|
|
446
|
-
prevUrl,
|
|
447
|
-
prevParams,
|
|
448
|
-
prevMatch,
|
|
364
|
+
stale: nav.stale,
|
|
365
|
+
prevUrl: nav.prevUrl,
|
|
366
|
+
prevParams: nav.prevParams,
|
|
367
|
+
prevMatch: nav.prevMatch,
|
|
449
368
|
matched,
|
|
450
|
-
manifestEntry,
|
|
451
|
-
entries,
|
|
369
|
+
manifestEntry: snapshot.manifestEntry,
|
|
370
|
+
entries: snapshot.entries,
|
|
452
371
|
routeKey: matched.routeKey,
|
|
453
|
-
localRouteName,
|
|
372
|
+
localRouteName: snapshot.localRouteName,
|
|
454
373
|
handlerContext,
|
|
455
374
|
loaderPromises,
|
|
456
375
|
routeMap: deps.getRouteMap(),
|
|
457
376
|
metricsStore,
|
|
458
377
|
Store,
|
|
459
|
-
interceptContextMatch,
|
|
378
|
+
interceptContextMatch: nav.interceptContextMatch,
|
|
460
379
|
interceptSelectorContext,
|
|
461
|
-
isSameRouteNavigation,
|
|
380
|
+
isSameRouteNavigation: nav.isSameRouteNavigation,
|
|
462
381
|
interceptResult,
|
|
463
|
-
cacheScope,
|
|
382
|
+
cacheScope: snapshot.cacheScope,
|
|
464
383
|
isIntercept,
|
|
465
384
|
actionContext,
|
|
466
385
|
isAction,
|
|
467
|
-
routeMiddleware,
|
|
386
|
+
routeMiddleware: snapshot.routeMiddleware,
|
|
468
387
|
isFullMatch: false,
|
|
469
388
|
};
|
|
470
389
|
}
|
|
@@ -615,6 +534,7 @@ export async function matchError<TEnv>(
|
|
|
615
534
|
segments: [errorSegment],
|
|
616
535
|
matched: matchedIds,
|
|
617
536
|
diff: [errorSegment.id],
|
|
537
|
+
resolvedIds: [errorSegment.id],
|
|
618
538
|
params: matched.params,
|
|
619
539
|
};
|
|
620
540
|
}
|
|
@@ -242,25 +242,3 @@ export function createPipelineState(): MatchPipelineState {
|
|
|
242
242
|
slots: {},
|
|
243
243
|
};
|
|
244
244
|
}
|
|
245
|
-
|
|
246
|
-
/**
|
|
247
|
-
* Input parameters for createMatchContext
|
|
248
|
-
*/
|
|
249
|
-
export interface CreateMatchContextInput<TEnv = any> {
|
|
250
|
-
request: Request;
|
|
251
|
-
env: TEnv;
|
|
252
|
-
actionContext?: ActionContext;
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
/**
|
|
256
|
-
* Result from createMatchContext - either a context or null (fall back to full match)
|
|
257
|
-
*/
|
|
258
|
-
export type CreateMatchContextResult<TEnv = any> =
|
|
259
|
-
| { type: "context"; ctx: MatchContext<TEnv> }
|
|
260
|
-
| { type: "fallback"; reason: string }
|
|
261
|
-
| { type: "error"; error: Error };
|
|
262
|
-
|
|
263
|
-
// Note: createMatchContext() will be implemented in Step J10 when we wire everything together.
|
|
264
|
-
// It requires access to RouterContext (findMatch, loadManifest, etc.) which are closure
|
|
265
|
-
// functions from createRouter(). The implementation will live in router.ts initially
|
|
266
|
-
// and call getRouterContext() to access these dependencies.
|