@rangojs/router 0.0.0-experimental.79 → 0.0.0-experimental.7c7e4327
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 +301 -797
- package/dist/bin/rango.js +603 -145
- package/dist/testing/vitest.js +82 -0
- package/dist/vite/index.js +3750 -1160
- package/dist/vite/plugins/cloudflare-protocol-loader-hook.mjs +76 -0
- package/package.json +96 -24
- 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 +12 -10
- 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 +75 -19
- package/skills/layout/SKILL.md +40 -19
- package/skills/links/SKILL.md +247 -17
- package/skills/loader/SKILL.md +248 -10
- package/skills/middleware/SKILL.md +25 -13
- package/skills/migrate-nextjs/SKILL.md +205 -20
- package/skills/migrate-react-router/SKILL.md +59 -670
- 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 +40 -10
- package/skills/ppr/SKILL.md +616 -0
- package/skills/prerender/SKILL.md +72 -60
- package/skills/rango/SKILL.md +318 -26
- package/skills/react-compiler/SKILL.md +168 -0
- package/skills/response-routes/SKILL.md +138 -49
- package/skills/route/SKILL.md +117 -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 +0 -65
- 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 +94 -25
- package/src/browser/navigation-client.ts +144 -79
- 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 +183 -144
- package/src/browser/prefetch/cache.ts +242 -77
- package/src/browser/prefetch/fetch.ts +325 -69
- package/src/browser/prefetch/queue.ts +61 -12
- package/src/browser/rango-state.ts +158 -76
- package/src/browser/react/Link.tsx +58 -20
- 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 +17 -14
- 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 +37 -22
- package/src/browser/segment-reconciler.ts +31 -21
- 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 +203 -154
- 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 +152 -21
- 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 +1 -1
- 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 +421 -58
- 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 +2202 -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 +180 -99
- package/src/cache/vercel/index.ts +11 -0
- package/src/cache/vercel/vercel-cache-store.ts +1127 -0
- package/src/client.rsc.tsx +41 -21
- package/src/client.tsx +33 -61
- 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 +67 -37
- 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 +97 -12
- package/src/index.ts +98 -14
- 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 +32 -37
- package/src/prerender.ts +78 -10
- 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 -39
- package/src/root-error-boundary.tsx +1 -19
- package/src/route-content-wrapper.tsx +19 -77
- package/src/route-definition/dsl-helpers.ts +304 -309
- package/src/route-definition/helper-factories.ts +28 -140
- package/src/route-definition/helpers-types.ts +87 -59
- package/src/route-definition/index.ts +1 -2
- package/src/route-definition/redirect.ts +44 -11
- package/src/route-definition/resolve-handler-use.ts +12 -1
- package/src/route-definition/use-item-types.ts +29 -0
- package/src/route-map-builder.ts +41 -20
- package/src/route-types.ts +19 -46
- package/src/router/basename.ts +14 -0
- package/src/router/content-negotiation.ts +73 -25
- package/src/router/error-handling.ts +45 -18
- package/src/router/find-match.ts +129 -30
- package/src/router/handler-context.ts +27 -42
- package/src/router/instrument.ts +355 -0
- package/src/router/intercept-resolution.ts +39 -20
- package/src/router/lazy-includes.ts +82 -59
- package/src/router/loader-resolution.ts +167 -72
- package/src/router/logging.ts +0 -6
- package/src/router/manifest.ts +74 -40
- package/src/router/match-api.ts +80 -55
- 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 +159 -285
- 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 +0 -22
- package/src/router/match-pipelines.ts +1 -42
- package/src/router/match-result.ts +69 -79
- 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 +7 -56
- 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 +112 -67
- package/src/router/preview-match.ts +6 -2
- package/src/router/request-classification.ts +50 -69
- package/src/router/revalidation.ts +123 -73
- package/src/router/route-snapshot.ts +14 -3
- package/src/router/router-context.ts +6 -29
- package/src/router/router-interfaces.ts +115 -36
- package/src/router/router-options.ts +166 -5
- package/src/router/router-registry.ts +2 -5
- package/src/router/segment-resolution/fresh.ts +131 -86
- package/src/router/segment-resolution/helpers.ts +86 -6
- package/src/router/segment-resolution/loader-cache.ts +139 -39
- package/src/router/segment-resolution/loader-mask.ts +67 -0
- package/src/router/segment-resolution/loader-snapshot.ts +251 -0
- package/src/router/segment-resolution/revalidation.ts +272 -320
- 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 +157 -71
- package/src/rsc/full-payload.ts +70 -0
- package/src/rsc/handler-context.ts +3 -2
- package/src/rsc/handler.ts +291 -217
- 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 +114 -38
- 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 +124 -13
- 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 +421 -76
- package/src/rsc/runtime-warnings.ts +23 -10
- package/src/rsc/server-action.ts +282 -116
- package/src/rsc/shell-capture.ts +1158 -0
- package/src/rsc/shell-serve.ts +150 -0
- package/src/rsc/ssr-setup.ts +16 -0
- package/src/rsc/transition-gate.ts +89 -0
- package/src/rsc/types.ts +53 -5
- package/src/runtime-env.ts +18 -0
- package/src/search-params.ts +35 -30
- package/src/segment-loader-promise.ts +49 -4
- package/src/segment-system.tsx +350 -149
- package/src/serialize.ts +243 -0
- package/src/server/context.ts +208 -51
- package/src/server/cookie-parse.ts +32 -0
- package/src/server/cookie-store.ts +152 -5
- package/src/server/handle-store.ts +21 -38
- package/src/server/loader-registry.ts +33 -42
- package/src/server/request-context.ts +395 -176
- package/src/ssr/index.tsx +458 -178
- package/src/ssr/ssr-root.tsx +228 -0
- package/src/static-handler.ts +10 -13
- 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 +110 -62
- package/src/types/index.ts +3 -10
- package/src/types/loader-types.ts +11 -9
- package/src/types/request-scope.ts +112 -0
- package/src/types/route-config.ts +20 -52
- package/src/types/route-entry.ts +0 -6
- package/src/types/segments.ts +135 -14
- package/src/urls/include-helper.ts +19 -64
- package/src/urls/include-provider.ts +71 -0
- package/src/urls/index.ts +2 -11
- package/src/urls/path-helper-types.ts +63 -17
- package/src/urls/path-helper.ts +22 -106
- package/src/urls/pattern-types.ts +72 -19
- package/src/urls/response-types.ts +22 -29
- package/src/urls/type-extraction.ts +98 -154
- package/src/urls/urls-function.ts +1 -19
- package/src/use-loader.tsx +292 -107
- 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 +8 -7
- 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 +96 -68
- 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 +45 -1
- package/src/vite/discovery/virtual-module-codegen.ts +14 -34
- package/src/vite/index.ts +4 -0
- package/src/vite/inject-client-debug.ts +88 -0
- package/src/vite/plugin-types.ts +210 -10
- 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 +88 -55
- package/src/vite/plugins/expose-ids/export-analysis.ts +101 -34
- package/src/vite/plugins/expose-ids/handler-transform.ts +11 -90
- 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 +505 -486
- package/src/vite/plugins/performance-tracks.ts +26 -25
- package/src/vite/plugins/refresh-cmd.ts +1 -1
- 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 +236 -138
- package/src/vite/router-discovery.ts +927 -136
- 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 +71 -43
- 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
package/src/router/types.ts
CHANGED
|
@@ -22,27 +22,11 @@ import type {
|
|
|
22
22
|
ShouldRevalidateFn,
|
|
23
23
|
} from "../types";
|
|
24
24
|
|
|
25
|
-
/**
|
|
26
|
-
* Result of resolving loaders with revalidation
|
|
27
|
-
* Contains both segments to render and all matched segment IDs
|
|
28
|
-
*/
|
|
29
|
-
export interface LoaderRevalidationResult {
|
|
30
|
-
segments: ResolvedSegment[];
|
|
31
|
-
matchedIds: string[];
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Result of resolving segments with revalidation
|
|
36
|
-
* Contains both segments to render and all matched segment IDs
|
|
37
|
-
*/
|
|
38
25
|
export interface SegmentRevalidationResult {
|
|
39
26
|
segments: ResolvedSegment[];
|
|
40
27
|
matchedIds: string[];
|
|
41
28
|
}
|
|
42
29
|
|
|
43
|
-
/**
|
|
44
|
-
* Action context type for revalidation
|
|
45
|
-
*/
|
|
46
30
|
export type ActionContext = {
|
|
47
31
|
actionId?: string;
|
|
48
32
|
actionUrl?: URL;
|
|
@@ -50,23 +34,6 @@ export type ActionContext = {
|
|
|
50
34
|
formData?: FormData;
|
|
51
35
|
};
|
|
52
36
|
|
|
53
|
-
/**
|
|
54
|
-
* Dependencies passed to segment resolution functions
|
|
55
|
-
* These are created within createRouter and passed to extracted utilities
|
|
56
|
-
*/
|
|
57
|
-
export interface RouterDependencies<TEnv> {
|
|
58
|
-
findNearestErrorBoundary: (
|
|
59
|
-
entry: EntryData | null,
|
|
60
|
-
) => ReactNode | ErrorBoundaryHandler | null;
|
|
61
|
-
findNearestNotFoundBoundary: (
|
|
62
|
-
entry: EntryData | null,
|
|
63
|
-
) => ReactNode | NotFoundBoundaryHandler | null;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* Dependencies injected from createRouter closure into extracted segment resolution functions.
|
|
68
|
-
* These are the closure-bound helpers that cannot be imported directly.
|
|
69
|
-
*/
|
|
70
37
|
export interface SegmentResolutionDeps<TEnv = any> {
|
|
71
38
|
wrapLoaderPromise: <T>(
|
|
72
39
|
promise: Promise<T>,
|
|
@@ -98,23 +65,16 @@ export interface SegmentResolutionDeps<TEnv = any> {
|
|
|
98
65
|
) => ReactNode | NotFoundBoundaryHandler | null;
|
|
99
66
|
notFoundComponent?: ReactNode | ((props: { pathname: string }) => ReactNode);
|
|
100
67
|
callOnError: (error: unknown, phase: ErrorPhase, context: any) => void;
|
|
68
|
+
/**
|
|
69
|
+
* Router-level default for the per-segment `transition({ viewTransition })`
|
|
70
|
+
* flag, from createRouter({ viewTransition }). Resolved into each segment's
|
|
71
|
+
* transition config during resolution (only `false` is stamped) so the render
|
|
72
|
+
* gate reads the boundary decision off the segment on both server and client.
|
|
73
|
+
* Undefined is treated as "auto" (wrap).
|
|
74
|
+
*/
|
|
75
|
+
viewTransitionDefault?: "auto" | false;
|
|
101
76
|
}
|
|
102
77
|
|
|
103
|
-
/**
|
|
104
|
-
* Dependencies injected from createRouter closure into extracted intercept resolution functions.
|
|
105
|
-
*/
|
|
106
|
-
export interface InterceptResolutionDeps<TEnv = any> {
|
|
107
|
-
wrapLoaderPromise: SegmentResolutionDeps<TEnv>["wrapLoaderPromise"];
|
|
108
|
-
evaluateInterceptWhen: (
|
|
109
|
-
intercept: InterceptEntry,
|
|
110
|
-
selectorContext: InterceptSelectorContext | null,
|
|
111
|
-
isAction: boolean,
|
|
112
|
-
) => boolean;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
/**
|
|
116
|
-
* Dependencies injected from createRouter closure into extracted match API functions.
|
|
117
|
-
*/
|
|
118
78
|
export interface MatchApiDeps<TEnv = any> {
|
|
119
79
|
findMatch: (pathname: string, ms?: any) => any;
|
|
120
80
|
getMetricsStore: () => any;
|
|
@@ -129,23 +89,13 @@ export interface MatchApiDeps<TEnv = any> {
|
|
|
129
89
|
getRouteMap: () => Record<string, string>;
|
|
130
90
|
}
|
|
131
91
|
|
|
132
|
-
/**
|
|
133
|
-
* Title descriptor types for template support
|
|
134
|
-
*/
|
|
135
92
|
export type TitleDescriptor =
|
|
136
93
|
| string
|
|
137
94
|
| { template: string; default: string } // For layouts - template applied to child titles
|
|
138
|
-
| { absolute: string };
|
|
95
|
+
| { absolute: string };
|
|
139
96
|
|
|
140
|
-
/**
|
|
141
|
-
* Unset descriptor to remove inherited meta
|
|
142
|
-
* Key format matches getMetaKey output: "title", "name:description", "property:og:image"
|
|
143
|
-
*/
|
|
144
97
|
export type UnsetDescriptor = { unset: string };
|
|
145
98
|
|
|
146
|
-
/**
|
|
147
|
-
* Base meta descriptor types (sync values)
|
|
148
|
-
*/
|
|
149
99
|
export type MetaDescriptorBase =
|
|
150
100
|
| { charSet: "utf-8" }
|
|
151
101
|
| { title: TitleDescriptor }
|
|
@@ -157,10 +107,6 @@ export type MetaDescriptorBase =
|
|
|
157
107
|
| UnsetDescriptor
|
|
158
108
|
| { [name: string]: unknown };
|
|
159
109
|
|
|
160
|
-
/**
|
|
161
|
-
* Meta descriptor that can be sync or async.
|
|
162
|
-
* Use Promise<MetaDescriptorBase> for streaming meta that resolves after initial render.
|
|
163
|
-
*/
|
|
164
110
|
export type MetaDescriptor = MetaDescriptorBase | Promise<MetaDescriptorBase>;
|
|
165
111
|
|
|
166
112
|
type LdJsonObject = { [Key in string]: LdJsonValue } & {
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* URL param encode/decode at the route boundary.
|
|
3
|
+
*
|
|
4
|
+
* Extraction (decode): regex/trie matchers keep param values URL-encoded;
|
|
5
|
+
* `safeDecodeURIComponent` turns them back into raw strings so `ctx.params`
|
|
6
|
+
* matches the contract apps expect (Express/React Router/Fastify/Koa) and
|
|
7
|
+
* round-trips through reverse stay stable. Malformed %-encoding is
|
|
8
|
+
* preserved as-is so a broken URL doesn't crash matching.
|
|
9
|
+
*
|
|
10
|
+
* Reversal (encode): `encodePathSegment` escapes only what RFC 3986
|
|
11
|
+
* requires for a path segment — `/`, `?`, `#`, space, control chars,
|
|
12
|
+
* non-ASCII — and leaves pchar sub-delims (`@ : $ & + , ; =` and friends)
|
|
13
|
+
* readable. `encodeURIComponent` over-encodes for path segments, which
|
|
14
|
+
* makes generated URLs harder for humans to read in the address bar
|
|
15
|
+
* (e.g. mailbox IDs like `ivo@example.com` would become
|
|
16
|
+
* `ivo%40example.com` even though `@` is path-legal).
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
export function safeDecodeURIComponent(raw: string): string {
|
|
20
|
+
if (raw === "" || raw.indexOf("%") === -1) return raw;
|
|
21
|
+
try {
|
|
22
|
+
return decodeURIComponent(raw);
|
|
23
|
+
} catch {
|
|
24
|
+
return raw;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const PATH_SAFE_ESCAPES: Record<string, string> = {
|
|
29
|
+
"%3A": ":",
|
|
30
|
+
"%40": "@",
|
|
31
|
+
"%24": "$",
|
|
32
|
+
"%26": "&",
|
|
33
|
+
"%2B": "+",
|
|
34
|
+
"%2C": ",",
|
|
35
|
+
"%3B": ";",
|
|
36
|
+
"%3D": "=",
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
export function encodePathSegment(value: string): string {
|
|
40
|
+
return encodeURIComponent(value).replace(
|
|
41
|
+
/%(?:3A|40|24|26|2B|2C|3B|3D)/gi,
|
|
42
|
+
(match) => PATH_SAFE_ESCAPES[match.toUpperCase()] ?? match,
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Encode a catch-all remainder: encode each `/`-separated segment but keep the
|
|
48
|
+
* separators, so `a/b c` -> `a/b%20c` (not `a%2Fb%20c`). Shared by the reverse
|
|
49
|
+
* helper and the build-time prerender substitution so both produce identical
|
|
50
|
+
* URLs. `encode` defaults to the path-safe `encodePathSegment`.
|
|
51
|
+
*/
|
|
52
|
+
export function encodePathRemainder(
|
|
53
|
+
value: string,
|
|
54
|
+
encode: (segment: string) => string = encodePathSegment,
|
|
55
|
+
): string {
|
|
56
|
+
return value.split("/").map(encode).join("/");
|
|
57
|
+
}
|
package/src/router.ts
CHANGED
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
import { type ReactNode } from "react";
|
|
2
2
|
import { createCacheScope } from "./cache/cache-scope.js";
|
|
3
|
-
import {
|
|
4
|
-
setCacheProfiles,
|
|
5
|
-
resolveCacheProfiles,
|
|
6
|
-
} from "./cache/profile-registry.js";
|
|
3
|
+
import { resolveCacheProfiles } from "./cache/profile-registry.js";
|
|
7
4
|
import { isCachedFunction } from "./cache/taint.js";
|
|
8
5
|
import { assertClientComponent } from "./component-utils.js";
|
|
9
6
|
import { DefaultDocument } from "./components/DefaultDocument.js";
|
|
@@ -21,11 +18,11 @@ import type { AllUseItems } from "./route-types.js";
|
|
|
21
18
|
import type { UrlPatterns } from "./urls.js";
|
|
22
19
|
import type { UrlBuilder } from "./urls/pattern-types.js";
|
|
23
20
|
import { urls } from "./urls.js";
|
|
21
|
+
import { buildPrecomputedByPrefix } from "./build/prefix-tree-utils.js";
|
|
24
22
|
import {
|
|
25
|
-
EntryData,
|
|
26
|
-
InterceptSelectorContext,
|
|
23
|
+
type EntryData,
|
|
27
24
|
getContext,
|
|
28
|
-
|
|
25
|
+
RangoContext,
|
|
29
26
|
type MetricsStore,
|
|
30
27
|
} from "./server/context";
|
|
31
28
|
import { createHandleStore, type HandleStore } from "./server/handle-store.js";
|
|
@@ -57,6 +54,7 @@ import { buildDebugManifest } from "./router/debug-manifest.js";
|
|
|
57
54
|
|
|
58
55
|
import type { SegmentResolutionDeps, MatchApiDeps } from "./router/types.js";
|
|
59
56
|
import { createHandlerContext } from "./router/handler-context.js";
|
|
57
|
+
import { normalizeBasename } from "./router/basename.js";
|
|
60
58
|
import {
|
|
61
59
|
setupLoaderAccess,
|
|
62
60
|
setupLoaderAccessSilent,
|
|
@@ -65,15 +63,17 @@ import {
|
|
|
65
63
|
import { loadManifest } from "./router/manifest.js";
|
|
66
64
|
import { createMetricsStore } from "./router/metrics.js";
|
|
67
65
|
import {
|
|
68
|
-
|
|
66
|
+
compileMiddlewarePattern,
|
|
69
67
|
type MiddlewareEntry,
|
|
70
68
|
type MiddlewareFn,
|
|
71
69
|
} from "./router/middleware.js";
|
|
72
70
|
import {
|
|
73
71
|
extractStaticPrefix,
|
|
72
|
+
joinPrefix,
|
|
74
73
|
traverseBack,
|
|
75
74
|
} from "./router/pattern-matching.js";
|
|
76
75
|
import { resolveSink, safeEmit, getRequestId } from "./router/telemetry.js";
|
|
76
|
+
import { resolveTracing } from "./router/tracing.js";
|
|
77
77
|
import { evaluateRevalidation } from "./router/revalidation.js";
|
|
78
78
|
import {
|
|
79
79
|
type RouterContext,
|
|
@@ -91,13 +91,10 @@ import {
|
|
|
91
91
|
RouterRegistry,
|
|
92
92
|
nextRouterAutoId,
|
|
93
93
|
} from "./router/router-registry.js";
|
|
94
|
+
import type { RangoOptions, RootLayoutProps } from "./router/router-options.js";
|
|
94
95
|
import type {
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
} from "./router/router-options.js";
|
|
98
|
-
import type {
|
|
99
|
-
RSCRouter,
|
|
100
|
-
RSCRouterInternal,
|
|
96
|
+
Rango,
|
|
97
|
+
RangoInternal,
|
|
101
98
|
RouterRequestInput,
|
|
102
99
|
} from "./router/router-interfaces.js";
|
|
103
100
|
|
|
@@ -112,26 +109,32 @@ import {
|
|
|
112
109
|
matchForPrerender as _matchForPrerender,
|
|
113
110
|
renderStaticSegment as _renderStaticSegment,
|
|
114
111
|
} from "./router/prerender-match.js";
|
|
112
|
+
import { resolveStateCookieName } from "./router/state-cookie-name.js";
|
|
113
|
+
import { resolvePrefetchCacheTTL } from "./router/prefetch-cache-ttl.js";
|
|
114
|
+
import {
|
|
115
|
+
resolvePrefetchCacheSize,
|
|
116
|
+
resolvePrefetchConcurrency,
|
|
117
|
+
} from "./router/prefetch-limits.js";
|
|
115
118
|
|
|
116
119
|
// Re-export public types and values from extracted modules
|
|
117
120
|
export { RSC_ROUTER_BRAND, RouterRegistry } from "./router/router-registry.js";
|
|
118
121
|
export type {
|
|
119
|
-
|
|
122
|
+
RangoOptions,
|
|
120
123
|
RootLayoutProps,
|
|
121
124
|
SSRStreamMode,
|
|
122
125
|
SSROptions,
|
|
123
126
|
ResolveStreamingContext,
|
|
124
127
|
} from "./router/router-options.js";
|
|
125
128
|
export type {
|
|
126
|
-
|
|
127
|
-
|
|
129
|
+
Rango,
|
|
130
|
+
RangoInternal,
|
|
128
131
|
RouterRequestInput,
|
|
129
132
|
} from "./router/router-interfaces.js";
|
|
130
133
|
export { toInternal } from "./router/router-interfaces.js";
|
|
131
134
|
|
|
132
135
|
export function createRouter<TEnv = any>(
|
|
133
|
-
options:
|
|
134
|
-
):
|
|
136
|
+
options: RangoOptions<TEnv> = {},
|
|
137
|
+
): Rango<TEnv, {}> {
|
|
135
138
|
const {
|
|
136
139
|
id: userProvidedId,
|
|
137
140
|
$$id: injectedId,
|
|
@@ -151,31 +154,48 @@ export function createRouter<TEnv = any>(
|
|
|
151
154
|
nonce,
|
|
152
155
|
version,
|
|
153
156
|
prefetchCacheTTL: prefetchCacheTTLOption,
|
|
157
|
+
prefetchCacheSize: prefetchCacheSizeOption,
|
|
158
|
+
prefetchConcurrency: prefetchConcurrencyOption,
|
|
159
|
+
stateCookiePrefix: stateCookiePrefixOption,
|
|
154
160
|
warmup: warmupOption,
|
|
155
161
|
allowDebugManifest: allowDebugManifestOption = false,
|
|
156
162
|
telemetry: telemetrySink,
|
|
163
|
+
tracing: tracingOption,
|
|
157
164
|
ssr: ssrOption,
|
|
158
165
|
timeout: timeoutShorthand,
|
|
159
166
|
timeouts: timeoutsOption,
|
|
160
167
|
onTimeout,
|
|
161
168
|
originCheck: originCheckOption,
|
|
169
|
+
viewTransition: viewTransitionOption = "auto",
|
|
170
|
+
debugCacheSignal: debugCacheSignalOption = false,
|
|
171
|
+
strictMode: strictModeOption = true,
|
|
162
172
|
} = options;
|
|
163
173
|
|
|
174
|
+
// Debug cache signal gate (DEVELOPMENT/TEST ONLY). Enabled by the
|
|
175
|
+
// debugCacheSignal option OR the RANGO_TEST_SIGNALS=1 env flag. When off,
|
|
176
|
+
// no X-Rango-Cache header is emitted and output is byte-identical.
|
|
177
|
+
const cacheSignalEnabled =
|
|
178
|
+
debugCacheSignalOption ||
|
|
179
|
+
(typeof process !== "undefined" &&
|
|
180
|
+
(process as { env?: Record<string, string | undefined> }).env
|
|
181
|
+
?.RANGO_TEST_SIGNALS === "1");
|
|
182
|
+
|
|
164
183
|
// Normalize basename: ensure leading slash, strip trailing slash.
|
|
165
|
-
// A bare "/" is equivalent to no basename.
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
? "/" + basenameOption.replace(/^\/+|\/+$/g, "")
|
|
169
|
-
: undefined;
|
|
184
|
+
// A bare "/" is equivalent to no basename. Shared with the testing
|
|
185
|
+
// primitives via normalizeBasename so they can never drift.
|
|
186
|
+
const basename = normalizeBasename(basenameOption);
|
|
170
187
|
|
|
171
188
|
// Resolve telemetry sink (no-op when not configured)
|
|
172
189
|
const telemetry = resolveSink(telemetrySink);
|
|
173
190
|
|
|
174
|
-
// Resolve
|
|
175
|
-
//
|
|
176
|
-
|
|
191
|
+
// Resolve span tracing (undefined when not configured; every traceSpan() call
|
|
192
|
+
// is then a direct pass-through with zero behavior change).
|
|
193
|
+
const resolvedTracing = resolveTracing(tracingOption);
|
|
194
|
+
|
|
195
|
+
// Resolve cache profiles: merge user config with the guaranteed default
|
|
196
|
+
// profile. This resolved map is threaded onto each request context; the
|
|
197
|
+
// "use cache: <profile>" runtime path reads it request-scoped.
|
|
177
198
|
const resolvedCacheProfiles = resolveCacheProfiles(cacheProfilesOption);
|
|
178
|
-
setCacheProfiles(resolvedCacheProfiles);
|
|
179
199
|
|
|
180
200
|
// Source file: prefer Vite-injected path (zero cost), fall back to
|
|
181
201
|
// stack trace parsing for non-Vite environments (e.g. tests).
|
|
@@ -210,21 +230,40 @@ export function createRouter<TEnv = any>(
|
|
|
210
230
|
const routerId =
|
|
211
231
|
userProvidedId ?? injectedId ?? `router_${nextRouterAutoId()}`;
|
|
212
232
|
|
|
213
|
-
// Resolve
|
|
214
|
-
//
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
233
|
+
// Resolve the rango state cookie name once, here, so the two cookie writers
|
|
234
|
+
// (the client document.cookie writer and the server Set-Cookie writer)
|
|
235
|
+
// consume one pre-composed name and cannot drift.
|
|
236
|
+
const resolvedStateCookieName = resolveStateCookieName(
|
|
237
|
+
stateCookiePrefixOption,
|
|
238
|
+
routerId,
|
|
239
|
+
);
|
|
240
|
+
|
|
241
|
+
// Resolve prefetch cache TTL (default: 300 seconds / 5 minutes). Clamps to a
|
|
242
|
+
// non-negative integer and guards non-finite (NaN/Infinity) inputs so a
|
|
243
|
+
// malformed `Cache-Control: max-age=NaN` can never reach the wire.
|
|
244
|
+
const resolvedPrefetchCacheTTL = resolvePrefetchCacheTTL(
|
|
245
|
+
prefetchCacheTTLOption,
|
|
246
|
+
);
|
|
247
|
+
const prefetchCacheTTL = resolvedPrefetchCacheTTL.ms;
|
|
220
248
|
const prefetchCacheControl: string | false =
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
249
|
+
resolvedPrefetchCacheTTL.cacheControl;
|
|
250
|
+
|
|
251
|
+
// Resolve client-side prefetch limits (in-memory cache size and queue
|
|
252
|
+
// concurrency). Both are positive-integer counts; sub-1/non-finite inputs
|
|
253
|
+
// fall back to the defaults. Shipped to the client in payload metadata.
|
|
254
|
+
const prefetchCacheSize = resolvePrefetchCacheSize(prefetchCacheSizeOption);
|
|
255
|
+
const prefetchConcurrency = resolvePrefetchConcurrency(
|
|
256
|
+
prefetchConcurrencyOption,
|
|
257
|
+
);
|
|
224
258
|
|
|
225
259
|
// Resolve warmup enabled flag (default: true)
|
|
226
260
|
const warmupEnabled = warmupOption !== false;
|
|
227
261
|
|
|
262
|
+
// Resolve StrictMode flag (default: true). Shipped to the client in payload
|
|
263
|
+
// metadata; the browser entry reads it once to decide whether to wrap the
|
|
264
|
+
// hydrated tree in React.StrictMode.
|
|
265
|
+
const strictMode = strictModeOption !== false;
|
|
266
|
+
|
|
228
267
|
// Resolve theme config (null if theme not enabled)
|
|
229
268
|
const resolvedThemeConfig = themeOption
|
|
230
269
|
? resolveThemeConfig(themeOption)
|
|
@@ -256,9 +295,14 @@ export function createRouter<TEnv = any>(
|
|
|
256
295
|
invokeOnError(onError, error, phase, context, "Router");
|
|
257
296
|
}
|
|
258
297
|
|
|
259
|
-
// Validate document is a client component
|
|
298
|
+
// Validate document is a client component. Under a test runner the "use
|
|
299
|
+
// client" transform has not run, so a real exported document has no marker;
|
|
300
|
+
// allowServerInTest lets the router construct in a bare unit test (for
|
|
301
|
+
// dispatch / assertGeneratedRoutesMatch) while a real build still throws.
|
|
260
302
|
if (documentOption !== undefined) {
|
|
261
|
-
assertClientComponent(documentOption, "document"
|
|
303
|
+
assertClientComponent(documentOption, "document", {
|
|
304
|
+
allowServerInTest: true,
|
|
305
|
+
});
|
|
262
306
|
}
|
|
263
307
|
|
|
264
308
|
// Use default document if none provided (keeps internal name as rootLayout)
|
|
@@ -322,7 +366,7 @@ export function createRouter<TEnv = any>(
|
|
|
322
366
|
let regex: RegExp | null = null;
|
|
323
367
|
let paramNames: string[] = [];
|
|
324
368
|
if (fullPattern) {
|
|
325
|
-
const parsed =
|
|
369
|
+
const parsed = compileMiddlewarePattern(fullPattern);
|
|
326
370
|
regex = parsed.regex;
|
|
327
371
|
paramNames = parsed.paramNames;
|
|
328
372
|
}
|
|
@@ -332,7 +376,6 @@ export function createRouter<TEnv = any>(
|
|
|
332
376
|
regex,
|
|
333
377
|
paramNames,
|
|
334
378
|
handler,
|
|
335
|
-
mountPrefix,
|
|
336
379
|
});
|
|
337
380
|
}
|
|
338
381
|
|
|
@@ -366,23 +409,28 @@ export function createRouter<TEnv = any>(
|
|
|
366
409
|
getRouterPrecomputedEntries(routerId) ?? getPrecomputedEntries();
|
|
367
410
|
if (current !== precomputedSource) {
|
|
368
411
|
precomputedSource = current;
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
412
|
+
// buildPrecomputedByPrefix drops any staticPrefix owned by more than one
|
|
413
|
+
// leaf include instead of collapsing it last-wins (which would mis-assign
|
|
414
|
+
// one include's routes to another's entry and 500 a valid sibling route).
|
|
415
|
+
// Such shared-prefix includes resolve via the handler path instead.
|
|
416
|
+
precomputedByPrefix = current ? buildPrecomputedByPrefix(current) : null;
|
|
372
417
|
}
|
|
373
418
|
return precomputedByPrefix;
|
|
374
419
|
}
|
|
375
420
|
|
|
376
421
|
// Wrapper to pass debugPerformance to external createMetricsStore.
|
|
377
422
|
// Also checks per-request flag set by ctx.debugPerformance() in middleware.
|
|
423
|
+
// With no active request context there is nowhere to hang the store, so return
|
|
424
|
+
// undefined: an orphan store would collect metrics no reader can reach (nothing
|
|
425
|
+
// holds it, and appendMetric(undefined, ...) is already a no-op).
|
|
378
426
|
const getMetricsStore = () => {
|
|
379
427
|
const reqCtx = _getRequestContext();
|
|
380
428
|
const enabled = debugPerformance || !!reqCtx?._debugPerformance;
|
|
381
|
-
if (!enabled) return undefined;
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
reqCtx._metricsStore ??= createMetricsStore(true);
|
|
429
|
+
if (!enabled || !reqCtx) return undefined;
|
|
430
|
+
// Anchor a mid-request store to the true request entry (reqCtx._handlerStart),
|
|
431
|
+
// not this call's performance.now(); undefined falls back to now() inside
|
|
432
|
+
// createMetricsStore (metrics.ts).
|
|
433
|
+
reqCtx._metricsStore ??= createMetricsStore(true, reqCtx._handlerStart);
|
|
386
434
|
return reqCtx._metricsStore;
|
|
387
435
|
};
|
|
388
436
|
|
|
@@ -393,11 +441,6 @@ export function createRouter<TEnv = any>(
|
|
|
393
441
|
const findNearestNotFoundBoundary = (entry: EntryData | null) =>
|
|
394
442
|
findNotFoundBoundary(entry, defaultNotFoundBoundary);
|
|
395
443
|
|
|
396
|
-
// Helper to get handleStore from request context
|
|
397
|
-
const getHandleStore = (): HandleStore | undefined => {
|
|
398
|
-
return _getRequestContext()?._handleStore;
|
|
399
|
-
};
|
|
400
|
-
|
|
401
444
|
// Track a pending handler promise (non-blocking).
|
|
402
445
|
// Attaches a side-effect .catch() to report streaming handler errors to onError
|
|
403
446
|
// without altering the rejection chain (React's streaming error boundary still handles it).
|
|
@@ -408,13 +451,14 @@ export function createRouter<TEnv = any>(
|
|
|
408
451
|
segmentType?: string;
|
|
409
452
|
},
|
|
410
453
|
): Promise<T> => {
|
|
411
|
-
|
|
454
|
+
// One ALS read serves both the store lookup and the onError closure.
|
|
455
|
+
const reqCtx = _getRequestContext();
|
|
456
|
+
const store = reqCtx?._handleStore;
|
|
412
457
|
const tracked = store ? store.track(promise) : promise;
|
|
413
458
|
|
|
414
459
|
// Report streaming handler errors to onError as a side-effect.
|
|
415
460
|
// The rejection still propagates to the RSC stream for client error boundaries.
|
|
416
461
|
// Captures request context eagerly (closure) so the catch handler has full context.
|
|
417
|
-
const reqCtx = _getRequestContext();
|
|
418
462
|
if (reqCtx && onError) {
|
|
419
463
|
tracked.catch((error) => {
|
|
420
464
|
callOnError(error, "handler", {
|
|
@@ -456,8 +500,12 @@ export function createRouter<TEnv = any>(
|
|
|
456
500
|
? getRequestId(errorContext.request)
|
|
457
501
|
: undefined
|
|
458
502
|
: undefined;
|
|
503
|
+
// Derived once here for both the loader.start and loader.end emits (the
|
|
504
|
+
// loader.error emit uses ctx.loaderName from wrapLoaderWithErrorHandling).
|
|
505
|
+
const loaderName = telemetrySink
|
|
506
|
+
? segmentId.split(".").pop() || "unknown"
|
|
507
|
+
: "";
|
|
459
508
|
if (telemetrySink) {
|
|
460
|
-
const loaderName = segmentId.split(".").pop() || "unknown";
|
|
461
509
|
safeEmit(telemetry, {
|
|
462
510
|
type: "loader.start",
|
|
463
511
|
timestamp: loaderStart,
|
|
@@ -511,7 +559,6 @@ export function createRouter<TEnv = any>(
|
|
|
511
559
|
|
|
512
560
|
// Emit loader.end after the promise settles (fire-and-forget)
|
|
513
561
|
if (telemetrySink) {
|
|
514
|
-
const loaderName = segmentId.split(".").pop() || "unknown";
|
|
515
562
|
result.then((r) => {
|
|
516
563
|
safeEmit(telemetry, {
|
|
517
564
|
type: "loader.end",
|
|
@@ -538,6 +585,7 @@ export function createRouter<TEnv = any>(
|
|
|
538
585
|
findNearestNotFoundBoundary,
|
|
539
586
|
notFoundComponent: notFound,
|
|
540
587
|
callOnError,
|
|
588
|
+
viewTransitionDefault: viewTransitionOption,
|
|
541
589
|
};
|
|
542
590
|
|
|
543
591
|
// Match API dependencies
|
|
@@ -574,8 +622,15 @@ export function createRouter<TEnv = any>(
|
|
|
574
622
|
routerId,
|
|
575
623
|
};
|
|
576
624
|
|
|
577
|
-
|
|
578
|
-
|
|
625
|
+
// Must return the Promise from _evaluateLazyEntry: an async include provider
|
|
626
|
+
// (`() => import("./routes")`) resolves off the startup path, and createFindMatch
|
|
627
|
+
// awaits this to know when the import + expansion have completed. Dropping it
|
|
628
|
+
// (typing this `void`) makes the import fire-and-forget, so findMatch spins the
|
|
629
|
+
// lazy-eval retry loop to its cap and returns null on the first request to any
|
|
630
|
+
// async include whose prefix isn't already covered by a unique precomputed entry
|
|
631
|
+
// (nested includes, shared prefixes, regex fallback).
|
|
632
|
+
function evaluateLazyEntry(entry: RouteEntry<TEnv>): void | Promise<void> {
|
|
633
|
+
return _evaluateLazyEntry(entry, lazyEvalDeps);
|
|
579
634
|
}
|
|
580
635
|
|
|
581
636
|
// Create findMatch with single-entry cache, bound to router state
|
|
@@ -665,6 +720,7 @@ export function createRouter<TEnv = any>(
|
|
|
665
720
|
findMatch,
|
|
666
721
|
findInterceptForRoute,
|
|
667
722
|
telemetry: telemetrySink,
|
|
723
|
+
cacheSignalEnabled,
|
|
668
724
|
});
|
|
669
725
|
|
|
670
726
|
const { match, matchPartial, matchError, previewMatch } = matchHandlers;
|
|
@@ -674,7 +730,7 @@ export function createRouter<TEnv = any>(
|
|
|
674
730
|
* The type system tracks accumulated routes through the builder chain
|
|
675
731
|
* Initial TRoutes is {} (empty) to avoid poisoning accumulated types with Record<string, string>
|
|
676
732
|
*/
|
|
677
|
-
const router:
|
|
733
|
+
const router: RangoInternal<TEnv, {}> = {
|
|
678
734
|
__brand: RSC_ROUTER_BRAND,
|
|
679
735
|
id: routerId,
|
|
680
736
|
basename,
|
|
@@ -722,7 +778,7 @@ export function createRouter<TEnv = any>(
|
|
|
722
778
|
};
|
|
723
779
|
|
|
724
780
|
let handlerResult: AllUseItems[] = [];
|
|
725
|
-
|
|
781
|
+
RangoContext.run(
|
|
726
782
|
{
|
|
727
783
|
manifest,
|
|
728
784
|
patterns: routePatterns,
|
|
@@ -834,10 +890,13 @@ export function createRouter<TEnv = any>(
|
|
|
834
890
|
|
|
835
891
|
// Create placeholder RouteEntry for each lazy include
|
|
836
892
|
for (const lazyInclude of lazyIncludes) {
|
|
837
|
-
// Compute the full URL prefix (combining parent prefix if any)
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
893
|
+
// Compute the full URL prefix (combining parent prefix if any). Use the
|
|
894
|
+
// slash-collapsing join so a trailing-slash parent prefix does not
|
|
895
|
+
// produce a double-slash staticPrefix the trie's sp can never match.
|
|
896
|
+
const fullPrefix = joinPrefix(
|
|
897
|
+
lazyInclude.context.urlPrefix,
|
|
898
|
+
lazyInclude.prefix,
|
|
899
|
+
);
|
|
841
900
|
|
|
842
901
|
const lazyEntry: RouteEntry<TEnv> & { _lazyPrefix?: string } = {
|
|
843
902
|
prefix: "",
|
|
@@ -932,13 +991,31 @@ export function createRouter<TEnv = any>(
|
|
|
932
991
|
// Expose prefetch cache settings
|
|
933
992
|
prefetchCacheControl,
|
|
934
993
|
prefetchCacheTTL,
|
|
994
|
+
prefetchCacheSize,
|
|
995
|
+
prefetchConcurrency,
|
|
996
|
+
|
|
997
|
+
// Expose the resolved rango state cookie name for the server-side writer
|
|
998
|
+
// (invalidateClientCache) and for shipping to the client in metadata.
|
|
999
|
+
resolvedStateCookieName,
|
|
935
1000
|
|
|
936
1001
|
// Expose warmup enabled flag for handler and client
|
|
937
1002
|
warmupEnabled,
|
|
938
1003
|
|
|
1004
|
+
// Expose StrictMode flag for the initial-render payload metadata
|
|
1005
|
+
strictMode,
|
|
1006
|
+
|
|
939
1007
|
// Expose router-wide performance debugging for request-level metrics setup
|
|
940
1008
|
debugPerformance,
|
|
941
1009
|
|
|
1010
|
+
// Expose resolved span tracing for the handler (Cloudflare custom spans)
|
|
1011
|
+
tracing: resolvedTracing,
|
|
1012
|
+
|
|
1013
|
+
// Expose the raw telemetry sink so handler-level emitters (timeout, origin
|
|
1014
|
+
// rejection, late-handle handler.error) can emit outside the match ALS.
|
|
1015
|
+
// Raw (not the resolveSink no-op wrapper) so router.telemetry stays
|
|
1016
|
+
// undefined when unconfigured and call sites gate on truthiness.
|
|
1017
|
+
telemetry: telemetrySink,
|
|
1018
|
+
|
|
942
1019
|
// Expose debug manifest flag for handler
|
|
943
1020
|
allowDebugManifest: allowDebugManifestOption,
|
|
944
1021
|
|
|
@@ -1000,6 +1077,13 @@ export function createRouter<TEnv = any>(
|
|
|
1000
1077
|
// Expose basename for runtime manifest generation
|
|
1001
1078
|
__basename: basename,
|
|
1002
1079
|
|
|
1080
|
+
// Expose router-level boundary defaults for build-time clientChunks
|
|
1081
|
+
// discovery (so a "use client" default boundary lands in app-fallback).
|
|
1082
|
+
// These are createRouter options, never pushed onto EntryData.
|
|
1083
|
+
__defaultErrorBoundary: defaultErrorBoundary,
|
|
1084
|
+
__defaultNotFoundBoundary: defaultNotFoundBoundary,
|
|
1085
|
+
__notFound: notFound,
|
|
1086
|
+
|
|
1003
1087
|
// RSC request handler (lazily created on first call)
|
|
1004
1088
|
fetch: (() => {
|
|
1005
1089
|
// Handler is created on first call and reused
|
|
@@ -1017,8 +1101,10 @@ export function createRouter<TEnv = any>(
|
|
|
1017
1101
|
if (!handler) {
|
|
1018
1102
|
// Lazy import deferred to first request to avoid dev mode issues
|
|
1019
1103
|
const { createRSCHandler } = await import("./rsc/handler.js");
|
|
1020
|
-
// Cast:
|
|
1021
|
-
//
|
|
1104
|
+
// Cast: createRSCHandler receives `router as any`, which erases TEnv
|
|
1105
|
+
// and infers its handler as RouterRequestInput<unknown>. Re-narrow the
|
|
1106
|
+
// returned handler to RouterRequestInput<TEnv> so the call below stays
|
|
1107
|
+
// typed. (The handler already accepts (request, RouterRequestInput).)
|
|
1022
1108
|
handler = createRSCHandler({
|
|
1023
1109
|
router: router as any,
|
|
1024
1110
|
cache,
|
|
@@ -1046,9 +1132,9 @@ export function createRouter<TEnv = any>(
|
|
|
1046
1132
|
|
|
1047
1133
|
// If urls option was provided, auto-register them
|
|
1048
1134
|
if (typeof urlsOption === "function") {
|
|
1049
|
-
return router.routes(urlsOption) as
|
|
1135
|
+
return router.routes(urlsOption) as Rango<TEnv, {}>;
|
|
1050
1136
|
} else if (urlsOption) {
|
|
1051
|
-
return router.routes(urlsOption) as
|
|
1137
|
+
return router.routes(urlsOption) as Rango<TEnv, {}>;
|
|
1052
1138
|
}
|
|
1053
1139
|
|
|
1054
1140
|
return router;
|