@rangojs/router 0.0.0-experimental.32 → 0.0.0-experimental.3232cd17
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 +4 -0
- package/README.md +198 -44
- package/dist/bin/rango.js +287 -105
- package/dist/testing/vitest.js +82 -0
- package/dist/vite/index.js +3248 -1117
- package/dist/vite/plugins/cloudflare-protocol-loader-hook.mjs +76 -0
- package/package.json +73 -21
- package/skills/api-client/SKILL.md +211 -0
- package/skills/breadcrumbs/SKILL.md +107 -1
- package/skills/bundle-analysis/SKILL.md +159 -0
- package/skills/cache-guide/SKILL.md +245 -21
- package/skills/caching/SKILL.md +302 -6
- package/skills/composability/SKILL.md +27 -2
- package/skills/css/SKILL.md +76 -0
- package/skills/document-cache/SKILL.md +78 -55
- package/skills/handler-use/SKILL.md +364 -0
- package/skills/hooks/SKILL.md +270 -30
- package/skills/host-router/SKILL.md +82 -22
- package/skills/i18n/SKILL.md +276 -0
- package/skills/intercept/SKILL.md +49 -5
- package/skills/layout/SKILL.md +35 -9
- package/skills/links/SKILL.md +249 -17
- package/skills/loader/SKILL.md +294 -30
- package/skills/middleware/SKILL.md +52 -13
- package/skills/migrate-nextjs/SKILL.md +584 -0
- package/skills/migrate-react-router/SKILL.md +769 -0
- package/skills/mime-routes/SKILL.md +27 -0
- package/skills/observability/SKILL.md +137 -0
- package/skills/parallel/SKILL.md +203 -7
- package/skills/prerender/SKILL.md +123 -100
- package/skills/rango/SKILL.md +250 -22
- package/skills/react-compiler/SKILL.md +168 -0
- package/skills/response-routes/SKILL.md +122 -47
- package/skills/route/SKILL.md +97 -5
- package/skills/router-setup/SKILL.md +90 -5
- 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 +129 -0
- package/skills/testing/bindings.md +89 -0
- package/skills/testing/cache-prerender.md +124 -0
- package/skills/testing/client-components.md +122 -0
- package/skills/testing/e2e-parity.md +125 -0
- package/skills/testing/flight.md +92 -0
- package/skills/testing/handles.md +129 -0
- package/skills/testing/loader.md +128 -0
- package/skills/testing/middleware.md +99 -0
- package/skills/testing/render-handler.md +121 -0
- package/skills/testing/response-routes.md +95 -0
- package/skills/testing/reverse-and-types.md +84 -0
- package/skills/testing/server-actions.md +107 -0
- package/skills/testing/server-tree.md +128 -0
- package/skills/testing/setup.md +120 -0
- package/skills/typesafety/SKILL.md +329 -27
- package/skills/use-cache/SKILL.md +36 -5
- package/skills/view-transitions/SKILL.md +294 -0
- package/src/__augment-tests__/augment.ts +81 -0
- package/src/__augment-tests__/augmented.check.ts +116 -0
- package/src/__internal.ts +67 -40
- 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/cookie-name.ts +140 -0
- package/src/browser/event-controller.ts +86 -147
- 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/link-interceptor.ts +4 -0
- package/src/browser/navigation-bridge.ts +148 -19
- package/src/browser/navigation-client.ts +187 -67
- package/src/browser/navigation-store-handle.ts +38 -0
- package/src/browser/navigation-store.ts +76 -67
- package/src/browser/navigation-transaction.ts +18 -66
- package/src/browser/partial-update.ts +123 -94
- package/src/browser/prefetch/cache.ts +214 -36
- package/src/browser/prefetch/fetch.ts +260 -38
- package/src/browser/prefetch/policy.ts +6 -0
- package/src/browser/prefetch/queue.ts +126 -20
- package/src/browser/prefetch/resource-ready.ts +77 -0
- package/src/browser/rango-state.ts +158 -76
- package/src/browser/react/Link.tsx +93 -11
- package/src/browser/react/NavigationProvider.tsx +115 -34
- package/src/browser/react/ScrollRestoration.tsx +10 -6
- package/src/browser/react/context.ts +7 -2
- package/src/browser/react/filter-segment-order.ts +49 -7
- package/src/browser/react/index.ts +0 -48
- package/src/browser/react/location-state-shared.ts +166 -8
- package/src/browser/react/location-state.ts +39 -14
- package/src/browser/react/use-action.ts +6 -15
- package/src/browser/react/use-handle.ts +23 -69
- package/src/browser/react/use-link-status.ts +0 -4
- package/src/browser/react/use-navigation.ts +22 -5
- 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 +52 -1
- package/src/browser/rsc-router.tsx +215 -76
- package/src/browser/scroll-restoration.ts +46 -39
- package/src/browser/segment-reconciler.ts +36 -9
- package/src/browser/segment-structure-assert.ts +2 -2
- package/src/browser/server-action-bridge.ts +176 -50
- package/src/browser/types.ts +95 -11
- 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 -0
- package/src/build/index.ts +8 -2
- package/src/build/prefix-tree-utils.ts +123 -0
- package/src/build/route-trie.ts +137 -32
- package/src/build/route-types/codegen.ts +4 -4
- package/src/build/route-types/include-resolution.ts +9 -2
- package/src/build/route-types/param-extraction.ts +6 -3
- package/src/build/route-types/per-module-writer.ts +7 -4
- package/src/build/route-types/router-processing.ts +278 -96
- package/src/build/route-types/scan-filter.ts +9 -2
- package/src/build/route-types/source-scan.ts +118 -0
- package/src/build/runtime-discovery.ts +9 -20
- package/src/cache/cache-error.ts +104 -0
- package/src/cache/cache-policy.ts +68 -28
- package/src/cache/cache-runtime.ts +149 -43
- package/src/cache/cache-scope.ts +148 -81
- package/src/cache/cache-tag.ts +98 -0
- package/src/cache/cf/cf-cache-store.ts +2550 -93
- package/src/cache/cf/index.ts +11 -17
- package/src/cache/document-cache.ts +78 -27
- package/src/cache/handle-snapshot.ts +63 -0
- package/src/cache/index.ts +23 -20
- package/src/cache/memory-segment-store.ts +136 -37
- package/src/cache/profile-registry.ts +6 -30
- package/src/cache/read-through-swr.ts +41 -11
- package/src/cache/segment-codec.ts +0 -16
- package/src/cache/tag-invalidation.ts +230 -0
- package/src/cache/taint.ts +55 -0
- package/src/cache/types.ts +33 -100
- package/src/cache/vercel/index.ts +11 -0
- package/src/cache/vercel/vercel-cache-store.ts +799 -0
- package/src/client.rsc.tsx +6 -21
- package/src/client.tsx +108 -290
- package/src/component-utils.ts +19 -0
- package/src/context-var.ts +84 -2
- package/src/debug.ts +2 -2
- package/src/decode-loader-results.ts +36 -0
- package/src/defer.ts +196 -0
- package/src/deps/ssr.ts +0 -1
- package/src/errors.ts +30 -4
- package/src/handle.ts +70 -22
- package/src/handles/MetaTags.tsx +0 -14
- package/src/handles/breadcrumbs.ts +16 -5
- package/src/handles/meta.ts +0 -39
- package/src/host/cookie-handler.ts +0 -36
- package/src/host/errors.ts +0 -24
- package/src/host/index.ts +8 -2
- package/src/host/pattern-matcher.ts +7 -50
- package/src/host/router.ts +107 -99
- package/src/host/testing.ts +40 -27
- package/src/host/types.ts +37 -4
- package/src/host/utils.ts +1 -1
- package/src/href-client.ts +137 -22
- package/src/index.rsc.ts +52 -26
- package/src/index.ts +100 -38
- package/src/internal-debug.ts +2 -4
- package/src/loader-store.ts +500 -0
- package/src/loader.rsc.ts +20 -13
- package/src/loader.ts +12 -11
- package/src/missing-id-error.ts +68 -0
- package/src/network-error-thrower.tsx +1 -6
- package/src/outlet-context.ts +1 -1
- package/src/outlet-provider.tsx +1 -5
- package/src/prerender/param-hash.ts +10 -11
- package/src/prerender/store.ts +37 -41
- package/src/prerender.ts +198 -82
- package/src/redirect-origin.ts +100 -0
- package/src/response-utils.ts +37 -0
- package/src/reverse.ts +65 -15
- package/src/root-error-boundary.tsx +1 -19
- package/src/route-content-wrapper.tsx +7 -72
- package/src/route-definition/dsl-helpers.ts +437 -274
- package/src/route-definition/helper-factories.ts +29 -139
- package/src/route-definition/helpers-types.ts +113 -37
- package/src/route-definition/index.ts +3 -0
- package/src/route-definition/redirect.ts +52 -10
- package/src/route-definition/resolve-handler-use.ts +161 -0
- package/src/route-definition/use-item-types.ts +32 -0
- package/src/route-map-builder.ts +7 -17
- package/src/route-types.ts +37 -41
- package/src/router/basename.ts +14 -0
- package/src/router/content-negotiation.ts +108 -9
- package/src/router/error-handling.ts +13 -17
- package/src/router/find-match.ts +45 -22
- package/src/router/handler-context.ts +83 -41
- package/src/router/intercept-resolution.ts +25 -23
- package/src/router/lazy-includes.ts +19 -53
- package/src/router/loader-resolution.ts +213 -30
- package/src/router/logging.ts +5 -8
- package/src/router/manifest.ts +49 -45
- package/src/router/match-api.ts +120 -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 +27 -6
- package/src/router/match-middleware/cache-lookup.ts +205 -249
- package/src/router/match-middleware/cache-store.ts +45 -32
- package/src/router/match-middleware/intercept-resolution.ts +8 -28
- package/src/router/match-middleware/segment-resolution.ts +52 -18
- package/src/router/match-pipelines.ts +1 -42
- package/src/router/match-result.ts +104 -40
- package/src/router/metrics.ts +5 -34
- package/src/router/middleware-types.ts +13 -142
- package/src/router/middleware.ts +173 -143
- package/src/router/navigation-snapshot.ts +131 -0
- package/src/router/params-util.ts +23 -0
- package/src/router/pattern-matching.ts +109 -63
- package/src/router/prerender-match.ts +190 -54
- package/src/router/preview-match.ts +32 -102
- package/src/router/request-classification.ts +276 -0
- package/src/router/revalidation.ts +63 -55
- package/src/router/route-snapshot.ts +244 -0
- package/src/router/router-context.ts +6 -28
- package/src/router/router-interfaces.ts +100 -35
- package/src/router/router-options.ts +91 -11
- package/src/router/router-registry.ts +2 -5
- package/src/router/segment-resolution/fresh.ts +242 -75
- package/src/router/segment-resolution/helpers.ts +63 -24
- package/src/router/segment-resolution/loader-cache.ts +41 -37
- package/src/router/segment-resolution/revalidation.ts +456 -372
- package/src/router/segment-resolution/static-store.ts +19 -5
- package/src/router/segment-resolution/streamed-handler-telemetry.ts +52 -0
- package/src/router/segment-resolution/view-transition-default.ts +36 -0
- package/src/router/segment-resolution.ts +4 -1
- package/src/router/segment-wrappers.ts +2 -3
- package/src/router/state-cookie-name.ts +33 -0
- package/src/router/substitute-pattern-params.ts +56 -0
- package/src/router/telemetry-otel.ts +0 -20
- package/src/router/telemetry.ts +96 -19
- package/src/router/timeout.ts +0 -20
- package/src/router/trie-matching.ts +91 -46
- package/src/router/types.ts +10 -63
- package/src/router/url-params.ts +44 -0
- package/src/router.ts +134 -43
- package/src/rsc/handler-context.ts +3 -2
- package/src/rsc/handler.ts +492 -383
- package/src/rsc/helpers.ts +162 -46
- package/src/rsc/index.ts +1 -1
- package/src/rsc/json-route-result.ts +38 -0
- package/src/rsc/loader-fetch.ts +23 -3
- package/src/rsc/manifest-init.ts +33 -42
- package/src/rsc/origin-guard.ts +39 -25
- package/src/rsc/progressive-enhancement.ts +30 -3
- package/src/rsc/redirect-guard.ts +99 -0
- package/src/rsc/response-error.ts +79 -12
- package/src/rsc/response-route-handler.ts +90 -63
- package/src/rsc/rsc-rendering.ts +56 -54
- package/src/rsc/runtime-warnings.ts +23 -10
- package/src/rsc/server-action.ts +74 -67
- package/src/rsc/ssr-setup.ts +18 -2
- package/src/rsc/types.ts +25 -6
- package/src/runtime-env.ts +18 -0
- package/src/search-params.ts +4 -20
- package/src/segment-content-promise.ts +67 -0
- package/src/segment-loader-promise.ts +134 -0
- package/src/segment-system.tsx +272 -129
- package/src/serialize.ts +243 -0
- package/src/server/context.ts +309 -61
- package/src/server/cookie-store.ts +80 -5
- package/src/server/handle-store.ts +26 -24
- package/src/server/loader-registry.ts +10 -28
- package/src/server/request-context.ts +338 -126
- package/src/ssr/index.tsx +23 -15
- 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 +618 -0
- package/src/testing/dom.entry.ts +22 -0
- package/src/testing/e2e/fixture.ts +188 -0
- package/src/testing/e2e/index.ts +128 -0
- package/src/testing/e2e/matchers.ts +35 -0
- package/src/testing/e2e/page-helpers.ts +272 -0
- package/src/testing/e2e/parity.ts +387 -0
- package/src/testing/e2e/server.ts +195 -0
- package/src/testing/flight-matchers.ts +97 -0
- package/src/testing/flight-normalize.ts +11 -0
- package/src/testing/flight-runtime.d.ts +57 -0
- package/src/testing/flight-tree.ts +682 -0
- package/src/testing/flight.entry.ts +52 -0
- package/src/testing/flight.ts +232 -0
- package/src/testing/generated-routes.ts +183 -0
- package/src/testing/index.ts +99 -0
- package/src/testing/internal/context.ts +348 -0
- package/src/testing/internal/flight-client-globals.ts +30 -0
- package/src/testing/internal/seed-vars.ts +54 -0
- package/src/testing/render-handler.ts +330 -0
- package/src/testing/render-route.tsx +566 -0
- package/src/testing/run-loader.ts +378 -0
- package/src/testing/run-middleware.ts +205 -0
- package/src/testing/vitest-stubs/cloudflare-email.ts +9 -0
- package/src/testing/vitest-stubs/cloudflare-workers.ts +21 -0
- package/src/testing/vitest-stubs/plugin-rsc.ts +16 -0
- package/src/testing/vitest-stubs/version.ts +5 -0
- package/src/testing/vitest.ts +305 -0
- package/src/theme/ThemeProvider.tsx +0 -52
- package/src/theme/ThemeScript.tsx +0 -6
- package/src/theme/constants.ts +0 -12
- package/src/theme/index.ts +0 -7
- package/src/theme/theme-context.ts +1 -5
- package/src/theme/theme-script.ts +0 -14
- package/src/theme/use-theme.ts +0 -3
- package/src/types/boundaries.ts +0 -35
- package/src/types/cache-types.ts +17 -8
- package/src/types/error-types.ts +30 -90
- package/src/types/global-namespace.ts +54 -41
- package/src/types/handler-context.ts +233 -81
- package/src/types/index.ts +1 -10
- package/src/types/loader-types.ts +44 -15
- package/src/types/request-scope.ts +107 -0
- package/src/types/route-config.ts +6 -50
- package/src/types/route-entry.ts +19 -7
- package/src/types/segments.ts +37 -14
- package/src/urls/include-helper.ts +33 -70
- package/src/urls/index.ts +1 -11
- package/src/urls/path-helper-types.ts +58 -11
- 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 -18
- 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 +192 -99
- 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 +51 -6
- package/src/vite/discovery/virtual-module-codegen.ts +14 -34
- package/src/vite/index.ts +8 -0
- package/src/vite/plugin-types.ts +187 -69
- package/src/vite/plugins/cjs-to-esm.ts +8 -18
- 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 +49 -98
- package/src/vite/plugins/expose-id-utils.ts +11 -50
- package/src/vite/plugins/expose-ids/export-analysis.ts +76 -34
- package/src/vite/plugins/expose-ids/handler-transform.ts +10 -48
- package/src/vite/plugins/expose-ids/loader-transform.ts +3 -20
- package/src/vite/plugins/expose-ids/router-transform.ts +20 -16
- package/src/vite/plugins/expose-internal-ids.ts +554 -317
- package/src/vite/plugins/performance-tracks.ts +89 -0
- package/src/vite/plugins/refresh-cmd.ts +89 -27
- package/src/vite/plugins/use-cache-transform.ts +73 -83
- package/src/vite/plugins/vercel-output.ts +258 -0
- package/src/vite/plugins/version-injector.ts +21 -25
- package/src/vite/plugins/version-plugin.ts +41 -20
- package/src/vite/plugins/virtual-entries.ts +2 -17
- package/src/vite/rango.ts +257 -289
- package/src/vite/router-discovery.ts +930 -140
- package/src/vite/utils/ast-handler-extract.ts +15 -31
- package/src/vite/utils/banner.ts +4 -4
- package/src/vite/utils/bundle-analysis.ts +10 -15
- package/src/vite/utils/client-chunks.ts +184 -0
- package/src/vite/utils/forward-user-plugins.ts +171 -0
- package/src/vite/utils/manifest-utils.ts +4 -59
- package/src/vite/utils/package-resolution.ts +20 -52
- package/src/vite/utils/prerender-utils.ts +27 -29
- package/src/vite/utils/shared-utils.ts +92 -42
- package/src/browser/action-response-classifier.ts +0 -99
- package/src/browser/react/use-client-cache.ts +0 -58
- package/src/browser/shallow.ts +0 -40
- package/src/handles/index.ts +0 -7
- package/src/router/middleware-cookies.ts +0 -55
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,75 @@ 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
|
-
? matched.routeKey.split(".").pop()!
|
|
356
|
-
: matched.routeKey;
|
|
357
|
-
|
|
358
|
-
const filteredSegmentIds = clientSegmentIds.filter((id) => {
|
|
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(nav.effectiveFromMatch?.routeKey);
|
|
372
291
|
|
|
373
292
|
const interceptSelectorContext: InterceptSelectorContext = {
|
|
374
|
-
from: effectiveFromUrl,
|
|
293
|
+
from: nav.effectiveFromUrl,
|
|
375
294
|
to: cleanUrl,
|
|
376
295
|
params: matched.params,
|
|
377
296
|
request,
|
|
378
297
|
env,
|
|
379
298
|
segments: {
|
|
380
|
-
path: effectiveFromUrl.pathname.split("/").filter(Boolean),
|
|
381
|
-
ids: filteredSegmentIds,
|
|
299
|
+
path: nav.effectiveFromUrl.pathname.split("/").filter(Boolean),
|
|
300
|
+
ids: nav.filteredSegmentIds,
|
|
382
301
|
},
|
|
383
302
|
fromRouteName:
|
|
384
|
-
effectiveFromMatch?.routeKey &&
|
|
385
|
-
!isAutoGeneratedRouteName(effectiveFromMatch.routeKey)
|
|
386
|
-
? effectiveFromMatch.routeKey
|
|
303
|
+
nav.effectiveFromMatch?.routeKey &&
|
|
304
|
+
!isAutoGeneratedRouteName(nav.effectiveFromMatch.routeKey)
|
|
305
|
+
? (nav.effectiveFromMatch.routeKey as DefaultRouteName)
|
|
387
306
|
: undefined,
|
|
388
307
|
toRouteName:
|
|
389
308
|
matched.routeKey && !isAutoGeneratedRouteName(matched.routeKey)
|
|
390
|
-
? matched.routeKey
|
|
309
|
+
? (matched.routeKey as DefaultRouteName)
|
|
391
310
|
: undefined,
|
|
392
311
|
};
|
|
393
312
|
const isAction = !!actionContext;
|
|
394
313
|
|
|
395
|
-
const clientHasInterceptSegments = [...clientSegmentSet].some((id) =>
|
|
314
|
+
const clientHasInterceptSegments = [...nav.clientSegmentSet].some((id) =>
|
|
396
315
|
id.includes(".@"),
|
|
397
316
|
);
|
|
398
317
|
const skipInterceptForAction = isAction && !clientHasInterceptSegments;
|
|
399
318
|
const interceptResult =
|
|
400
|
-
isSameRouteNavigation || skipInterceptForAction
|
|
319
|
+
nav.isSameRouteNavigation || skipInterceptForAction
|
|
401
320
|
? null
|
|
402
321
|
: findInterceptForRoute(
|
|
403
322
|
matched.routeKey,
|
|
404
|
-
manifestEntry.parent,
|
|
323
|
+
snapshot.manifestEntry.parent,
|
|
405
324
|
interceptSelectorContext,
|
|
406
325
|
isAction,
|
|
407
326
|
) ||
|
|
408
|
-
(localRouteName !== matched.routeKey
|
|
327
|
+
(snapshot.localRouteName !== matched.routeKey
|
|
409
328
|
? findInterceptForRoute(
|
|
410
|
-
localRouteName,
|
|
411
|
-
manifestEntry.parent,
|
|
329
|
+
snapshot.localRouteName,
|
|
330
|
+
snapshot.manifestEntry.parent,
|
|
412
331
|
interceptSelectorContext,
|
|
413
332
|
isAction,
|
|
414
333
|
)
|
|
415
334
|
: null);
|
|
416
335
|
|
|
336
|
+
// Make a mutable copy of clientSegmentSet so we can delete entries
|
|
337
|
+
// for same-route navigation forcing
|
|
338
|
+
const clientSegmentSet = new Set(nav.clientSegmentSet);
|
|
339
|
+
|
|
417
340
|
if (
|
|
418
|
-
isSameRouteNavigation &&
|
|
419
|
-
manifestEntry.type === "route" &&
|
|
420
|
-
|
|
341
|
+
nav.isSameRouteNavigation &&
|
|
342
|
+
snapshot.manifestEntry.type === "route" &&
|
|
343
|
+
nav.hasInterceptSource
|
|
421
344
|
) {
|
|
422
345
|
debugLog("matchPartial.intercept", "forcing route segment render", {
|
|
423
|
-
segmentId: manifestEntry.shortCode,
|
|
346
|
+
segmentId: snapshot.manifestEntry.shortCode,
|
|
424
347
|
});
|
|
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
|
-
}
|
|
348
|
+
clientSegmentSet.delete(snapshot.manifestEntry.shortCode);
|
|
434
349
|
}
|
|
435
350
|
|
|
436
351
|
const isIntercept = !!interceptResult;
|
|
@@ -440,31 +355,31 @@ export async function createMatchContextForPartial<TEnv>(
|
|
|
440
355
|
url: cleanUrl,
|
|
441
356
|
pathname,
|
|
442
357
|
env,
|
|
443
|
-
clientSegmentIds,
|
|
358
|
+
clientSegmentIds: nav.clientSegmentIds,
|
|
444
359
|
clientSegmentSet,
|
|
445
|
-
stale,
|
|
446
|
-
prevUrl,
|
|
447
|
-
prevParams,
|
|
448
|
-
prevMatch,
|
|
360
|
+
stale: nav.stale,
|
|
361
|
+
prevUrl: nav.prevUrl,
|
|
362
|
+
prevParams: nav.prevParams,
|
|
363
|
+
prevMatch: nav.prevMatch,
|
|
449
364
|
matched,
|
|
450
|
-
manifestEntry,
|
|
451
|
-
entries,
|
|
365
|
+
manifestEntry: snapshot.manifestEntry,
|
|
366
|
+
entries: snapshot.entries,
|
|
452
367
|
routeKey: matched.routeKey,
|
|
453
|
-
localRouteName,
|
|
368
|
+
localRouteName: snapshot.localRouteName,
|
|
454
369
|
handlerContext,
|
|
455
370
|
loaderPromises,
|
|
456
371
|
routeMap: deps.getRouteMap(),
|
|
457
372
|
metricsStore,
|
|
458
373
|
Store,
|
|
459
|
-
interceptContextMatch,
|
|
374
|
+
interceptContextMatch: nav.interceptContextMatch,
|
|
460
375
|
interceptSelectorContext,
|
|
461
|
-
isSameRouteNavigation,
|
|
376
|
+
isSameRouteNavigation: nav.isSameRouteNavigation,
|
|
462
377
|
interceptResult,
|
|
463
|
-
cacheScope,
|
|
378
|
+
cacheScope: snapshot.cacheScope,
|
|
464
379
|
isIntercept,
|
|
465
380
|
actionContext,
|
|
466
381
|
isAction,
|
|
467
|
-
routeMiddleware,
|
|
382
|
+
routeMiddleware: snapshot.routeMiddleware,
|
|
468
383
|
isFullMatch: false,
|
|
469
384
|
};
|
|
470
385
|
}
|
|
@@ -615,6 +530,7 @@ export async function matchError<TEnv>(
|
|
|
615
530
|
segments: [errorSegment],
|
|
616
531
|
matched: matchedIds,
|
|
617
532
|
diff: [errorSegment.id],
|
|
533
|
+
resolvedIds: [errorSegment.id],
|
|
618
534
|
params: matched.params,
|
|
619
535
|
};
|
|
620
536
|
}
|
|
@@ -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.
|