@rangojs/router 0.0.0-experimental.1878aa49 → 0.0.0-experimental.190fb30d
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 -4
- package/README.md +303 -741
- package/dist/bin/rango.js +605 -146
- package/dist/testing/vitest.js +82 -0
- package/dist/vite/index.js +4117 -1211
- package/dist/vite/index.js.bak +5448 -0
- package/dist/vite/plugins/cloudflare-protocol-loader-hook.mjs +76 -0
- package/package.json +86 -15
- package/skills/api-client/SKILL.md +211 -0
- package/skills/breadcrumbs/SKILL.md +85 -6
- package/skills/bundle-analysis/SKILL.md +159 -0
- package/skills/cache-guide/SKILL.md +228 -33
- package/skills/caching/SKILL.md +336 -19
- package/skills/catalog.json +271 -0
- package/skills/comparison/SKILL.md +50 -0
- package/skills/comparison/agents/openai.yaml +4 -0
- package/skills/comparison/references/framework-comparison.md +837 -0
- package/skills/composability/SKILL.md +110 -4
- package/skills/css/SKILL.md +76 -0
- package/skills/debug-manifest/SKILL.md +5 -3
- package/skills/defer-hydration/SKILL.md +235 -0
- package/skills/document-cache/SKILL.md +87 -56
- package/skills/fonts/SKILL.md +1 -1
- package/skills/handler-use/SKILL.md +364 -0
- package/skills/hooks/SKILL.md +73 -691
- package/skills/hooks/data.md +273 -0
- package/skills/hooks/handle-and-actions.md +103 -0
- package/skills/hooks/navigation.md +110 -0
- package/skills/hooks/outlets.md +41 -0
- package/skills/hooks/state.md +228 -0
- package/skills/hooks/urls.md +135 -0
- package/skills/host-router/SKILL.md +129 -27
- package/skills/i18n/SKILL.md +276 -0
- package/skills/intercept/SKILL.md +94 -18
- package/skills/layout/SKILL.md +62 -19
- package/skills/links/SKILL.md +247 -17
- package/skills/loader/SKILL.md +248 -10
- package/skills/middleware/SKILL.md +57 -16
- package/skills/migrate-nextjs/SKILL.md +745 -0
- package/skills/migrate-react-router/SKILL.md +153 -0
- package/skills/migrate-react-router/cloudflare-workers.md +129 -0
- package/skills/migrate-react-router/component-migration.md +196 -0
- package/skills/migrate-react-router/data-and-actions.md +225 -0
- package/skills/migrate-react-router/route-mapping.md +271 -0
- package/skills/mime-routes/SKILL.md +29 -2
- package/skills/observability/SKILL.md +202 -0
- package/skills/parallel/SKILL.md +99 -10
- package/skills/ppr/SKILL.md +618 -0
- package/skills/prerender/SKILL.md +178 -124
- package/skills/rango/SKILL.md +318 -24
- package/skills/react-compiler/SKILL.md +168 -0
- package/skills/response-routes/SKILL.md +138 -49
- package/skills/route/SKILL.md +141 -9
- package/skills/router-setup/SKILL.md +44 -9
- package/skills/scripts/SKILL.md +179 -0
- package/skills/server-actions/SKILL.md +776 -0
- package/skills/shell-manifest/SKILL.md +185 -0
- package/skills/streams-and-websockets/SKILL.md +283 -0
- package/skills/tailwind/SKILL.md +28 -4
- 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 +131 -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 +85 -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/theme/SKILL.md +1 -1
- package/skills/typesafety/SKILL.md +45 -626
- package/skills/typesafety/env-and-bindings.md +254 -0
- package/skills/typesafety/generated-files-and-cli.md +335 -0
- package/skills/typesafety/params-and-search.md +153 -0
- package/skills/typesafety/route-types.md +209 -0
- package/skills/use-cache/SKILL.md +74 -15
- package/skills/vercel/SKILL.md +128 -0
- 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/connection-warmup.ts +134 -0
- package/src/browser/cookie-name.ts +140 -0
- package/src/browser/event-controller.ts +252 -158
- 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/logging.ts +28 -0
- package/src/browser/merge-segment-loaders.ts +6 -4
- package/src/browser/navigation-bridge.ts +115 -27
- package/src/browser/navigation-client.ts +163 -70
- package/src/browser/navigation-store-handle.ts +38 -0
- package/src/browser/navigation-store.ts +161 -73
- package/src/browser/navigation-transaction.ts +9 -59
- package/src/browser/network-error-handler.ts +34 -7
- package/src/browser/partial-update.ts +186 -135
- package/src/browser/prefetch/cache.ts +246 -71
- package/src/browser/prefetch/fetch.ts +350 -38
- package/src/browser/prefetch/queue.ts +61 -12
- package/src/browser/rango-state.ts +158 -76
- package/src/browser/react/Link.tsx +70 -9
- package/src/browser/react/NavigationProvider.tsx +202 -120
- package/src/browser/react/ScrollRestoration.tsx +10 -6
- 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 +25 -3
- 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 +145 -28
- package/src/browser/scroll-restoration.ts +44 -27
- package/src/browser/segment-reconciler.ts +44 -12
- package/src/browser/segment-structure-assert.ts +2 -2
- package/src/browser/server-action-bridge.ts +236 -65
- package/src/browser/types.ts +102 -9
- package/src/browser/validate-redirect-origin.ts +43 -16
- package/src/build/collect-fallback-refs.ts +107 -0
- package/src/build/generate-manifest.ts +205 -159
- package/src/build/generate-route-types.ts +3 -1
- package/src/build/index.ts +11 -3
- package/src/build/prefix-tree-utils.ts +123 -0
- package/src/build/route-trie.ts +198 -41
- 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 +456 -62
- 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 +128 -51
- 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 +13 -21
- package/src/cache/cache-error.ts +104 -0
- package/src/cache/cache-key-utils.ts +58 -13
- package/src/cache/cache-policy.ts +108 -34
- package/src/cache/cache-runtime.ts +454 -101
- package/src/cache/cache-scope.ts +187 -96
- package/src/cache/cache-tag.ts +149 -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 +2206 -372
- 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 +126 -41
- package/src/cache/handle-snapshot.ts +70 -0
- package/src/cache/index.ts +23 -20
- package/src/cache/memory-segment-store.ts +243 -37
- package/src/cache/profile-registry.ts +46 -31
- package/src/cache/read-through-swr.ts +56 -12
- package/src/cache/segment-codec.ts +13 -21
- package/src/cache/shell-snapshot.ts +417 -0
- package/src/cache/tag-invalidation.ts +230 -0
- package/src/cache/types.ts +194 -99
- package/src/cache/vercel/index.ts +11 -0
- package/src/cache/vercel/vercel-cache-store.ts +1132 -0
- package/src/client.rsc.tsx +41 -21
- package/src/client.tsx +116 -290
- package/src/cloudflare/index.ts +11 -0
- package/src/cloudflare/tracing.ts +108 -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 +185 -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 +104 -34
- package/src/handles/MetaTags.tsx +24 -53
- package/src/handles/Scripts.tsx +183 -0
- package/src/handles/breadcrumbs.ts +35 -8
- package/src/handles/deferred-resolution.ts +127 -0
- package/src/handles/is-thenable.ts +18 -0
- package/src/handles/meta.ts +14 -40
- package/src/handles/script.ts +244 -0
- package/src/host/cookie-handler.ts +9 -60
- package/src/host/errors.ts +13 -22
- package/src/host/index.ts +9 -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 +100 -13
- package/src/index.ts +143 -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 +215 -86
- package/src/redirect-origin.ts +114 -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 +147 -72
- package/src/route-definition/index.ts +4 -2
- package/src/route-definition/redirect.ts +44 -11
- 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 +41 -20
- 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 +129 -30
- package/src/router/handler-context.ts +47 -22
- package/src/router/instrument.ts +355 -0
- package/src/router/intercept-resolution.ts +39 -20
- package/src/router/lazy-includes.ts +85 -62
- package/src/router/loader-resolution.ts +277 -54
- package/src/router/logging.ts +0 -6
- package/src/router/manifest.ts +97 -57
- package/src/router/match-api.ts +178 -218
- package/src/router/match-context.ts +0 -22
- package/src/router/match-handlers.ts +211 -165
- package/src/router/match-middleware/background-revalidation.ts +40 -24
- package/src/router/match-middleware/cache-lookup.ts +168 -277
- 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 +113 -45
- package/src/router/metrics.ts +0 -34
- package/src/router/middleware-types.ts +7 -134
- package/src/router/middleware.ts +298 -172
- package/src/router/navigation-snapshot.ts +133 -0
- package/src/router/params-util.ts +23 -0
- package/src/router/parse-pattern.ts +115 -0
- package/src/router/pattern-matching.ts +181 -150
- package/src/router/prefetch-cache-ttl.ts +51 -0
- package/src/router/prefetch-limits.ts +37 -0
- package/src/router/prerender-match.ts +201 -56
- package/src/router/preview-match.ts +35 -103
- package/src/router/request-classification.ts +291 -0
- package/src/router/revalidation.ts +123 -73
- package/src/router/route-snapshot.ts +256 -0
- package/src/router/router-context.ts +6 -29
- package/src/router/router-interfaces.ts +125 -35
- package/src/router/router-options.ts +166 -5
- package/src/router/router-registry.ts +2 -5
- package/src/router/segment-resolution/fresh.ts +188 -86
- package/src/router/segment-resolution/helpers.ts +86 -6
- package/src/router/segment-resolution/loader-cache.ts +155 -39
- package/src/router/segment-resolution/loader-mask.ts +67 -0
- package/src/router/segment-resolution/loader-snapshot.ts +308 -0
- package/src/router/segment-resolution/revalidation.ts +344 -319
- 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 +75 -0
- package/src/router/telemetry-otel.ts +160 -200
- package/src/router/telemetry.ts +105 -20
- package/src/router/timeout.ts +0 -20
- package/src/router/tracing.ts +215 -0
- package/src/router/trie-matching.ts +171 -59
- package/src/router/types.ts +9 -63
- package/src/router/url-params.ts +57 -0
- package/src/router.ts +170 -72
- package/src/rsc/full-payload.ts +70 -0
- package/src/rsc/handler-context.ts +3 -2
- package/src/rsc/handler.ts +678 -513
- 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 +29 -42
- package/src/rsc/nonce.ts +10 -1
- package/src/rsc/origin-guard.ts +39 -25
- package/src/rsc/progressive-enhancement.ts +134 -15
- package/src/rsc/redirect-guard.ts +100 -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 +497 -77
- package/src/rsc/runtime-warnings.ts +23 -10
- package/src/rsc/server-action.ts +286 -114
- package/src/rsc/shell-capture.ts +1166 -0
- package/src/rsc/shell-serve.ts +181 -0
- package/src/rsc/ssr-setup.ts +17 -1
- package/src/rsc/transition-gate.ts +89 -0
- package/src/rsc/types.ts +54 -5
- 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 +167 -0
- package/src/segment-system.tsx +355 -204
- package/src/serialize.ts +243 -0
- package/src/server/context.ts +247 -54
- package/src/server/cookie-parse.ts +32 -0
- package/src/server/cookie-store.ts +152 -5
- package/src/server/handle-store.ts +40 -38
- package/src/server/loader-registry.ts +33 -42
- package/src/server/request-context.ts +502 -161
- package/src/ssr/index.tsx +467 -178
- package/src/ssr/inject-rsc-eager.ts +167 -0
- package/src/ssr/ssr-root.tsx +228 -0
- package/src/static-handler.ts +27 -18
- package/src/testing/cache-status.ts +162 -0
- package/src/testing/collect-handle.ts +46 -0
- package/src/testing/dispatch.ts +813 -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 +199 -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 +584 -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 +56 -84
- 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 +13 -4
- package/src/types/error-types.ts +30 -90
- package/src/types/global-namespace.ts +54 -41
- package/src/types/handler-context.ts +120 -62
- package/src/types/index.ts +3 -10
- package/src/types/loader-types.ts +40 -10
- package/src/types/request-scope.ts +112 -0
- package/src/types/route-config.ts +20 -52
- package/src/types/route-entry.ts +12 -7
- package/src/types/segments.ts +136 -15
- package/src/urls/include-helper.ts +40 -75
- package/src/urls/include-provider.ts +71 -0
- package/src/urls/index.ts +2 -11
- package/src/urls/path-helper-types.ts +102 -23
- package/src/urls/path-helper.ts +62 -111
- package/src/urls/pattern-types.ts +72 -19
- package/src/urls/response-types.ts +25 -22
- package/src/urls/type-extraction.ts +98 -154
- package/src/urls/urls-function.ts +1 -19
- package/src/use-loader.tsx +346 -89
- package/src/vercel/index.ts +11 -0
- package/src/vercel/tracing.ts +88 -0
- package/src/vite/debug.ts +185 -0
- package/src/vite/discovery/bundle-postprocess.ts +36 -38
- package/src/vite/discovery/dev-prerender-cache.ts +117 -0
- package/src/vite/discovery/discover-routers.ts +127 -86
- package/src/vite/discovery/discovery-errors.ts +255 -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 +15 -0
- package/src/vite/inject-client-debug.ts +88 -0
- package/src/vite/plugin-types.ts +261 -6
- 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 +26 -25
- 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 +384 -0
- 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 +138 -27
- package/src/vite/rango.ts +238 -139
- package/src/vite/router-discovery.ts +1091 -159
- 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 +98 -38
- package/src/vite/utils/shared-utils.ts +142 -43
- 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,256 @@
|
|
|
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
|
+
* The isSSR flag the manifest was resolved with. Recorded so consumers can
|
|
53
|
+
* decide whether the snapshot is reusable: a snapshot resolved with isSSR
|
|
54
|
+
* differs (loading({ ssr: false }) entries) and is cached under a different
|
|
55
|
+
* manifest partition, so the full (document) path only reuses an isSSR:true
|
|
56
|
+
* snapshot and the partial path only reuses a non-isSSR one. Undefined on
|
|
57
|
+
* inline snapshots (redirect / not-found) that are never reused.
|
|
58
|
+
*/
|
|
59
|
+
isSSR?: boolean;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export type ResolveRouteResult<TEnv = any> =
|
|
63
|
+
| { type: "match"; snapshot: RouteSnapshot<TEnv> }
|
|
64
|
+
| { type: "redirect"; redirectTo: string }
|
|
65
|
+
| null;
|
|
66
|
+
|
|
67
|
+
export interface ResolveRouteDeps<TEnv = any> {
|
|
68
|
+
findMatch: (
|
|
69
|
+
pathname: string,
|
|
70
|
+
) => RouteMatchResult<TEnv> | null | Promise<RouteMatchResult<TEnv> | null>;
|
|
71
|
+
metricsStore?: MetricsStore;
|
|
72
|
+
isSSR?: boolean;
|
|
73
|
+
/**
|
|
74
|
+
* When true, skip entries array and cacheScope chain construction.
|
|
75
|
+
* Used by previewMatch which only needs matched, manifestEntry,
|
|
76
|
+
* routeMiddleware, and responseType — avoids an extra traverseBack
|
|
77
|
+
* allocation and cacheScope composition on the hot classification path.
|
|
78
|
+
*/
|
|
79
|
+
lite?: boolean;
|
|
80
|
+
/**
|
|
81
|
+
* When true, skip pushing the "route-matching" metric internally.
|
|
82
|
+
* Used by createMatchContextForPartial on the fresh path (no snapshot
|
|
83
|
+
* reuse) so it can measure current + prev + intercept-source findMatch
|
|
84
|
+
* calls under one combined "route-matching" metric. On the reuse path,
|
|
85
|
+
* the partial path emits "route-matching:nav" for the prev +
|
|
86
|
+
* intercept-source lookups only (current-route resolution was done
|
|
87
|
+
* during classification without metrics).
|
|
88
|
+
*/
|
|
89
|
+
skipRouteMatchMetric?: boolean;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Resolve a pathname into a RouteSnapshot.
|
|
94
|
+
*
|
|
95
|
+
* This is the single source of truth for route derivation. It performs:
|
|
96
|
+
* 1. findMatch(pathname)
|
|
97
|
+
* 2. Redirect check
|
|
98
|
+
* 3. loadManifest
|
|
99
|
+
* 4. Passthrough detection
|
|
100
|
+
* 5. collectRouteMiddleware
|
|
101
|
+
* 6. Cache scope chain
|
|
102
|
+
* 7. responseType + localRouteName extraction
|
|
103
|
+
*
|
|
104
|
+
* Metrics timing is preserved identically to the previous inline code.
|
|
105
|
+
*/
|
|
106
|
+
export async function resolveRoute<TEnv = any>(
|
|
107
|
+
pathname: string,
|
|
108
|
+
deps: ResolveRouteDeps<TEnv>,
|
|
109
|
+
): Promise<ResolveRouteResult<TEnv>> {
|
|
110
|
+
const {
|
|
111
|
+
metricsStore,
|
|
112
|
+
isSSR = false,
|
|
113
|
+
lite = false,
|
|
114
|
+
skipRouteMatchMetric = false,
|
|
115
|
+
} = deps;
|
|
116
|
+
|
|
117
|
+
const routeMatchStart =
|
|
118
|
+
metricsStore && !skipRouteMatchMetric ? performance.now() : 0;
|
|
119
|
+
const matched = await deps.findMatch(pathname);
|
|
120
|
+
if (metricsStore && !skipRouteMatchMetric) {
|
|
121
|
+
metricsStore.metrics.push({
|
|
122
|
+
label: "route-matching",
|
|
123
|
+
duration: performance.now() - routeMatchStart,
|
|
124
|
+
startTime: routeMatchStart - metricsStore.requestStart,
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
if (!matched) {
|
|
129
|
+
return null;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
if (matched.redirectTo) {
|
|
133
|
+
return { type: "redirect", redirectTo: matched.redirectTo };
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
const manifestStart = metricsStore ? performance.now() : 0;
|
|
137
|
+
const manifestEntry = await loadManifest(
|
|
138
|
+
matched.entry,
|
|
139
|
+
matched.routeKey,
|
|
140
|
+
pathname,
|
|
141
|
+
metricsStore,
|
|
142
|
+
isSSR,
|
|
143
|
+
);
|
|
144
|
+
if (metricsStore) {
|
|
145
|
+
metricsStore.metrics.push({
|
|
146
|
+
label: "manifest-loading",
|
|
147
|
+
duration: performance.now() - manifestStart,
|
|
148
|
+
startTime: manifestStart - metricsStore.requestStart,
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
const isPassthrough =
|
|
153
|
+
manifestEntry.type === "route" && manifestEntry.isPassthrough === true;
|
|
154
|
+
|
|
155
|
+
let entries: EntryData[];
|
|
156
|
+
let cacheScope: CacheScope | null = null;
|
|
157
|
+
if (lite) {
|
|
158
|
+
entries = [];
|
|
159
|
+
} else {
|
|
160
|
+
({ entries, cacheScope } = buildEntriesAndCacheScope(manifestEntry));
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
const routeMiddleware = collectRouteMiddleware(
|
|
164
|
+
lite ? traverseBack(manifestEntry) : entries,
|
|
165
|
+
matched.params,
|
|
166
|
+
);
|
|
167
|
+
|
|
168
|
+
const responseType =
|
|
169
|
+
matched.responseType ||
|
|
170
|
+
(manifestEntry.type === "route" ? manifestEntry.responseType : undefined);
|
|
171
|
+
|
|
172
|
+
const localRouteName = matched.routeKey.includes(".")
|
|
173
|
+
? matched.routeKey.split(".").pop()!
|
|
174
|
+
: matched.routeKey;
|
|
175
|
+
|
|
176
|
+
return {
|
|
177
|
+
type: "match",
|
|
178
|
+
snapshot: {
|
|
179
|
+
matched,
|
|
180
|
+
manifestEntry,
|
|
181
|
+
entries,
|
|
182
|
+
routeKey: matched.routeKey,
|
|
183
|
+
localRouteName,
|
|
184
|
+
params: matched.params,
|
|
185
|
+
routeMiddleware,
|
|
186
|
+
cacheScope,
|
|
187
|
+
isPassthrough,
|
|
188
|
+
responseType,
|
|
189
|
+
isSSR,
|
|
190
|
+
},
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* Fill in the entries and cacheScope fields on a lite snapshot.
|
|
196
|
+
*
|
|
197
|
+
* When classifyRequest produces a lite snapshot (entries=[], cacheScope=null),
|
|
198
|
+
* this function computes the missing fields from manifestEntry without
|
|
199
|
+
* re-running findMatch, loadManifest, or collectRouteMiddleware.
|
|
200
|
+
*
|
|
201
|
+
* If the snapshot already has entries, returns it as-is.
|
|
202
|
+
*/
|
|
203
|
+
export function ensureFullRouteSnapshot<TEnv = any>(
|
|
204
|
+
snapshot: RouteSnapshot<TEnv>,
|
|
205
|
+
): RouteSnapshot<TEnv> {
|
|
206
|
+
if (snapshot.entries.length > 0) {
|
|
207
|
+
return snapshot;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
const { entries, cacheScope } = buildEntriesAndCacheScope(
|
|
211
|
+
snapshot.manifestEntry,
|
|
212
|
+
);
|
|
213
|
+
return { ...snapshot, entries, cacheScope };
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* Materialize the entry chain and derive the merged cache scope.
|
|
218
|
+
* Shared by resolveRoute (non-lite) and ensureFullRouteSnapshot.
|
|
219
|
+
*/
|
|
220
|
+
function buildEntriesAndCacheScope(manifestEntry: EntryData): {
|
|
221
|
+
entries: EntryData[];
|
|
222
|
+
cacheScope: CacheScope | null;
|
|
223
|
+
} {
|
|
224
|
+
const entries = [...traverseBack(manifestEntry)];
|
|
225
|
+
let cacheScope: CacheScope | null = null;
|
|
226
|
+
for (const entry of entries) {
|
|
227
|
+
if (entry.cache) {
|
|
228
|
+
cacheScope = createCacheScope(entry.cache, cacheScope);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
return { entries, cacheScope };
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* Test helper: create a RouteSnapshot with sensible defaults and overrides.
|
|
236
|
+
*/
|
|
237
|
+
export function createRouteSnapshot<TEnv = any>(
|
|
238
|
+
overrides?: Partial<RouteSnapshot<TEnv>>,
|
|
239
|
+
): RouteSnapshot<TEnv> {
|
|
240
|
+
return {
|
|
241
|
+
matched: {
|
|
242
|
+
entry: {} as any,
|
|
243
|
+
routeKey: "test",
|
|
244
|
+
params: {},
|
|
245
|
+
} as RouteMatchResult<TEnv>,
|
|
246
|
+
manifestEntry: { type: "route", shortCode: "R0", parent: null } as any,
|
|
247
|
+
entries: [],
|
|
248
|
+
routeKey: "test",
|
|
249
|
+
localRouteName: "test",
|
|
250
|
+
params: {},
|
|
251
|
+
routeMiddleware: [],
|
|
252
|
+
cacheScope: null,
|
|
253
|
+
isPassthrough: false,
|
|
254
|
+
...overrides,
|
|
255
|
+
};
|
|
256
|
+
}
|
|
@@ -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,10 @@ 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
|
-
|
|
58
|
-
|
|
58
|
+
findMatch: (
|
|
59
|
+
pathname: string,
|
|
60
|
+
) => RouteMatchResult | null | Promise<RouteMatchResult | null>;
|
|
59
61
|
|
|
60
|
-
// Manifest loading
|
|
61
62
|
loadManifest: (
|
|
62
63
|
entry: any,
|
|
63
64
|
routeKey: string,
|
|
@@ -66,10 +67,8 @@ export interface RouterContext<TEnv = any> {
|
|
|
66
67
|
isSSR?: boolean,
|
|
67
68
|
) => Promise<EntryData>;
|
|
68
69
|
|
|
69
|
-
// Entry traversal
|
|
70
70
|
traverseBack: (entry: EntryData) => Generator<EntryData>;
|
|
71
71
|
|
|
72
|
-
// Handler context creation
|
|
73
72
|
createHandlerContext: (
|
|
74
73
|
params: Record<string, string>,
|
|
75
74
|
request: Request,
|
|
@@ -83,7 +82,6 @@ export interface RouterContext<TEnv = any> {
|
|
|
83
82
|
isPassthroughRoute?: boolean,
|
|
84
83
|
) => HandlerContext<any, TEnv>;
|
|
85
84
|
|
|
86
|
-
// Loader setup
|
|
87
85
|
setupLoaderAccess: (
|
|
88
86
|
ctx: HandlerContext<any, TEnv>,
|
|
89
87
|
loaderPromises: Map<string, Promise<any>>,
|
|
@@ -94,7 +92,6 @@ export interface RouterContext<TEnv = any> {
|
|
|
94
92
|
loaderPromises: Map<string, Promise<any>>,
|
|
95
93
|
) => void;
|
|
96
94
|
|
|
97
|
-
// Context access
|
|
98
95
|
getContext: () => {
|
|
99
96
|
getOrCreateStore: (key: string) => any;
|
|
100
97
|
runWithStore: <T>(
|
|
@@ -105,16 +102,13 @@ export interface RouterContext<TEnv = any> {
|
|
|
105
102
|
) => T;
|
|
106
103
|
};
|
|
107
104
|
|
|
108
|
-
// Metrics
|
|
109
105
|
getMetricsStore: () => MetricsStore | undefined;
|
|
110
106
|
|
|
111
|
-
// Cache
|
|
112
107
|
createCacheScope: (
|
|
113
108
|
cacheConfig: any,
|
|
114
109
|
parent: CacheScope | null,
|
|
115
110
|
) => CacheScope | null;
|
|
116
111
|
|
|
117
|
-
// Intercept detection
|
|
118
112
|
findInterceptForRoute: (
|
|
119
113
|
routeKey: string,
|
|
120
114
|
parentEntry: EntryData | null,
|
|
@@ -122,7 +116,6 @@ export interface RouterContext<TEnv = any> {
|
|
|
122
116
|
isAction: boolean,
|
|
123
117
|
) => InterceptResult | null;
|
|
124
118
|
|
|
125
|
-
// Segment resolution (with revalidation)
|
|
126
119
|
resolveAllSegmentsWithRevalidation: (
|
|
127
120
|
entries: EntryData[],
|
|
128
121
|
routeKey: string,
|
|
@@ -133,7 +126,6 @@ export interface RouterContext<TEnv = any> {
|
|
|
133
126
|
request: Request,
|
|
134
127
|
prevUrl: URL,
|
|
135
128
|
nextUrl: URL,
|
|
136
|
-
loaderPromises: Map<string, Promise<any>>,
|
|
137
129
|
actionContext: any | undefined,
|
|
138
130
|
interceptResult: InterceptResult | null,
|
|
139
131
|
localRouteName: string,
|
|
@@ -164,14 +156,13 @@ export interface RouterContext<TEnv = any> {
|
|
|
164
156
|
handlerContext: HandlerContext<any, TEnv>,
|
|
165
157
|
belongsToRoute: boolean,
|
|
166
158
|
revalidationContext?: RevalidationContext,
|
|
159
|
+
options?: { skipMiddleware?: boolean },
|
|
167
160
|
) => Promise<ResolvedSegment[]>;
|
|
168
161
|
|
|
169
|
-
// Collect with markers
|
|
170
162
|
collectWithMarkers?: <T>(
|
|
171
163
|
gen: AsyncGenerator<T | { __type: "id"; id: string }>,
|
|
172
164
|
) => Promise<{ items: T[]; matchedIds: string[] }>;
|
|
173
165
|
|
|
174
|
-
// Revalidation evaluation
|
|
175
166
|
evaluateRevalidation: (params: {
|
|
176
167
|
segment: ResolvedSegment;
|
|
177
168
|
prevParams: Record<string, string>;
|
|
@@ -195,7 +186,6 @@ export interface RouterContext<TEnv = any> {
|
|
|
195
186
|
| "intercept-loader";
|
|
196
187
|
}) => Promise<boolean>;
|
|
197
188
|
|
|
198
|
-
// Request context
|
|
199
189
|
getRequestContext: () =>
|
|
200
190
|
| {
|
|
201
191
|
waitUntil: (fn: () => Promise<void>) => void;
|
|
@@ -203,17 +193,15 @@ export interface RouterContext<TEnv = any> {
|
|
|
203
193
|
}
|
|
204
194
|
| undefined;
|
|
205
195
|
|
|
206
|
-
// Simple segment resolution (without revalidation - for full match)
|
|
207
196
|
resolveAllSegments: (
|
|
208
197
|
entries: EntryData[],
|
|
209
198
|
routeKey: string,
|
|
210
199
|
params: Record<string, string>,
|
|
211
200
|
handlerContext: HandlerContext<any, TEnv>,
|
|
212
201
|
loaderPromises: Map<string, Promise<any>>,
|
|
213
|
-
options?:
|
|
202
|
+
options?: ResolveSegmentOptions,
|
|
214
203
|
) => Promise<ResolvedSegment[]>;
|
|
215
204
|
|
|
216
|
-
// Generator-based simple resolution
|
|
217
205
|
resolveAllSegmentsGenerator?: (
|
|
218
206
|
entries: EntryData[],
|
|
219
207
|
routeKey: string,
|
|
@@ -222,21 +210,17 @@ export interface RouterContext<TEnv = any> {
|
|
|
222
210
|
loaderPromises: Map<string, Promise<any>>,
|
|
223
211
|
) => AsyncGenerator<ResolvedSegment | { __type: "id"; id: string }>;
|
|
224
212
|
|
|
225
|
-
// Collect segments from generator
|
|
226
213
|
collectSegmentsFromGenerator?: <T>(
|
|
227
214
|
gen: AsyncGenerator<T | { __type: "id"; id: string }>,
|
|
228
215
|
) => Promise<T[]>;
|
|
229
216
|
|
|
230
|
-
// Handle store
|
|
231
217
|
createHandleStore: () => any;
|
|
232
218
|
|
|
233
|
-
// Loaders-only resolution (for full match cache hit - no revalidation)
|
|
234
219
|
resolveLoadersOnly?: (
|
|
235
220
|
entries: EntryData[],
|
|
236
221
|
handlerContext: HandlerContext<any, TEnv>,
|
|
237
222
|
) => Promise<ResolvedSegment[]>;
|
|
238
223
|
|
|
239
|
-
// Loaders-only resolution (for cache hit scenarios)
|
|
240
224
|
resolveLoadersOnlyWithRevalidation?: (
|
|
241
225
|
entries: EntryData[],
|
|
242
226
|
handlerContext: HandlerContext<any, TEnv>,
|
|
@@ -258,10 +242,8 @@ export interface RouterContext<TEnv = any> {
|
|
|
258
242
|
// Telemetry sink (optional, no-op when undefined)
|
|
259
243
|
telemetry?: TelemetrySink;
|
|
260
244
|
|
|
261
|
-
// Request ID for telemetry span correlation (set per-request in match handlers)
|
|
262
245
|
requestId?: string;
|
|
263
246
|
|
|
264
|
-
// Intercept loaders only (for cache hit + intercept scenarios)
|
|
265
247
|
resolveInterceptLoadersOnly?: (
|
|
266
248
|
intercept: InterceptEntry,
|
|
267
249
|
entry: EntryData,
|
|
@@ -284,7 +266,6 @@ export interface RouterContext<TEnv = any> {
|
|
|
284
266
|
} | null>;
|
|
285
267
|
}
|
|
286
268
|
|
|
287
|
-
// AsyncLocalStorage instance for router context
|
|
288
269
|
const routerContext = new AsyncLocalStorage<RouterContext<any>>();
|
|
289
270
|
|
|
290
271
|
/**
|
|
@@ -308,10 +289,6 @@ export function getRouterContext<TEnv = any>(): RouterContext<TEnv> {
|
|
|
308
289
|
*
|
|
309
290
|
* All async code within fn() can call getRouterContext() to access router closures.
|
|
310
291
|
* This works across async boundaries thanks to AsyncLocalStorage.
|
|
311
|
-
*
|
|
312
|
-
* @param deps Router dependencies to make available
|
|
313
|
-
* @param fn Function to run with dependencies available
|
|
314
|
-
* @returns Result of fn()
|
|
315
292
|
*/
|
|
316
293
|
export function runWithRouterContext<T, TEnv = any>(
|
|
317
294
|
deps: RouterContext<TEnv>,
|