@rangojs/router 0.0.0-experimental.135c6902 → 0.0.0-experimental.136
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 +3386 -1111
- package/dist/vite/index.js.bak +5448 -0
- package/dist/vite/plugins/cloudflare-protocol-loader-hook.mjs +76 -0
- package/package.json +78 -25
- 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 +247 -23
- package/skills/caching/SKILL.md +281 -11
- 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 +289 -53
- package/skills/middleware/SKILL.md +52 -13
- package/skills/migrate-nextjs/SKILL.md +584 -0
- package/skills/migrate-react-router/SKILL.md +914 -0
- package/skills/mime-routes/SKILL.md +28 -1
- package/skills/observability/SKILL.md +172 -0
- package/skills/parallel/SKILL.md +144 -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 +101 -5
- package/skills/router-setup/SKILL.md +117 -10
- 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 +332 -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 +199 -86
- 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 +174 -109
- package/src/browser/prefetch/cache.ts +222 -69
- package/src/browser/prefetch/fetch.ts +347 -39
- package/src/browser/prefetch/queue.ts +113 -32
- package/src/browser/prefetch/resource-ready.ts +77 -0
- package/src/browser/rango-state.ts +158 -76
- package/src/browser/react/Link.tsx +102 -15
- package/src/browser/react/NavigationProvider.tsx +300 -122
- 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 +125 -28
- 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 -61
- package/src/browser/types.ts +115 -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 +239 -52
- package/src/cache/cache-scope.ts +234 -87
- 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/taint.ts +55 -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 +84 -2
- 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 +149 -74
- 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 +83 -39
- 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 +274 -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 +54 -25
- package/src/router/match-middleware/cache-lookup.ts +205 -271
- package/src/router/match-middleware/cache-store.ts +81 -50
- 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 +93 -39
- package/src/router/metrics.ts +5 -34
- package/src/router/middleware-types.ts +13 -142
- package/src/router/middleware.ts +268 -171
- 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/prefetch-limits.ts +37 -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 -27
- package/src/router/router-interfaces.ts +129 -35
- package/src/router/router-options.ts +202 -15
- package/src/router/router-registry.ts +2 -5
- package/src/router/segment-resolution/fresh.ts +197 -92
- package/src/router/segment-resolution/helpers.ts +115 -30
- package/src/router/segment-resolution/loader-cache.ts +76 -39
- package/src/router/segment-resolution/revalidation.ts +392 -338
- 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 +10 -63
- package/src/router/url-params.ts +44 -0
- package/src/router.ts +174 -54
- package/src/rsc/handler-context.ts +3 -2
- package/src/rsc/handler.ts +660 -518
- 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 +127 -31
- package/src/rsc/manifest-init.ts +33 -42
- package/src/rsc/origin-guard.ts +39 -25
- package/src/rsc/progressive-enhancement.ts +133 -13
- 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 +115 -73
- package/src/rsc/runtime-warnings.ts +23 -10
- package/src/rsc/server-action.ts +287 -113
- package/src/rsc/ssr-setup.ts +18 -2
- package/src/rsc/transition-gate.ts +89 -0
- package/src/rsc/types.ts +36 -6
- 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 +269 -202
- package/src/serialize.ts +243 -0
- package/src/server/context.ts +235 -51
- 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 +442 -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 +234 -82
- package/src/types/index.ts +3 -10
- package/src/types/loader-types.ts +44 -15
- 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 +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/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 +119 -111
- 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/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
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Route Snapshot
|
|
3
|
+
*
|
|
4
|
+
* Pure data type representing the fully-resolved state of a single route match.
|
|
5
|
+
* Consolidates the duplicated findMatch + loadManifest + collectRouteMiddleware +
|
|
6
|
+
* cacheScope derivation that previously lived separately in preview-match.ts
|
|
7
|
+
* and match-api.ts.
|
|
8
|
+
*
|
|
9
|
+
* resolveRoute() is the factory: given a pathname and dependencies, it returns
|
|
10
|
+
* a RouteSnapshot (or redirect/null). Consumers (createMatchContextForFull,
|
|
11
|
+
* createMatchContextForPartial, previewMatch) read snapshot fields instead of
|
|
12
|
+
* re-deriving them.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import type { CacheScope } from "../cache/cache-scope.js";
|
|
16
|
+
import { createCacheScope } from "../cache/cache-scope.js";
|
|
17
|
+
import type { EntryData, MetricsStore } from "../server/context.js";
|
|
18
|
+
import { loadManifest } from "./manifest.js";
|
|
19
|
+
import { collectRouteMiddleware } from "./middleware.js";
|
|
20
|
+
import type { CollectedMiddleware } from "./middleware-types.js";
|
|
21
|
+
import { traverseBack } from "./pattern-matching.js";
|
|
22
|
+
import type { RouteMatchResult } from "./pattern-matching.js";
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Immutable snapshot of a resolved route match.
|
|
26
|
+
*
|
|
27
|
+
* Contains everything derivable from (pathname, findMatch, loadManifest)
|
|
28
|
+
* without request context, navigation state, or intercept logic.
|
|
29
|
+
*/
|
|
30
|
+
export interface RouteSnapshot<TEnv = any> {
|
|
31
|
+
/** Raw match result from the trie/pattern matcher */
|
|
32
|
+
matched: RouteMatchResult<TEnv>;
|
|
33
|
+
/** Resolved manifest entry (with loaded handler, loader, etc.) */
|
|
34
|
+
manifestEntry: EntryData;
|
|
35
|
+
/** All entries in the route chain (from traverseBack) */
|
|
36
|
+
entries: EntryData[];
|
|
37
|
+
/** Canonical route key (e.g. "blog.detail") */
|
|
38
|
+
routeKey: string;
|
|
39
|
+
/** Last segment of a dotted route key (e.g. "detail" from "blog.detail") */
|
|
40
|
+
localRouteName: string;
|
|
41
|
+
/** Extracted route params */
|
|
42
|
+
params: Record<string, string>;
|
|
43
|
+
/** Collected route-level middleware from the entry tree */
|
|
44
|
+
routeMiddleware: CollectedMiddleware[];
|
|
45
|
+
/** Merged cache scope from the entry chain */
|
|
46
|
+
cacheScope: CacheScope | null;
|
|
47
|
+
/** Whether the matched route is a passthrough route */
|
|
48
|
+
isPassthrough: boolean;
|
|
49
|
+
/** Response type for non-RSC routes (e.g. "application/json") */
|
|
50
|
+
responseType?: string;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export type ResolveRouteResult<TEnv = any> =
|
|
54
|
+
| { type: "match"; snapshot: RouteSnapshot<TEnv> }
|
|
55
|
+
| { type: "redirect"; redirectTo: string }
|
|
56
|
+
| null;
|
|
57
|
+
|
|
58
|
+
export interface ResolveRouteDeps<TEnv = any> {
|
|
59
|
+
findMatch: (pathname: string) => RouteMatchResult<TEnv> | null;
|
|
60
|
+
metricsStore?: MetricsStore;
|
|
61
|
+
isSSR?: boolean;
|
|
62
|
+
/**
|
|
63
|
+
* When true, skip entries array and cacheScope chain construction.
|
|
64
|
+
* Used by previewMatch which only needs matched, manifestEntry,
|
|
65
|
+
* routeMiddleware, and responseType — avoids an extra traverseBack
|
|
66
|
+
* allocation and cacheScope composition on the hot classification path.
|
|
67
|
+
*/
|
|
68
|
+
lite?: boolean;
|
|
69
|
+
/**
|
|
70
|
+
* When true, skip pushing the "route-matching" metric internally.
|
|
71
|
+
* Used by createMatchContextForPartial on the fresh path (no snapshot
|
|
72
|
+
* reuse) so it can measure current + prev + intercept-source findMatch
|
|
73
|
+
* calls under one combined "route-matching" metric. On the reuse path,
|
|
74
|
+
* the partial path emits "route-matching:nav" for the prev +
|
|
75
|
+
* intercept-source lookups only (current-route resolution was done
|
|
76
|
+
* during classification without metrics).
|
|
77
|
+
*/
|
|
78
|
+
skipRouteMatchMetric?: boolean;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Resolve a pathname into a RouteSnapshot.
|
|
83
|
+
*
|
|
84
|
+
* This is the single source of truth for route derivation. It performs:
|
|
85
|
+
* 1. findMatch(pathname)
|
|
86
|
+
* 2. Redirect check
|
|
87
|
+
* 3. loadManifest
|
|
88
|
+
* 4. Passthrough detection
|
|
89
|
+
* 5. collectRouteMiddleware
|
|
90
|
+
* 6. Cache scope chain
|
|
91
|
+
* 7. responseType + localRouteName extraction
|
|
92
|
+
*
|
|
93
|
+
* Metrics timing is preserved identically to the previous inline code.
|
|
94
|
+
*/
|
|
95
|
+
export async function resolveRoute<TEnv = any>(
|
|
96
|
+
pathname: string,
|
|
97
|
+
deps: ResolveRouteDeps<TEnv>,
|
|
98
|
+
): Promise<ResolveRouteResult<TEnv>> {
|
|
99
|
+
const {
|
|
100
|
+
metricsStore,
|
|
101
|
+
isSSR = false,
|
|
102
|
+
lite = false,
|
|
103
|
+
skipRouteMatchMetric = false,
|
|
104
|
+
} = deps;
|
|
105
|
+
|
|
106
|
+
const routeMatchStart =
|
|
107
|
+
metricsStore && !skipRouteMatchMetric ? performance.now() : 0;
|
|
108
|
+
const matched = deps.findMatch(pathname);
|
|
109
|
+
if (metricsStore && !skipRouteMatchMetric) {
|
|
110
|
+
metricsStore.metrics.push({
|
|
111
|
+
label: "route-matching",
|
|
112
|
+
duration: performance.now() - routeMatchStart,
|
|
113
|
+
startTime: routeMatchStart - metricsStore.requestStart,
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
if (!matched) {
|
|
118
|
+
return null;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
if (matched.redirectTo) {
|
|
122
|
+
return { type: "redirect", redirectTo: matched.redirectTo };
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const manifestStart = metricsStore ? performance.now() : 0;
|
|
126
|
+
const manifestEntry = await loadManifest(
|
|
127
|
+
matched.entry,
|
|
128
|
+
matched.routeKey,
|
|
129
|
+
pathname,
|
|
130
|
+
metricsStore,
|
|
131
|
+
isSSR,
|
|
132
|
+
);
|
|
133
|
+
if (metricsStore) {
|
|
134
|
+
metricsStore.metrics.push({
|
|
135
|
+
label: "manifest-loading",
|
|
136
|
+
duration: performance.now() - manifestStart,
|
|
137
|
+
startTime: manifestStart - metricsStore.requestStart,
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
const isPassthrough =
|
|
142
|
+
manifestEntry.type === "route" && manifestEntry.isPassthrough === true;
|
|
143
|
+
|
|
144
|
+
let entries: EntryData[];
|
|
145
|
+
let cacheScope: CacheScope | null = null;
|
|
146
|
+
if (lite) {
|
|
147
|
+
entries = [];
|
|
148
|
+
} else {
|
|
149
|
+
({ entries, cacheScope } = buildEntriesAndCacheScope(manifestEntry));
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
const routeMiddleware = collectRouteMiddleware(
|
|
153
|
+
lite ? traverseBack(manifestEntry) : entries,
|
|
154
|
+
matched.params,
|
|
155
|
+
);
|
|
156
|
+
|
|
157
|
+
const responseType =
|
|
158
|
+
matched.responseType ||
|
|
159
|
+
(manifestEntry.type === "route" ? manifestEntry.responseType : undefined);
|
|
160
|
+
|
|
161
|
+
const localRouteName = matched.routeKey.includes(".")
|
|
162
|
+
? matched.routeKey.split(".").pop()!
|
|
163
|
+
: matched.routeKey;
|
|
164
|
+
|
|
165
|
+
return {
|
|
166
|
+
type: "match",
|
|
167
|
+
snapshot: {
|
|
168
|
+
matched,
|
|
169
|
+
manifestEntry,
|
|
170
|
+
entries,
|
|
171
|
+
routeKey: matched.routeKey,
|
|
172
|
+
localRouteName,
|
|
173
|
+
params: matched.params,
|
|
174
|
+
routeMiddleware,
|
|
175
|
+
cacheScope,
|
|
176
|
+
isPassthrough,
|
|
177
|
+
responseType,
|
|
178
|
+
},
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Fill in the entries and cacheScope fields on a lite snapshot.
|
|
184
|
+
*
|
|
185
|
+
* When classifyRequest produces a lite snapshot (entries=[], cacheScope=null),
|
|
186
|
+
* this function computes the missing fields from manifestEntry without
|
|
187
|
+
* re-running findMatch, loadManifest, or collectRouteMiddleware.
|
|
188
|
+
*
|
|
189
|
+
* If the snapshot already has entries, returns it as-is.
|
|
190
|
+
*/
|
|
191
|
+
export function ensureFullRouteSnapshot<TEnv = any>(
|
|
192
|
+
snapshot: RouteSnapshot<TEnv>,
|
|
193
|
+
): RouteSnapshot<TEnv> {
|
|
194
|
+
if (snapshot.entries.length > 0) {
|
|
195
|
+
return snapshot;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
const { entries, cacheScope } = buildEntriesAndCacheScope(
|
|
199
|
+
snapshot.manifestEntry,
|
|
200
|
+
);
|
|
201
|
+
return { ...snapshot, entries, cacheScope };
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* Materialize the entry chain and derive the merged cache scope.
|
|
206
|
+
* Shared by resolveRoute (non-lite) and ensureFullRouteSnapshot.
|
|
207
|
+
*/
|
|
208
|
+
function buildEntriesAndCacheScope(manifestEntry: EntryData): {
|
|
209
|
+
entries: EntryData[];
|
|
210
|
+
cacheScope: CacheScope | null;
|
|
211
|
+
} {
|
|
212
|
+
const entries = [...traverseBack(manifestEntry)];
|
|
213
|
+
let cacheScope: CacheScope | null = null;
|
|
214
|
+
for (const entry of entries) {
|
|
215
|
+
if (entry.cache) {
|
|
216
|
+
cacheScope = createCacheScope(entry.cache, cacheScope);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
return { entries, cacheScope };
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Test helper: create a RouteSnapshot with sensible defaults and overrides.
|
|
224
|
+
*/
|
|
225
|
+
export function createRouteSnapshot<TEnv = any>(
|
|
226
|
+
overrides?: Partial<RouteSnapshot<TEnv>>,
|
|
227
|
+
): RouteSnapshot<TEnv> {
|
|
228
|
+
return {
|
|
229
|
+
matched: {
|
|
230
|
+
entry: {} as any,
|
|
231
|
+
routeKey: "test",
|
|
232
|
+
params: {},
|
|
233
|
+
} as RouteMatchResult<TEnv>,
|
|
234
|
+
manifestEntry: { type: "route", shortCode: "R0", parent: null } as any,
|
|
235
|
+
entries: [],
|
|
236
|
+
routeKey: "test",
|
|
237
|
+
localRouteName: "test",
|
|
238
|
+
params: {},
|
|
239
|
+
routeMiddleware: [],
|
|
240
|
+
cacheScope: null,
|
|
241
|
+
isPassthrough: false,
|
|
242
|
+
...overrides,
|
|
243
|
+
};
|
|
244
|
+
}
|
|
@@ -19,6 +19,7 @@ import type {
|
|
|
19
19
|
} from "../types.js";
|
|
20
20
|
import type { RouteMatchResult } from "./pattern-matching.js";
|
|
21
21
|
import type { TelemetrySink } from "./telemetry.js";
|
|
22
|
+
import type { ResolveSegmentOptions } from "./segment-resolution.js";
|
|
22
23
|
|
|
23
24
|
/**
|
|
24
25
|
* Revalidation context passed to segment resolution
|
|
@@ -54,10 +55,8 @@ export interface InterceptResult {
|
|
|
54
55
|
* Instead of passing 20+ parameters, middleware calls getRouterContext() to access them.
|
|
55
56
|
*/
|
|
56
57
|
export interface RouterContext<TEnv = any> {
|
|
57
|
-
// Route matching
|
|
58
58
|
findMatch: (pathname: string) => RouteMatchResult | null;
|
|
59
59
|
|
|
60
|
-
// Manifest loading
|
|
61
60
|
loadManifest: (
|
|
62
61
|
entry: any,
|
|
63
62
|
routeKey: string,
|
|
@@ -66,10 +65,8 @@ export interface RouterContext<TEnv = any> {
|
|
|
66
65
|
isSSR?: boolean,
|
|
67
66
|
) => Promise<EntryData>;
|
|
68
67
|
|
|
69
|
-
// Entry traversal
|
|
70
68
|
traverseBack: (entry: EntryData) => Generator<EntryData>;
|
|
71
69
|
|
|
72
|
-
// Handler context creation
|
|
73
70
|
createHandlerContext: (
|
|
74
71
|
params: Record<string, string>,
|
|
75
72
|
request: Request,
|
|
@@ -83,7 +80,6 @@ export interface RouterContext<TEnv = any> {
|
|
|
83
80
|
isPassthroughRoute?: boolean,
|
|
84
81
|
) => HandlerContext<any, TEnv>;
|
|
85
82
|
|
|
86
|
-
// Loader setup
|
|
87
83
|
setupLoaderAccess: (
|
|
88
84
|
ctx: HandlerContext<any, TEnv>,
|
|
89
85
|
loaderPromises: Map<string, Promise<any>>,
|
|
@@ -94,7 +90,6 @@ export interface RouterContext<TEnv = any> {
|
|
|
94
90
|
loaderPromises: Map<string, Promise<any>>,
|
|
95
91
|
) => void;
|
|
96
92
|
|
|
97
|
-
// Context access
|
|
98
93
|
getContext: () => {
|
|
99
94
|
getOrCreateStore: (key: string) => any;
|
|
100
95
|
runWithStore: <T>(
|
|
@@ -105,16 +100,13 @@ export interface RouterContext<TEnv = any> {
|
|
|
105
100
|
) => T;
|
|
106
101
|
};
|
|
107
102
|
|
|
108
|
-
// Metrics
|
|
109
103
|
getMetricsStore: () => MetricsStore | undefined;
|
|
110
104
|
|
|
111
|
-
// Cache
|
|
112
105
|
createCacheScope: (
|
|
113
106
|
cacheConfig: any,
|
|
114
107
|
parent: CacheScope | null,
|
|
115
108
|
) => CacheScope | null;
|
|
116
109
|
|
|
117
|
-
// Intercept detection
|
|
118
110
|
findInterceptForRoute: (
|
|
119
111
|
routeKey: string,
|
|
120
112
|
parentEntry: EntryData | null,
|
|
@@ -122,7 +114,6 @@ export interface RouterContext<TEnv = any> {
|
|
|
122
114
|
isAction: boolean,
|
|
123
115
|
) => InterceptResult | null;
|
|
124
116
|
|
|
125
|
-
// Segment resolution (with revalidation)
|
|
126
117
|
resolveAllSegmentsWithRevalidation: (
|
|
127
118
|
entries: EntryData[],
|
|
128
119
|
routeKey: string,
|
|
@@ -133,7 +124,6 @@ export interface RouterContext<TEnv = any> {
|
|
|
133
124
|
request: Request,
|
|
134
125
|
prevUrl: URL,
|
|
135
126
|
nextUrl: URL,
|
|
136
|
-
loaderPromises: Map<string, Promise<any>>,
|
|
137
127
|
actionContext: any | undefined,
|
|
138
128
|
interceptResult: InterceptResult | null,
|
|
139
129
|
localRouteName: string,
|
|
@@ -164,14 +154,13 @@ export interface RouterContext<TEnv = any> {
|
|
|
164
154
|
handlerContext: HandlerContext<any, TEnv>,
|
|
165
155
|
belongsToRoute: boolean,
|
|
166
156
|
revalidationContext?: RevalidationContext,
|
|
157
|
+
options?: { skipMiddleware?: boolean },
|
|
167
158
|
) => Promise<ResolvedSegment[]>;
|
|
168
159
|
|
|
169
|
-
// Collect with markers
|
|
170
160
|
collectWithMarkers?: <T>(
|
|
171
161
|
gen: AsyncGenerator<T | { __type: "id"; id: string }>,
|
|
172
162
|
) => Promise<{ items: T[]; matchedIds: string[] }>;
|
|
173
163
|
|
|
174
|
-
// Revalidation evaluation
|
|
175
164
|
evaluateRevalidation: (params: {
|
|
176
165
|
segment: ResolvedSegment;
|
|
177
166
|
prevParams: Record<string, string>;
|
|
@@ -195,7 +184,6 @@ export interface RouterContext<TEnv = any> {
|
|
|
195
184
|
| "intercept-loader";
|
|
196
185
|
}) => Promise<boolean>;
|
|
197
186
|
|
|
198
|
-
// Request context
|
|
199
187
|
getRequestContext: () =>
|
|
200
188
|
| {
|
|
201
189
|
waitUntil: (fn: () => Promise<void>) => void;
|
|
@@ -203,16 +191,15 @@ export interface RouterContext<TEnv = any> {
|
|
|
203
191
|
}
|
|
204
192
|
| undefined;
|
|
205
193
|
|
|
206
|
-
// Simple segment resolution (without revalidation - for full match)
|
|
207
194
|
resolveAllSegments: (
|
|
208
195
|
entries: EntryData[],
|
|
209
196
|
routeKey: string,
|
|
210
197
|
params: Record<string, string>,
|
|
211
198
|
handlerContext: HandlerContext<any, TEnv>,
|
|
212
199
|
loaderPromises: Map<string, Promise<any>>,
|
|
200
|
+
options?: ResolveSegmentOptions,
|
|
213
201
|
) => Promise<ResolvedSegment[]>;
|
|
214
202
|
|
|
215
|
-
// Generator-based simple resolution
|
|
216
203
|
resolveAllSegmentsGenerator?: (
|
|
217
204
|
entries: EntryData[],
|
|
218
205
|
routeKey: string,
|
|
@@ -221,21 +208,17 @@ export interface RouterContext<TEnv = any> {
|
|
|
221
208
|
loaderPromises: Map<string, Promise<any>>,
|
|
222
209
|
) => AsyncGenerator<ResolvedSegment | { __type: "id"; id: string }>;
|
|
223
210
|
|
|
224
|
-
// Collect segments from generator
|
|
225
211
|
collectSegmentsFromGenerator?: <T>(
|
|
226
212
|
gen: AsyncGenerator<T | { __type: "id"; id: string }>,
|
|
227
213
|
) => Promise<T[]>;
|
|
228
214
|
|
|
229
|
-
// Handle store
|
|
230
215
|
createHandleStore: () => any;
|
|
231
216
|
|
|
232
|
-
// Loaders-only resolution (for full match cache hit - no revalidation)
|
|
233
217
|
resolveLoadersOnly?: (
|
|
234
218
|
entries: EntryData[],
|
|
235
219
|
handlerContext: HandlerContext<any, TEnv>,
|
|
236
220
|
) => Promise<ResolvedSegment[]>;
|
|
237
221
|
|
|
238
|
-
// Loaders-only resolution (for cache hit scenarios)
|
|
239
222
|
resolveLoadersOnlyWithRevalidation?: (
|
|
240
223
|
entries: EntryData[],
|
|
241
224
|
handlerContext: HandlerContext<any, TEnv>,
|
|
@@ -257,10 +240,8 @@ export interface RouterContext<TEnv = any> {
|
|
|
257
240
|
// Telemetry sink (optional, no-op when undefined)
|
|
258
241
|
telemetry?: TelemetrySink;
|
|
259
242
|
|
|
260
|
-
// Request ID for telemetry span correlation (set per-request in match handlers)
|
|
261
243
|
requestId?: string;
|
|
262
244
|
|
|
263
|
-
// Intercept loaders only (for cache hit + intercept scenarios)
|
|
264
245
|
resolveInterceptLoadersOnly?: (
|
|
265
246
|
intercept: InterceptEntry,
|
|
266
247
|
entry: EntryData,
|
|
@@ -283,7 +264,6 @@ export interface RouterContext<TEnv = any> {
|
|
|
283
264
|
} | null>;
|
|
284
265
|
}
|
|
285
266
|
|
|
286
|
-
// AsyncLocalStorage instance for router context
|
|
287
267
|
const routerContext = new AsyncLocalStorage<RouterContext<any>>();
|
|
288
268
|
|
|
289
269
|
/**
|
|
@@ -307,10 +287,6 @@ export function getRouterContext<TEnv = any>(): RouterContext<TEnv> {
|
|
|
307
287
|
*
|
|
308
288
|
* All async code within fn() can call getRouterContext() to access router closures.
|
|
309
289
|
* This works across async boundaries thanks to AsyncLocalStorage.
|
|
310
|
-
*
|
|
311
|
-
* @param deps Router dependencies to make available
|
|
312
|
-
* @param fn Function to run with dependencies available
|
|
313
|
-
* @returns Result of fn()
|
|
314
290
|
*/
|
|
315
291
|
export function runWithRouterContext<T, TEnv = any>(
|
|
316
292
|
deps: RouterContext<TEnv>,
|