@rangojs/router 0.0.0-experimental.b9cb8739 → 0.0.0-experimental.bdaf10aa
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 +730 -184
- package/dist/testing/vitest.js +82 -0
- package/dist/vite/index.js +4344 -1335
- 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 +251 -24
- package/skills/caching/SKILL.md +375 -17
- 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 +249 -17
- package/skills/loader/SKILL.md +302 -54
- package/skills/middleware/SKILL.md +59 -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 +225 -10
- package/skills/ppr/SKILL.md +622 -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 +172 -9
- package/skills/router-setup/SKILL.md +131 -11
- 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 -616
- 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/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 +257 -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 +132 -33
- package/src/browser/navigation-client.ts +218 -68
- package/src/browser/navigation-store-handle.ts +38 -0
- package/src/browser/navigation-store.ts +203 -80
- package/src/browser/navigation-transaction.ts +18 -66
- package/src/browser/network-error-handler.ts +34 -7
- package/src/browser/partial-update.ts +241 -127
- package/src/browser/prefetch/cache.ts +271 -44
- package/src/browser/prefetch/fetch.ts +367 -40
- package/src/browser/prefetch/queue.ts +144 -23
- package/src/browser/prefetch/resource-ready.ts +77 -0
- package/src/browser/rango-state.ts +158 -76
- package/src/browser/react/Link.tsx +121 -16
- package/src/browser/react/NavigationProvider.tsx +240 -122
- package/src/browser/react/ScrollRestoration.tsx +10 -6
- package/src/browser/react/context.ts +7 -2
- 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 +272 -80
- package/src/browser/scroll-restoration.ts +56 -22
- package/src/browser/segment-reconciler.ts +44 -7
- package/src/browser/segment-structure-assert.ts +2 -2
- package/src/browser/server-action-bridge.ts +244 -71
- package/src/browser/types.ts +136 -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 +207 -158
- package/src/build/generate-route-types.ts +6 -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 +464 -63
- 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 +336 -110
- 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 -97
- package/src/cache/cache-scope.ts +235 -103
- 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 +2446 -170
- 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 +11 -17
- package/src/cache/document-cache.ts +144 -49
- package/src/cache/handle-snapshot.ts +70 -0
- package/src/cache/index.ts +24 -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/taint.ts +55 -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 +84 -2
- package/src/debug.ts +2 -2
- 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 +485 -303
- package/src/route-definition/helper-factories.ts +28 -140
- package/src/route-definition/helpers-types.ts +153 -77
- package/src/route-definition/index.ts +4 -2
- package/src/route-definition/redirect.ts +53 -12
- 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 +48 -21
- 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 +130 -29
- package/src/router/handler-context.ts +83 -39
- package/src/router/instrument.ts +355 -0
- package/src/router/intercept-resolution.ts +50 -24
- package/src/router/lazy-includes.ts +89 -63
- package/src/router/loader-resolution.ts +286 -56
- package/src/router/logging.ts +5 -8
- package/src/router/manifest.ts +105 -56
- 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 +66 -22
- package/src/router/match-middleware/cache-lookup.ts +214 -263
- package/src/router/match-middleware/cache-store.ts +105 -50
- package/src/router/match-middleware/intercept-resolution.ts +8 -28
- package/src/router/match-middleware/segment-resolution.ts +52 -18
- package/src/router/match-pipelines.ts +1 -42
- package/src/router/match-result.ts +128 -44
- package/src/router/metrics.ts +5 -34
- package/src/router/middleware-types.ts +13 -142
- package/src/router/middleware.ts +301 -177
- 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 +203 -58
- 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 +11 -29
- package/src/router/router-interfaces.ts +146 -35
- package/src/router/router-options.ts +202 -15
- package/src/router/router-registry.ts +2 -5
- package/src/router/segment-resolution/fresh.ts +301 -78
- package/src/router/segment-resolution/helpers.ts +115 -30
- package/src/router/segment-resolution/loader-cache.ts +156 -39
- package/src/router/segment-resolution/loader-mask.ts +60 -0
- package/src/router/segment-resolution/loader-snapshot.ts +259 -0
- package/src/router/segment-resolution/mask-nested.ts +83 -0
- package/src/router/segment-resolution/revalidation.ts +477 -385
- 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 +8 -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 +10 -63
- package/src/router/url-params.ts +57 -0
- package/src/router.ts +210 -71
- package/src/rsc/full-payload.ts +70 -0
- package/src/rsc/handler-context.ts +3 -2
- package/src/rsc/handler.ts +682 -508
- 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/nonce.ts +10 -1
- package/src/rsc/origin-guard.ts +39 -25
- package/src/rsc/progressive-enhancement.ts +138 -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 +509 -73
- package/src/rsc/runtime-warnings.ts +23 -10
- package/src/rsc/server-action.ts +287 -113
- package/src/rsc/shell-capture.ts +1190 -0
- package/src/rsc/shell-serve.ts +181 -0
- package/src/rsc/ssr-setup.ts +18 -2
- package/src/rsc/transition-gate.ts +89 -0
- package/src/rsc/types.ts +62 -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 +167 -0
- package/src/segment-system.tsx +449 -132
- package/src/serialize.ts +243 -0
- package/src/server/context.ts +367 -61
- 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 +38 -46
- package/src/server/request-context.ts +558 -173
- package/src/ssr/index.tsx +491 -174
- 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 +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 +20 -52
- package/src/types/route-entry.ts +19 -7
- package/src/types/segments.ts +137 -14
- 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 +84 -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 +130 -85
- 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 -6
- 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 +234 -62
- 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 +49 -98
- 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/vercel-output.ts +384 -0
- package/src/vite/plugins/version-injector.ts +40 -29
- package/src/vite/plugins/version-plugin.ts +46 -37
- package/src/vite/plugins/virtual-entries.ts +138 -27
- package/src/vite/rango.ts +353 -303
- package/src/vite/router-discovery.ts +1090 -166
- package/src/vite/utils/ast-handler-extract.ts +26 -35
- package/src/vite/utils/banner.ts +4 -4
- package/src/vite/utils/bundle-analysis.ts +10 -15
- package/src/vite/utils/client-chunks.ts +184 -0
- package/src/vite/utils/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 +144 -44
- 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.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";
|
|
@@ -19,11 +16,13 @@ import {
|
|
|
19
16
|
import MapRootLayout from "./server/root-layout.js";
|
|
20
17
|
import type { AllUseItems } from "./route-types.js";
|
|
21
18
|
import type { UrlPatterns } from "./urls.js";
|
|
19
|
+
import type { UrlBuilder } from "./urls/pattern-types.js";
|
|
20
|
+
import { urls } from "./urls.js";
|
|
21
|
+
import { buildPrecomputedByPrefix } from "./build/prefix-tree-utils.js";
|
|
22
22
|
import {
|
|
23
|
-
EntryData,
|
|
24
|
-
InterceptSelectorContext,
|
|
23
|
+
type EntryData,
|
|
25
24
|
getContext,
|
|
26
|
-
|
|
25
|
+
RangoContext,
|
|
27
26
|
type MetricsStore,
|
|
28
27
|
} from "./server/context";
|
|
29
28
|
import { createHandleStore, type HandleStore } from "./server/handle-store.js";
|
|
@@ -55,6 +54,7 @@ import { buildDebugManifest } from "./router/debug-manifest.js";
|
|
|
55
54
|
|
|
56
55
|
import type { SegmentResolutionDeps, MatchApiDeps } from "./router/types.js";
|
|
57
56
|
import { createHandlerContext } from "./router/handler-context.js";
|
|
57
|
+
import { normalizeBasename } from "./router/basename.js";
|
|
58
58
|
import {
|
|
59
59
|
setupLoaderAccess,
|
|
60
60
|
setupLoaderAccessSilent,
|
|
@@ -63,15 +63,17 @@ import {
|
|
|
63
63
|
import { loadManifest } from "./router/manifest.js";
|
|
64
64
|
import { createMetricsStore } from "./router/metrics.js";
|
|
65
65
|
import {
|
|
66
|
-
|
|
66
|
+
compileMiddlewarePattern,
|
|
67
67
|
type MiddlewareEntry,
|
|
68
68
|
type MiddlewareFn,
|
|
69
69
|
} from "./router/middleware.js";
|
|
70
70
|
import {
|
|
71
71
|
extractStaticPrefix,
|
|
72
|
+
joinPrefix,
|
|
72
73
|
traverseBack,
|
|
73
74
|
} from "./router/pattern-matching.js";
|
|
74
75
|
import { resolveSink, safeEmit, getRequestId } from "./router/telemetry.js";
|
|
76
|
+
import { resolveTracing } from "./router/tracing.js";
|
|
75
77
|
import { evaluateRevalidation } from "./router/revalidation.js";
|
|
76
78
|
import {
|
|
77
79
|
type RouterContext,
|
|
@@ -89,13 +91,10 @@ import {
|
|
|
89
91
|
RouterRegistry,
|
|
90
92
|
nextRouterAutoId,
|
|
91
93
|
} from "./router/router-registry.js";
|
|
94
|
+
import type { RangoOptions, RootLayoutProps } from "./router/router-options.js";
|
|
92
95
|
import type {
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
} from "./router/router-options.js";
|
|
96
|
-
import type {
|
|
97
|
-
RSCRouter,
|
|
98
|
-
RSCRouterInternal,
|
|
96
|
+
Rango,
|
|
97
|
+
RangoInternal,
|
|
99
98
|
RouterRequestInput,
|
|
100
99
|
} from "./router/router-interfaces.js";
|
|
101
100
|
|
|
@@ -110,29 +109,36 @@ import {
|
|
|
110
109
|
matchForPrerender as _matchForPrerender,
|
|
111
110
|
renderStaticSegment as _renderStaticSegment,
|
|
112
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";
|
|
113
118
|
|
|
114
119
|
// Re-export public types and values from extracted modules
|
|
115
120
|
export { RSC_ROUTER_BRAND, RouterRegistry } from "./router/router-registry.js";
|
|
116
121
|
export type {
|
|
117
|
-
|
|
122
|
+
RangoOptions,
|
|
118
123
|
RootLayoutProps,
|
|
119
124
|
SSRStreamMode,
|
|
120
125
|
SSROptions,
|
|
121
126
|
ResolveStreamingContext,
|
|
122
127
|
} from "./router/router-options.js";
|
|
123
128
|
export type {
|
|
124
|
-
|
|
125
|
-
|
|
129
|
+
Rango,
|
|
130
|
+
RangoInternal,
|
|
126
131
|
RouterRequestInput,
|
|
127
132
|
} from "./router/router-interfaces.js";
|
|
128
133
|
export { toInternal } from "./router/router-interfaces.js";
|
|
129
134
|
|
|
130
135
|
export function createRouter<TEnv = any>(
|
|
131
|
-
options:
|
|
132
|
-
):
|
|
136
|
+
options: RangoOptions<TEnv> = {},
|
|
137
|
+
): Rango<TEnv, {}> {
|
|
133
138
|
const {
|
|
134
139
|
id: userProvidedId,
|
|
135
140
|
$$id: injectedId,
|
|
141
|
+
basename: basenameOption,
|
|
136
142
|
debugPerformance = false,
|
|
137
143
|
document: documentOption,
|
|
138
144
|
defaultErrorBoundary,
|
|
@@ -148,24 +154,48 @@ export function createRouter<TEnv = any>(
|
|
|
148
154
|
nonce,
|
|
149
155
|
version,
|
|
150
156
|
prefetchCacheTTL: prefetchCacheTTLOption,
|
|
157
|
+
prefetchCacheSize: prefetchCacheSizeOption,
|
|
158
|
+
prefetchConcurrency: prefetchConcurrencyOption,
|
|
159
|
+
stateCookiePrefix: stateCookiePrefixOption,
|
|
151
160
|
warmup: warmupOption,
|
|
152
161
|
allowDebugManifest: allowDebugManifestOption = false,
|
|
153
162
|
telemetry: telemetrySink,
|
|
163
|
+
tracing: tracingOption,
|
|
154
164
|
ssr: ssrOption,
|
|
155
165
|
timeout: timeoutShorthand,
|
|
156
166
|
timeouts: timeoutsOption,
|
|
157
167
|
onTimeout,
|
|
158
168
|
originCheck: originCheckOption,
|
|
169
|
+
viewTransition: viewTransitionOption = "auto",
|
|
170
|
+
debugCacheSignal: debugCacheSignalOption = false,
|
|
171
|
+
strictMode: strictModeOption = true,
|
|
159
172
|
} = options;
|
|
160
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
|
+
|
|
183
|
+
// Normalize basename: ensure leading slash, strip trailing slash.
|
|
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);
|
|
187
|
+
|
|
161
188
|
// Resolve telemetry sink (no-op when not configured)
|
|
162
189
|
const telemetry = resolveSink(telemetrySink);
|
|
163
190
|
|
|
164
|
-
// Resolve
|
|
165
|
-
//
|
|
166
|
-
|
|
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.
|
|
167
198
|
const resolvedCacheProfiles = resolveCacheProfiles(cacheProfilesOption);
|
|
168
|
-
setCacheProfiles(resolvedCacheProfiles);
|
|
169
199
|
|
|
170
200
|
// Source file: prefer Vite-injected path (zero cost), fall back to
|
|
171
201
|
// stack trace parsing for non-Vite environments (e.g. tests).
|
|
@@ -200,21 +230,40 @@ export function createRouter<TEnv = any>(
|
|
|
200
230
|
const routerId =
|
|
201
231
|
userProvidedId ?? injectedId ?? `router_${nextRouterAutoId()}`;
|
|
202
232
|
|
|
203
|
-
// Resolve
|
|
204
|
-
//
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
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;
|
|
210
248
|
const prefetchCacheControl: string | false =
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
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
|
+
);
|
|
214
258
|
|
|
215
259
|
// Resolve warmup enabled flag (default: true)
|
|
216
260
|
const warmupEnabled = warmupOption !== false;
|
|
217
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
|
+
|
|
218
267
|
// Resolve theme config (null if theme not enabled)
|
|
219
268
|
const resolvedThemeConfig = themeOption
|
|
220
269
|
? resolveThemeConfig(themeOption)
|
|
@@ -246,9 +295,14 @@ export function createRouter<TEnv = any>(
|
|
|
246
295
|
invokeOnError(onError, error, phase, context, "Router");
|
|
247
296
|
}
|
|
248
297
|
|
|
249
|
-
// 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.
|
|
250
302
|
if (documentOption !== undefined) {
|
|
251
|
-
assertClientComponent(documentOption, "document"
|
|
303
|
+
assertClientComponent(documentOption, "document", {
|
|
304
|
+
allowServerInTest: true,
|
|
305
|
+
});
|
|
252
306
|
}
|
|
253
307
|
|
|
254
308
|
// Use default document if none provided (keeps internal name as rootLayout)
|
|
@@ -312,7 +366,7 @@ export function createRouter<TEnv = any>(
|
|
|
312
366
|
let regex: RegExp | null = null;
|
|
313
367
|
let paramNames: string[] = [];
|
|
314
368
|
if (fullPattern) {
|
|
315
|
-
const parsed =
|
|
369
|
+
const parsed = compileMiddlewarePattern(fullPattern);
|
|
316
370
|
regex = parsed.regex;
|
|
317
371
|
paramNames = parsed.paramNames;
|
|
318
372
|
}
|
|
@@ -322,7 +376,6 @@ export function createRouter<TEnv = any>(
|
|
|
322
376
|
regex,
|
|
323
377
|
paramNames,
|
|
324
378
|
handler,
|
|
325
|
-
mountPrefix,
|
|
326
379
|
});
|
|
327
380
|
}
|
|
328
381
|
|
|
@@ -356,23 +409,28 @@ export function createRouter<TEnv = any>(
|
|
|
356
409
|
getRouterPrecomputedEntries(routerId) ?? getPrecomputedEntries();
|
|
357
410
|
if (current !== precomputedSource) {
|
|
358
411
|
precomputedSource = current;
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
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;
|
|
362
417
|
}
|
|
363
418
|
return precomputedByPrefix;
|
|
364
419
|
}
|
|
365
420
|
|
|
366
421
|
// Wrapper to pass debugPerformance to external createMetricsStore.
|
|
367
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).
|
|
368
426
|
const getMetricsStore = () => {
|
|
369
427
|
const reqCtx = _getRequestContext();
|
|
370
428
|
const enabled = debugPerformance || !!reqCtx?._debugPerformance;
|
|
371
|
-
if (!enabled) return undefined;
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
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);
|
|
376
434
|
return reqCtx._metricsStore;
|
|
377
435
|
};
|
|
378
436
|
|
|
@@ -383,11 +441,6 @@ export function createRouter<TEnv = any>(
|
|
|
383
441
|
const findNearestNotFoundBoundary = (entry: EntryData | null) =>
|
|
384
442
|
findNotFoundBoundary(entry, defaultNotFoundBoundary);
|
|
385
443
|
|
|
386
|
-
// Helper to get handleStore from request context
|
|
387
|
-
const getHandleStore = (): HandleStore | undefined => {
|
|
388
|
-
return _getRequestContext()?._handleStore;
|
|
389
|
-
};
|
|
390
|
-
|
|
391
444
|
// Track a pending handler promise (non-blocking).
|
|
392
445
|
// Attaches a side-effect .catch() to report streaming handler errors to onError
|
|
393
446
|
// without altering the rejection chain (React's streaming error boundary still handles it).
|
|
@@ -398,13 +451,14 @@ export function createRouter<TEnv = any>(
|
|
|
398
451
|
segmentType?: string;
|
|
399
452
|
},
|
|
400
453
|
): Promise<T> => {
|
|
401
|
-
|
|
454
|
+
// One ALS read serves both the store lookup and the onError closure.
|
|
455
|
+
const reqCtx = _getRequestContext();
|
|
456
|
+
const store = reqCtx?._handleStore;
|
|
402
457
|
const tracked = store ? store.track(promise) : promise;
|
|
403
458
|
|
|
404
459
|
// Report streaming handler errors to onError as a side-effect.
|
|
405
460
|
// The rejection still propagates to the RSC stream for client error boundaries.
|
|
406
461
|
// Captures request context eagerly (closure) so the catch handler has full context.
|
|
407
|
-
const reqCtx = _getRequestContext();
|
|
408
462
|
if (reqCtx && onError) {
|
|
409
463
|
tracked.catch((error) => {
|
|
410
464
|
callOnError(error, "handler", {
|
|
@@ -446,8 +500,12 @@ export function createRouter<TEnv = any>(
|
|
|
446
500
|
? getRequestId(errorContext.request)
|
|
447
501
|
: undefined
|
|
448
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
|
+
: "";
|
|
449
508
|
if (telemetrySink) {
|
|
450
|
-
const loaderName = segmentId.split(".").pop() || "unknown";
|
|
451
509
|
safeEmit(telemetry, {
|
|
452
510
|
type: "loader.start",
|
|
453
511
|
timestamp: loaderStart,
|
|
@@ -501,7 +559,6 @@ export function createRouter<TEnv = any>(
|
|
|
501
559
|
|
|
502
560
|
// Emit loader.end after the promise settles (fire-and-forget)
|
|
503
561
|
if (telemetrySink) {
|
|
504
|
-
const loaderName = segmentId.split(".").pop() || "unknown";
|
|
505
562
|
result.then((r) => {
|
|
506
563
|
safeEmit(telemetry, {
|
|
507
564
|
type: "loader.end",
|
|
@@ -526,7 +583,9 @@ export function createRouter<TEnv = any>(
|
|
|
526
583
|
trackHandler,
|
|
527
584
|
findNearestErrorBoundary,
|
|
528
585
|
findNearestNotFoundBoundary,
|
|
586
|
+
notFoundComponent: notFound,
|
|
529
587
|
callOnError,
|
|
588
|
+
viewTransitionDefault: viewTransitionOption,
|
|
530
589
|
};
|
|
531
590
|
|
|
532
591
|
// Match API dependencies
|
|
@@ -560,10 +619,18 @@ export function createRouter<TEnv = any>(
|
|
|
560
619
|
mergedRouteMap,
|
|
561
620
|
nextMountIndex: () => mountIndex++,
|
|
562
621
|
getPrecomputedByPrefix,
|
|
622
|
+
routerId,
|
|
563
623
|
};
|
|
564
624
|
|
|
565
|
-
|
|
566
|
-
|
|
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);
|
|
567
634
|
}
|
|
568
635
|
|
|
569
636
|
// Create findMatch with single-entry cache, bound to router state
|
|
@@ -613,6 +680,8 @@ export function createRouter<TEnv = any>(
|
|
|
613
680
|
params: Record<string, string>,
|
|
614
681
|
buildVars?: Record<string, any>,
|
|
615
682
|
isPassthroughRoute?: boolean,
|
|
683
|
+
buildEnv?: TEnv,
|
|
684
|
+
devMode?: boolean,
|
|
616
685
|
) {
|
|
617
686
|
return _matchForPrerender(
|
|
618
687
|
pathname,
|
|
@@ -620,6 +689,8 @@ export function createRouter<TEnv = any>(
|
|
|
620
689
|
prerenderDeps,
|
|
621
690
|
buildVars,
|
|
622
691
|
isPassthroughRoute,
|
|
692
|
+
buildEnv,
|
|
693
|
+
devMode,
|
|
623
694
|
);
|
|
624
695
|
}
|
|
625
696
|
|
|
@@ -627,12 +698,16 @@ export function createRouter<TEnv = any>(
|
|
|
627
698
|
handler: Function,
|
|
628
699
|
handlerId: string,
|
|
629
700
|
routeName?: string,
|
|
701
|
+
buildEnv?: TEnv,
|
|
702
|
+
devMode?: boolean,
|
|
630
703
|
) {
|
|
631
704
|
return _renderStaticSegment<TEnv>(
|
|
632
705
|
handler,
|
|
633
706
|
handlerId,
|
|
634
707
|
mergedRouteMap,
|
|
635
708
|
routeName,
|
|
709
|
+
buildEnv,
|
|
710
|
+
devMode,
|
|
636
711
|
);
|
|
637
712
|
}
|
|
638
713
|
|
|
@@ -645,6 +720,7 @@ export function createRouter<TEnv = any>(
|
|
|
645
720
|
findMatch,
|
|
646
721
|
findInterceptForRoute,
|
|
647
722
|
telemetry: telemetrySink,
|
|
723
|
+
cacheSignalEnabled,
|
|
648
724
|
});
|
|
649
725
|
|
|
650
726
|
const { match, matchPartial, matchError, previewMatch } = matchHandlers;
|
|
@@ -654,11 +730,18 @@ export function createRouter<TEnv = any>(
|
|
|
654
730
|
* The type system tracks accumulated routes through the builder chain
|
|
655
731
|
* Initial TRoutes is {} (empty) to avoid poisoning accumulated types with Record<string, string>
|
|
656
732
|
*/
|
|
657
|
-
const router:
|
|
733
|
+
const router: RangoInternal<TEnv, {}> = {
|
|
658
734
|
__brand: RSC_ROUTER_BRAND,
|
|
659
735
|
id: routerId,
|
|
736
|
+
basename,
|
|
737
|
+
|
|
738
|
+
routes(patternsOrBuilder: UrlPatterns<TEnv> | UrlBuilder<TEnv>): any {
|
|
739
|
+
// Wrap builder functions in urls() automatically
|
|
740
|
+
const urlPatterns: UrlPatterns<TEnv> =
|
|
741
|
+
typeof patternsOrBuilder === "function"
|
|
742
|
+
? (urls(patternsOrBuilder) as UrlPatterns<TEnv>)
|
|
743
|
+
: patternsOrBuilder;
|
|
660
744
|
|
|
661
|
-
routes(urlPatterns: UrlPatterns<TEnv>): any {
|
|
662
745
|
// Store reference for runtime manifest generation
|
|
663
746
|
storedUrlPatterns = urlPatterns;
|
|
664
747
|
const currentMountIndex = mountIndex++;
|
|
@@ -689,13 +772,13 @@ export function createRouter<TEnv = any>(
|
|
|
689
772
|
errorBoundary: [],
|
|
690
773
|
notFoundBoundary: [],
|
|
691
774
|
layout: [],
|
|
692
|
-
parallel:
|
|
775
|
+
parallel: {},
|
|
693
776
|
intercept: [],
|
|
694
777
|
loader: [],
|
|
695
778
|
};
|
|
696
779
|
|
|
697
780
|
let handlerResult: AllUseItems[] = [];
|
|
698
|
-
|
|
781
|
+
RangoContext.run(
|
|
699
782
|
{
|
|
700
783
|
manifest,
|
|
701
784
|
patterns: routePatterns,
|
|
@@ -706,6 +789,10 @@ export function createRouter<TEnv = any>(
|
|
|
706
789
|
counters: {},
|
|
707
790
|
mountIndex: currentMountIndex,
|
|
708
791
|
cacheProfiles: resolvedCacheProfiles,
|
|
792
|
+
// basename sets the initial URL prefix so all path() patterns
|
|
793
|
+
// are registered with the prefix (e.g. "/admin" + "/users" = "/admin/users").
|
|
794
|
+
// No namePrefix — route names stay unprefixed.
|
|
795
|
+
...(basename ? { urlPrefix: basename } : {}),
|
|
709
796
|
},
|
|
710
797
|
() => {
|
|
711
798
|
handlerResult = urlPatterns.handler() as AllUseItems[];
|
|
@@ -725,7 +812,7 @@ export function createRouter<TEnv = any>(
|
|
|
725
812
|
if (entry.type === "route" && entry.isPrerender) {
|
|
726
813
|
if (!prerenderRouteKeys) prerenderRouteKeys = new Set();
|
|
727
814
|
prerenderRouteKeys.add(name);
|
|
728
|
-
if (entry.
|
|
815
|
+
if (entry.isPassthrough === true) {
|
|
729
816
|
if (!passthroughRouteKeys) passthroughRouteKeys = new Set();
|
|
730
817
|
passthroughRouteKeys.add(name);
|
|
731
818
|
}
|
|
@@ -751,6 +838,7 @@ export function createRouter<TEnv = any>(
|
|
|
751
838
|
trailingSlash: trailingSlashConfig,
|
|
752
839
|
handler: urlPatterns.handler,
|
|
753
840
|
mountIndex: currentMountIndex,
|
|
841
|
+
routerId,
|
|
754
842
|
cacheProfiles: resolvedCacheProfiles,
|
|
755
843
|
...(prerenderRouteKeys ? { prerenderRouteKeys } : {}),
|
|
756
844
|
...(passthroughRouteKeys ? { passthroughRouteKeys } : {}),
|
|
@@ -770,6 +858,7 @@ export function createRouter<TEnv = any>(
|
|
|
770
858
|
trailingSlash: trailingSlashConfig,
|
|
771
859
|
handler: urlPatterns.handler,
|
|
772
860
|
mountIndex: currentMountIndex,
|
|
861
|
+
routerId,
|
|
773
862
|
cacheProfiles: resolvedCacheProfiles,
|
|
774
863
|
...(prerenderRouteKeys ? { prerenderRouteKeys } : {}),
|
|
775
864
|
...(passthroughRouteKeys ? { passthroughRouteKeys } : {}),
|
|
@@ -801,10 +890,13 @@ export function createRouter<TEnv = any>(
|
|
|
801
890
|
|
|
802
891
|
// Create placeholder RouteEntry for each lazy include
|
|
803
892
|
for (const lazyInclude of lazyIncludes) {
|
|
804
|
-
// Compute the full URL prefix (combining parent prefix if any)
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
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
|
+
);
|
|
808
900
|
|
|
809
901
|
const lazyEntry: RouteEntry<TEnv> & { _lazyPrefix?: string } = {
|
|
810
902
|
prefix: "",
|
|
@@ -813,6 +905,7 @@ export function createRouter<TEnv = any>(
|
|
|
813
905
|
trailingSlash: trailingSlashConfig,
|
|
814
906
|
handler: urlPatterns.handler,
|
|
815
907
|
mountIndex: mountIndex++,
|
|
908
|
+
routerId,
|
|
816
909
|
// Lazy evaluation fields
|
|
817
910
|
lazy: true,
|
|
818
911
|
lazyPatterns: lazyInclude.patterns,
|
|
@@ -851,8 +944,18 @@ export function createRouter<TEnv = any>(
|
|
|
851
944
|
patternOrMiddleware: string | MiddlewareFn<TEnv>,
|
|
852
945
|
middleware?: MiddlewareFn<TEnv>,
|
|
853
946
|
): any {
|
|
854
|
-
//
|
|
855
|
-
|
|
947
|
+
// Auto-prefix pattern with basename so router-level middleware
|
|
948
|
+
// patterns are router-relative (e.g. "/users/*" matches "/app/users/*").
|
|
949
|
+
if (basename && typeof patternOrMiddleware === "string") {
|
|
950
|
+
const pattern = patternOrMiddleware;
|
|
951
|
+
const prefixed =
|
|
952
|
+
pattern === "/*" || pattern === "*"
|
|
953
|
+
? `${basename}/*`
|
|
954
|
+
: `${basename}${pattern}`;
|
|
955
|
+
addMiddleware(prefixed, middleware, null);
|
|
956
|
+
} else {
|
|
957
|
+
addMiddleware(patternOrMiddleware, middleware, null);
|
|
958
|
+
}
|
|
856
959
|
return router;
|
|
857
960
|
},
|
|
858
961
|
|
|
@@ -888,13 +991,31 @@ export function createRouter<TEnv = any>(
|
|
|
888
991
|
// Expose prefetch cache settings
|
|
889
992
|
prefetchCacheControl,
|
|
890
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,
|
|
891
1000
|
|
|
892
1001
|
// Expose warmup enabled flag for handler and client
|
|
893
1002
|
warmupEnabled,
|
|
894
1003
|
|
|
1004
|
+
// Expose StrictMode flag for the initial-render payload metadata
|
|
1005
|
+
strictMode,
|
|
1006
|
+
|
|
895
1007
|
// Expose router-wide performance debugging for request-level metrics setup
|
|
896
1008
|
debugPerformance,
|
|
897
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
|
+
|
|
898
1019
|
// Expose debug manifest flag for handler
|
|
899
1020
|
allowDebugManifest: allowDebugManifestOption,
|
|
900
1021
|
|
|
@@ -953,6 +1074,16 @@ export function createRouter<TEnv = any>(
|
|
|
953
1074
|
// Expose source file for per-router type generation
|
|
954
1075
|
__sourceFile,
|
|
955
1076
|
|
|
1077
|
+
// Expose basename for runtime manifest generation
|
|
1078
|
+
__basename: basename,
|
|
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
|
+
|
|
956
1087
|
// RSC request handler (lazily created on first call)
|
|
957
1088
|
fetch: (() => {
|
|
958
1089
|
// Handler is created on first call and reused
|
|
@@ -970,8 +1101,10 @@ export function createRouter<TEnv = any>(
|
|
|
970
1101
|
if (!handler) {
|
|
971
1102
|
// Lazy import deferred to first request to avoid dev mode issues
|
|
972
1103
|
const { createRSCHandler } = await import("./rsc/handler.js");
|
|
973
|
-
// Cast:
|
|
974
|
-
//
|
|
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).)
|
|
975
1108
|
handler = createRSCHandler({
|
|
976
1109
|
router: router as any,
|
|
977
1110
|
cache,
|
|
@@ -986,6 +1119,10 @@ export function createRouter<TEnv = any>(
|
|
|
986
1119
|
};
|
|
987
1120
|
})(),
|
|
988
1121
|
|
|
1122
|
+
// Low-level route matching for request classification
|
|
1123
|
+
findMatch: (pathname: string, metricsStore?: any) =>
|
|
1124
|
+
findMatch(pathname, metricsStore),
|
|
1125
|
+
|
|
989
1126
|
// Debug utility for manifest inspection
|
|
990
1127
|
debugManifest: () => buildDebugManifest<TEnv>(routesEntries),
|
|
991
1128
|
};
|
|
@@ -994,8 +1131,10 @@ export function createRouter<TEnv = any>(
|
|
|
994
1131
|
RouterRegistry.set(routerId, router);
|
|
995
1132
|
|
|
996
1133
|
// If urls option was provided, auto-register them
|
|
997
|
-
if (urlsOption) {
|
|
998
|
-
return router.routes(urlsOption) as
|
|
1134
|
+
if (typeof urlsOption === "function") {
|
|
1135
|
+
return router.routes(urlsOption) as Rango<TEnv, {}>;
|
|
1136
|
+
} else if (urlsOption) {
|
|
1137
|
+
return router.routes(urlsOption) as Rango<TEnv, {}>;
|
|
999
1138
|
}
|
|
1000
1139
|
|
|
1001
1140
|
return router;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Full (initial-load / document) RSC payload builder.
|
|
3
|
+
*
|
|
4
|
+
* Extracted from rsc-rendering.ts so both the foreground render AND the PPR
|
|
5
|
+
* background shell capture (shell-capture.ts) build the SAME payload shape over
|
|
6
|
+
* their own handle store. `resume` requires the captured tree to match the served
|
|
7
|
+
* tree; building an identical payload over the same replayed segments is what
|
|
8
|
+
* makes that hold. Keep this byte-identical to the normal full-render path.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import type { MatchResult } from "../types.js";
|
|
12
|
+
import type { RscPayload } from "./types.js";
|
|
13
|
+
import type { HandlerContext } from "./handler-context.js";
|
|
14
|
+
import type { RequestContext } from "../server/request-context.js";
|
|
15
|
+
import type { HandleStore } from "../server/handle-store.js";
|
|
16
|
+
import { gateTransitions } from "./transition-gate.js";
|
|
17
|
+
import { resolvedHandleStream } from "../handles/deferred-resolution.js";
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Build the metadata payload for a full (non-partial) document render.
|
|
21
|
+
*
|
|
22
|
+
* @param handleStore - the store whose resolved handle stream feeds the payload;
|
|
23
|
+
* the foreground passes reqCtx's store, the background capture passes its fresh
|
|
24
|
+
* derived-context store.
|
|
25
|
+
*/
|
|
26
|
+
export function buildFullPayload(
|
|
27
|
+
m: MatchResult,
|
|
28
|
+
// env is opaque here (the payload never reads it); `any` avoids the invariance
|
|
29
|
+
// friction of HandlerContext<TEnv> vs the ambient RequestContext env at the two
|
|
30
|
+
// call sites (foreground render + background capture).
|
|
31
|
+
ctx: HandlerContext<any>,
|
|
32
|
+
url: URL,
|
|
33
|
+
reqCtx: RequestContext<any>,
|
|
34
|
+
handleStore: HandleStore,
|
|
35
|
+
): RscPayload {
|
|
36
|
+
return {
|
|
37
|
+
metadata: {
|
|
38
|
+
pathname: url.pathname,
|
|
39
|
+
routerId: ctx.router.id,
|
|
40
|
+
basename: ctx.router.basename,
|
|
41
|
+
segments: gateTransitions(m.segments, reqCtx, ctx.router.onError),
|
|
42
|
+
matched: m.matched,
|
|
43
|
+
diff: m.diff,
|
|
44
|
+
resolvedIds: m.resolvedIds,
|
|
45
|
+
params: m.params,
|
|
46
|
+
isPartial: false,
|
|
47
|
+
rootLayout: ctx.router.rootLayout,
|
|
48
|
+
// Full render: resolve deferred handle values server-side so SSR markup and
|
|
49
|
+
// the first sync useHandle read see resolved values. Partial payloads
|
|
50
|
+
// (rsc-rendering.ts) keep streaming (handleStore.stream()).
|
|
51
|
+
handles: resolvedHandleStream(handleStore),
|
|
52
|
+
version: ctx.version,
|
|
53
|
+
prefetchCacheTTL: ctx.router.prefetchCacheTTL,
|
|
54
|
+
prefetchCacheSize: ctx.router.prefetchCacheSize,
|
|
55
|
+
prefetchConcurrency: ctx.router.prefetchConcurrency,
|
|
56
|
+
stateCookieName: ctx.router.resolvedStateCookieName,
|
|
57
|
+
themeConfig: ctx.router.themeConfig,
|
|
58
|
+
// Carry warmupEnabled on the initial full-render payload so the client
|
|
59
|
+
// respects warmup:false from first load. The 404 and PE payloads already
|
|
60
|
+
// include it; without it here warmup could never be disabled on the
|
|
61
|
+
// normal full-load path (partial payloads omit it by design).
|
|
62
|
+
warmupEnabled: ctx.router.warmupEnabled,
|
|
63
|
+
// Carry strictMode on the initial full-render payload so the browser
|
|
64
|
+
// entry knows whether to wrap hydration in React.StrictMode. Partial
|
|
65
|
+
// (navigation) payloads omit it by design; StrictMode is decided once.
|
|
66
|
+
strictMode: ctx.router.strictMode,
|
|
67
|
+
initialTheme: reqCtx.theme,
|
|
68
|
+
},
|
|
69
|
+
};
|
|
70
|
+
}
|